يعد GoalChain إطارًا بسيطًا ولكنه فعال لتمكين تدفقات المحادثة الموجهة نحو الهدف للتفاعل بين الإنسان وLLM وLLM-LLM.
pip install goalchain
لنقم باستيراد فئات Field
و ValidationError
و Goal
و GoalChain
، والتي تمثل الأساس لتدفق المحادثة.
from goalchain import Field , ValidationError , Goal , GoalChain
في هذا المثال، سنقوم بإنشاء مساعد يعمل بالذكاء الاصطناعي هدفه جمع معلومات من العميل حول طلب المنتج المطلوب. نحن نحدد المعلومات التي سيتم جمعها باستخدام كائنات Field
ضمن ProductOrderGoal
، وهي تابعة Goal
:
نحدد أيضًا أداة التحقق من الكمية (بعد إرسال النوع إلى int). يتم استخدام ValidationError
لتمرير رسائل الخطأ مرة أخرى إلى المحادثة. يجب أن تكون هذه الرسائل قابلة للقراءة من قبل الإنسان.
format_hint
هو تلميح لنوع اللغة الطبيعية لمخرجات وضع 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 )
في حالة قيام العميل بتغيير رأيه، فلنقم بإنشاء فئة فرعية أخرى Goal
تسمى OrderCancelGoal
. سنطلب سببًا اختياريًا لإلغاء العميل للطلب المستمر. من خلال تحديد أن الحقل "(اختياري)" في الوصف، سيعرف LLM أنه ليس ضروريًا لتحقيق الهدف.
class OrderCancelGoal ( Goal ):
reason = Field ( "reason for order cancellation (optional)" , format_hint = "a string" )
لاحظ أن أسماء كائنات الحقل، مثل product_name
يتم تمريرها مباشرة إلى موجه LLM، وبالتالي فهي جزء من مهمة هندسة الموجه، كما هو الحال مع كل سلسلة أخرى.
في الأساس، تشبه الفئات التي حددناها النماذج التي يجب أن يملأها العميل، ولكنها تفتقر إلى التعليمات. دعونا نضيف تلك عن طريق إنشاء مثيل للفئات ككائنات.
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
)
نحن نحدد
opener
افتراضية - شيء سيستخدمه مساعد الذكاء الاصطناعي بدون أي إدخال مسبق، تحدد علامة confirm
ما إذا كان مساعد الذكاء الاصطناعي سيطلب التأكيد بمجرد حصوله على جميع المعلومات المطلوبة المحددة باستخدام كائنات Field
. وهو True
افتراضيا. لا نحتاج إلى تأكيد لهدف إلغاء الطلب، لأنه في حد ذاته يعد بالفعل نوعًا من التأكيد.
بعد ذلك نحتاج إلى ربط الأهداف معًا.
product_order_goal . connect ( goal = order_cancel_goal ,
user_goal = "to cancel the current order" ,
hand_over = True ,
keep_messages = True )
يعد user_goal
عبارة أخرى عن عبارة "إلى ...". بدون hand_over=True
، سيرد وكيل الذكاء الاصطناعي باستخدام opener
المعلبة. يؤدي ضبطه على True
إلى ضمان تدفق المحادثة بسلاسة. في بعض الأحيان قد ترغب في الحصول على رد جاهز، وفي أحيان أخرى لا.
keep_messages=True
يعني أن order_cancel_goal
سيتلقى السجل الكامل للمحادثة مع product_order_goal
، وإلا فسيتم مسحه. مرة أخرى، في بعض الأحيان قد يكون من المرغوب فيه مسح سجل المحادثة، كما هو الحال عند محاكاة شخصيات الذكاء الاصطناعي المختلفة.
دعونا نفكر أيضًا في إمكانية وجود عميل غير حاسم حقًا. يجب علينا أيضًا أن نمنحهم خيار "إلغاء الإلغاء".
order_cancel_goal . connect ( goal = product_order_goal ,
user_goal = "to continue with the order anyway" ,
hand_over = True ,
keep_messages = True )
في مرحلة ما ربما تساءلت عما إذا كان بإمكانك تحقيق هدف دون أي كائنات Field
. أنت تستطيع! مثل هذا الهدف هو هدف توجيه يتم تحديده فقط من خلال الاتصالات التي يمتلكها. وهذا مفيد على سبيل المثال في نظام قائمة البريد الصوتي.
قد يكون لديك فضول أيضًا لمعرفة ما إذا كان بإمكانك ربط الهدف بنفسه. أنت تستطيع! يكون هذا مفيدًا على سبيل المثال عند استخدام confirm=False
مع كائن وراثة Goal
، حيث تطلب إدخال مستخدم متسلسل من بعض التنوع.
يمكنك أيضًا ربط الروابط، على سبيل المثال goal.connect(...).connect(...).connect(...)
أخيرًا، دعنا نستخدم GoalChain
لتحديد الهدف الأولي واختبار مساعد مبيعات الذكاء الاصطناعي لدينا!
goal_chain = GoalChain ( product_order_goal )
لاحظ أن كل هدف يمكن أن يستخدم واجهة برمجة تطبيقات LLM منفصلة كما تم تمكينها بواسطة LiteLLM، وإذا كان لديك مجموعة متغيرات البيئة المطلوبة، فيمكنك استخدام أي نموذج من موفري النماذج المدعومة.
النموذج الافتراضي هو "gpt-4-1106-preview"
، وهو:
product_order_goal = ProductOrderGoal (...
model = "gpt-4-1106-preview" ,
json_model = "gpt-4-1106-preview"
)
يمكنك أيضًا تمرير معلمات LiteLLM الشائعة باستخدام params
، على سبيل المثال:
product_order_goal = ProductOrderGoal (...
model = "gpt-4-1106-preview" ,
json_model = "gpt-4-1106-preview" ,
params = { "temperature" : 1.5 , "max_tokens" : 10 }
)
يمكنك أيضًا استخدام params
لاستدعاء النماذج المحلية باستخدام VLLM.
عند استخدام النموذج الافتراضي "gpt-4-1106-preview"
، تذكر تعيين متغير البيئة OPENAI_API_KEY
.
import os
os . environ [ "OPENAI_API_KEY" ] = "sk-ABC..."
ملحوظة: الكود متاح حتى الآن كجوهر. الصقها في دفتر ملاحظات Jupyter، مسبوقًا بـ !pip install goalchain
للبدء بالمثال المباشر أدناه.
عادةً ما يكون المستخدم هو الذي يطالب وكيل الذكاء الاصطناعي أولاً، ولكن إذا لم يكن الأمر كذلك، فإننا نستدعي get_response
بدون أي وسيطات، أو نستخدم None
كوسيطة:
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 بإرجاع dict
يحتوي على نوع الاستجابة (إما message
أو data
)، ومحتوى الاستجابة (في الوقت الحالي مجرد استجابتنا الجاهزة) والكائن الحالي الذي يرث Goal
.
دعنا نستفسر عن مساعد الذكاء الاصطناعي الخاص بنا بشأن عملية شراء محتملة.
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>}
يعمل مساعد الذكاء الاصطناعي على تحقيق هدفه الحالي، وجمع المعلومات المطلوبة للطلب.
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>}
دعونا نختبر ما إذا كان مساعد الذكاء الاصطناعي لدينا يمكنه التعامل مع إلغاء الطلب الحالي.
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>}
لقد نجحت. لاحظ أن الهدف الذي تم إرجاعه أصبح الآن من النوع OrderCancelGoal
. لقد قمنا بتبديل الأهداف. دعونا أيضًا نختبر ما إذا كان بإمكاننا العودة مرة أخرى.
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>}
لقد عدنا إلى 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>}
يؤكد مساعد الذكاء الاصطناعي طلبنا. إذا لم يعجبنا هذا السلوك فسنستخدم confirm=False
.
دعونا نرى كيف يستجيب المساعد لاستعلام خارج النطاق.
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>}
يقوم مساعد الذكاء الاصطناعي بإعادة توجيهنا إلى البريد الوارد لفريق المبيعات كما هو محدد سابقًا، ويعيد تكرار التأكيد.
لكن دعونا نرمي الكرة المنحنية...
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>}
قدم المدقق الذي نستخدمه معلومات كافية لمساعد الذكاء الاصطناعي لتبرير سبب عدم تمكنه من معالجة هذه الكمية عبر رسالة ValidationError
.
لاحظ أن GoalChain يتحقق فقط من صحة المدخلات بمجرد اكتمال Goal
لأسباب تتعلق بكفاءة الرمز المميز والأداء. إذا كنت ترغب في التحقق من صحة المدخلات أثناء التقدم، فلديك خياران:
استخدم Goal
Field
واحد فقط، وقم confirm=False
. قم بربط هذه الأهداف بدلاً من استخدام حقول متعددة في Goal
واحد.
استخدم مطالبة بسيطة، على سبيل المثال quantity = Field("quantity of product (no more than 100)", format_hint="an integer")
. هذا الأسلوب ليس مضمونًا، لذا يوصى باستخدام أداة التحقق من الصحة. ومع ذلك، سيتلقى المستخدم تعليقات فورية.
دعونا نكمل الطلب.
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>}
المحتوى الذي تم إرجاعه عبارة عن قاموس تم تحليله من إخراج وضع JSON الخاص بـ LLM. المفاتيح هي أسماء مثيلاتنا الميدانية. يمكننا الآن استخدام البيانات لتنفيذ نوع ما من الإجراءات، مثل معالجة ترتيب المكنسة الكهربائية الافتراضية 2000XL.
لاحظ أنه في الواقع، إذا كنت تقوم ببناء مثل هذا النظام، فستحتاج إلى تحديد هدف مخصص للبحث عن المنتج بحيث لا تسمح بأسماء منتجات عشوائية أو لا معنى لها.
دعنا نرسل تأكيدًا بأن الطلب قد تمت معالجته عبر simulate_response
. سنستخدم أيضًا rephrase = True
لإعادة صياغة المخرجات، والتي ستبدو أكثر طبيعية في حالة تفاعل العميل بشكل متكرر مع الهدف.
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>}
عند هذه النقطة قد ننهي الجلسة أو نعود إلى القائمة أو هدف التوجيه لمزيد من الإدخال.
إذا كنت ترغب في تخصيص GoalChain أو المساهمة فيه، أو الإبلاغ عن أي مشكلات، تفضل بزيارة صفحة GitHub.