GoalChain adalah kerangka kerja sederhana namun efektif untuk memungkinkan alur percakapan yang berorientasi pada tujuan untuk interaksi manusia-LLM dan LLM-LLM.
pip install goalchain
Mari kita impor kelas Field
, ValidationError
, Goal
dan GoalChain
, yang merupakan dasar alur percakapan.
from goalchain import Field , ValidationError , Goal , GoalChain
Dalam contoh ini kita akan membuat asisten AI yang tujuannya adalah mengumpulkan informasi dari pelanggan tentang pesanan produk yang diinginkan. Kami mendefinisikan informasi yang akan dikumpulkan menggunakan objek Field
dalam ProductOrderGoal
, yang merupakan turunan dari Goal
:
Kami juga mendefinisikan validator untuk kuantitas (setelah mengetikkan casting ke int). ValidationError
digunakan untuk meneruskan pesan kesalahan kembali ke percakapan. Pesan-pesan ini harus dapat dibaca manusia.
format_hint
adalah petunjuk tipe bahasa alami untuk keluaran mode JSON LLM.
def quantity_validator ( value ):
try :
value = int ( value )
except ( ValueError , TypeError ):
raise ValidationError ( "Quantity must be a valid number" )
if value <= 0 :
raise ValidationError ( "Quantity cannot be less than one" )
if value > 100 :
raise ValidationError ( "Quantity cannot be greater than 100" )
return value
class ProductOrderGoal ( Goal ):
product_name = Field ( "product to be ordered" , format_hint = "a string" )
customer_email = Field ( "customer email" , format_hint = "a string" )
quantity = Field ( "quantity of product" , format_hint = "an integer" , validator = quantity_validator )
Jika pelanggan berubah pikiran, mari buat kelas turunan Goal
lain yang disebut OrderCancelGoal
. Kami akan meminta alasan opsional atas pembatalan pesanan yang sedang berlangsung oleh pelanggan. Dengan menentukan bahwa bidang tersebut adalah "(opsional)" dalam deskripsi, LLM akan mengetahui bahwa hal tersebut tidak diperlukan untuk mencapai tujuan.
class OrderCancelGoal ( Goal ):
reason = Field ( "reason for order cancellation (optional)" , format_hint = "a string" )
Perhatikan bahwa nama objek bidang, seperti product_name
diteruskan langsung ke prompt LLM, sehingga merupakan bagian dari tugas rekayasa prompt, seperti halnya setiap string lainnya.
Pada dasarnya kelas yang kami definisikan seperti formulir yang harus diisi oleh pelanggan, namun tidak memiliki instruksi. Mari tambahkan itu dengan membuat instance kelas sebagai objek.
product_order_goal = ProductOrderGoal (
label = "product_order" ,
goal = "to obtain information on an order to be made" ,
opener = "I see you are trying to order a product, how can I help you?" ,
out_of_scope = "Ask the user to contact sales team at [email protected]"
)
order_cancel_goal = OrderCancelGoal (
label = "cancel_current_order" ,
goal = "to obtain the reason for the cancellation" ,
opener = "I see you are trying to cancel the current order, how can I help you?" ,
out_of_scope = "Ask the user to contact the support team at [email protected]" ,
confirm = False
)
Kami mendefinisikan
opener
default - sesuatu yang akan digunakan asisten AI tanpa masukan sebelumnya, Bendera confirm
menentukan apakah asisten AI akan meminta konfirmasi setelah semua informasi yang diperlukan ditentukan menggunakan objek Field
. Ini adalah True
secara default. Kami tidak memerlukan konfirmasi untuk tujuan pembatalan pesanan, karena itu sendiri sudah menjadi semacam konfirmasi.
Selanjutnya kita perlu menghubungkan tujuan-tujuan tersebut bersama-sama.
product_order_goal . connect ( goal = order_cancel_goal ,
user_goal = "to cancel the current order" ,
hand_over = True ,
keep_messages = True )
user_goal
adalah pernyataan "ke..." lainnya. Tanpa hand_over=True
agen AI akan membalas dengan opener
kalengan. Menyetelnya ke True
memastikan percakapan mengalir dengan lancar. Terkadang Anda mungkin menginginkan tanggapan terekam, terkadang tidak.
keep_messages=True
berarti order_cancel_goal
akan menerima riwayat lengkap percakapan dengan product_order_goal
, jika tidak maka akan dihapus. Sekali lagi, terkadang diperlukan penghapusan riwayat percakapan, seperti saat menyimulasikan kepribadian AI yang berbeda.
Mari kita pertimbangkan juga kemungkinan pelanggan yang benar-benar ragu-ragu. Kita juga harus memberi mereka pilihan untuk "membatalkan pembatalan".
order_cancel_goal . connect ( goal = product_order_goal ,
user_goal = "to continue with the order anyway" ,
hand_over = True ,
keep_messages = True )
Pada titik tertentu Anda mungkin bertanya-tanya apakah Anda dapat membuat tujuan tanpa objek Field
apa pun. Anda bisa! Sasaran tersebut adalah sasaran perutean yang hanya ditentukan berdasarkan koneksi yang dimilikinya. Hal ini berguna misalnya dalam sistem menu pesan suara.
Anda mungkin juga penasaran apakah Anda dapat menghubungkan suatu tujuan dengan tujuan itu sendiri. Anda bisa! Ini berguna misalnya saat menggunakan confirm=False
dengan objek Pewarisan Goal
, yang mengharuskan Anda memasukkan beberapa jenis masukan pengguna secara berurutan.
Anda juga dapat menghubungkan secara berantai, misalnya goal.connect(...).connect(...).connect(...)
Terakhir, mari gunakan GoalChain
untuk menetapkan tujuan awal dan menguji asisten penjualan AI kami!
goal_chain = GoalChain ( product_order_goal )
Perhatikan bahwa setiap sasaran dapat menggunakan API LLM terpisah seperti yang diaktifkan oleh LiteLLM, dan jika Anda telah menetapkan variabel lingkungan yang diperlukan, Anda dapat menggunakan model apa pun dari penyedia model yang didukung.
Model defaultnya adalah "gpt-4-1106-preview"
, yaitu:
product_order_goal = ProductOrderGoal (...
model = "gpt-4-1106-preview" ,
json_model = "gpt-4-1106-preview"
)
Anda juga dapat meneruskan parameter umum LiteLLM menggunakan params
, misalnya:
product_order_goal = ProductOrderGoal (...
model = "gpt-4-1106-preview" ,
json_model = "gpt-4-1106-preview" ,
params = { "temperature" : 1.5 , "max_tokens" : 10 }
)
Anda juga dapat menggunakan params
untuk memanggil model lokal menggunakan VLLM.
Saat menggunakan model "gpt-4-1106-preview"
default, ingatlah untuk menyetel variabel lingkungan OPENAI_API_KEY
.
import os
os . environ [ "OPENAI_API_KEY" ] = "sk-ABC..."
Catatan: Kode sejauh ini tersedia sebagai intinya. Tempelkan ke dalam notebook Jupyter, didahului dengan !pip install goalchain
untuk memulai contoh langsung di bawah.
Biasanya penggunalah yang meminta agen AI terlebih dahulu, namun jika tidak demikian, kita memanggil get_response
tanpa argumen apa pun, atau menggunakan None
sebagai argumen:
goal_chain . get_response ()
{'type': 'message',
'content': 'Great choice! Could you please provide me with your email address to proceed with the order?',
'goal': <__main__.ProductOrderGoal at 0x7f8c8b687110>}
GoalChain mengembalikan dict
yang berisi jenis respons (baik message
atau data
), konten respons (saat ini hanya respons terekam kami) dan objek pewarisan Goal
saat ini.
Mari tanyakan kepada asisten AI kami tentang kemungkinan pembelian.
goal_chain . get_response ( "Hi, I'd like to buy a vacuum cleaner" )
{'type': 'message',
'content': 'Great! Could you please provide your email address so we can send the confirmation of your order?',
'goal': <__main__.ProductOrderGoal at 0x7ff0fb283090>}
Asisten AI sedang berupaya mencapai tujuannya saat ini, dan mengumpulkan informasi yang diperlukan untuk suatu pesanan.
goal_chain . get_response ( "Sure, it is [email protected]" )
{'type': 'message',
'content': 'Thank you, John. Which model of vacuum cleaner would you like to order?',
'goal': <__main__.ProductOrderGoal at 0x7ff0fb283090>}
goal_chain . get_response ( "The 2000XL model" )
{'type': 'message',
'content': 'How many of the 2000XL model would you like to order?',
'goal': <__main__.ProductOrderGoal at 0x7ff0fb283090>}
Mari kita uji apakah asisten AI kita dapat menangani pembatalan pesanan saat ini.
goal_chain . get_response ( "Actually I changed my mind, cancel this order" )
{'type': 'message',
'content': 'Of course, I can assist with that. Could you please tell me the reason for the cancellation?',
'goal': <__main__.OrderCancelGoal at 0x7ff0fb275650>}
Itu berhasil. Perhatikan bahwa sasaran yang dikembalikan sekarang bertipe OrderCancelGoal
. Kami telah bertukar tujuan. Mari kita uji juga apakah kita dapat beralih kembali.
goal_chain . get_response ( "Actually, yeah, I would like to buy the vacuum cleaner" )
{'type': 'message',
'content': 'Understood. How many of the 2000XL model would you like to order?',
'goal': <__main__.ProductOrderGoal at 0x7ff0fb283090>}
Kami kembali ke ProductOrderGoal
.
goal_chain . get_response ( "1 please" )
{'type': 'message',
'content': 'To confirm, you would like to order one 2000XL vacuum cleaner and the order will be sent to [email protected], is that correct?',
'goal': <__main__.ProductOrderGoal at 0x7ff0fb283090>}
Asisten AI mengonfirmasi pesanan kami. Jika kami tidak menyukai perilaku ini, kami akan menggunakan confirm=False
.
Mari kita lihat bagaimana asisten merespons kueri di luar cakupan.
goal_chain . get_response ( "Is it a good vacuum cleaner? What do you think?" )
{'type': 'message',
'content': "For product reviews and additional information, I recommend contacting our sales team at [email protected]. They can help with your inquiries. Meanwhile, can you please confirm if you'd like to proceed with the order for one 2000XL vacuum cleaner to [email protected]?",
'goal': <__main__.ProductOrderGoal at 0x7ff0fb283090>}
Asisten AI mengarahkan kami ke kotak masuk tim penjualan seperti yang ditentukan sebelumnya, dan mengulangi konfirmasinya.
Tapi mari kita lempar bola melengkung...
goal_chain . get_response ( "Ok, I'd actually like to make that an order of 500" )
{'type': 'message',
'content': "Just to clarify, you'd like to order 500 units of the 2000XL vacuum cleaner, with the order confirmation sent to [email protected]. Is that correct?",
'goal': <__main__.ProductOrderGoal at 0x7ff0fb283090>}
goal_chain . get_response ( "Yes" )
{'type': 'message',
'content': 'I’m sorry, but I need to inform you that the quantity cannot be greater than 100 for an order. If you would like to proceed with an order within this limit, please let me know.',
'goal': <__main__.ProductOrderGoal at 0x7ff0fb283090>}
Validator yang kami gunakan telah memberikan informasi yang cukup kepada asisten AI untuk menjelaskan mengapa ia tidak dapat memproses kuantitas ini melalui pesan ValidationError
.
Perhatikan bahwa GoalChain hanya memvalidasi input setelah Goal
selesai untuk alasan efisiensi dan kinerja token. Jika Anda ingin memvalidasi input seiring berjalannya waktu, Anda memiliki dua opsi:
Gunakan Goal
dengan hanya satu Field
, dan confirm=False
. Rangkai sasaran-sasaran ini alih-alih menggunakan beberapa bidang dalam satu Goal
.
Gunakan soft-prompt, misalnya quantity = Field("quantity of product (no more than 100)", format_hint="an integer")
. Pendekatan ini tidak mudah dilakukan, jadi tetap disarankan untuk menggunakan validator. Namun, pengguna akan segera menerima umpan balik.
Ayo selesaikan pesanannya.
goal_chain . get_response ( "Alright, I'll guess I'll just go with 1" )
{'type': 'message',
'content': 'To confirm, you would like to order one 2000XL vacuum cleaner and the order will be sent to [email protected], is that correct?',
'goal': <__main__.ProductOrderGoal at 0x7ff0fb283090>}
goal_chain . get_response ( "That's right" )
{'type': 'data',
'content': {'customer_email': '[email protected]',
'product_name': '2000XL',
'quantity': 1},
'goal': <__main__.ProductOrderGoal at 0x7ff0fb283090>}
Konten yang dikembalikan adalah kamus yang diurai dari output mode JSON LLM. Kuncinya adalah nama instance bidang kami. Kami sekarang dapat menggunakan data tersebut untuk melakukan beberapa tindakan, seperti memproses pesanan penyedot debu 2000XL hipotetis kami.
Perhatikan bahwa pada kenyataannya, jika Anda sedang membangun sistem seperti itu, Anda perlu membuat sasaran pencarian produk khusus agar tidak mengizinkan nama produk yang sewenang-wenang atau tidak berarti.
Ayo kirimkan konfirmasi kita bahwa pesanan telah diproses melalui simulate_response
. Kami juga akan menggunakan rephrase = True
untuk menyusun ulang output, yang akan tampak lebih alami jika pelanggan sering berinteraksi dengan sasaran.
goal_chain . simulate_response ( f"Thank you for ordering from Acme. Your order will be dispatched in the next 1-3 business days." , rephrase = True )
{'type': 'message',
'content': 'We appreciate your purchase with Acme! Rest assured, your order will be on its way within the next 1 to 3 business days.',
'goal': <__main__.ProductOrderGoal at 0x7ff0fb283090>}
Pada titik ini kita dapat mengakhiri sesi atau menyambung kembali ke menu atau tujuan perutean untuk masukan lebih lanjut.
Jika Anda ingin menyesuaikan atau berkontribusi pada GoalChain, atau melaporkan masalah apa pun, kunjungi halaman GitHub.