GoalChain 是一个简单但有效的框架,用于为人类与法学硕士以及法学硕士与法学硕士之间的交互提供以目标为导向的对话流程。
pip install goalchain
让我们导入Field
、 ValidationError
、 Goal
和GoalChain
类,它们是对话流的基础。
from goalchain import Field , ValidationError , Goal , GoalChain
在此示例中,我们将创建一个人工智能助手,其目标是从客户那里收集有关其所需产品订单的信息。我们使用ProductOrderGoal
中的Field
对象定义要收集的信息,该对象是Goal
的子级:
我们还为数量定义了一个验证器(在类型转换为 int 之后)。 ValidationError
用于将错误消息传递回对话。这些消息应该是人类可读的。
format_hint
是LLM的JSON模式输出的自然语言类型提示。
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 )
如果客户改变主意,让我们创建另一个名为OrderCancelGoal
的Goal
子类。我们将要求客户提供取消正在进行的订单的可选原因。通过在描述中指定该字段为“(可选)”,法学硕士将知道实现目标不是必需的。
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
标志确定 AI 助手在拥有使用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
是另一个“to ...”语句。如果没有hand_over=True
AI 代理将使用罐装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
设定初始目标并测试我们的AI销售助手!
goal_chain = GoalChain ( product_order_goal )
请注意,每个目标都可以使用由 LiteLLM 启用的单独的 LLM API,并且如果您设置了所需的环境变量,则可以使用受支持的模型提供程序中的任何模型。
默认型号为"gpt-4-1106-preview"
,即:
product_order_goal = ProductOrderGoal (...
model = "gpt-4-1106-preview" ,
json_model = "gpt-4-1106-preview"
)
您还可以使用params
传递 LiteLLM 通用参数,例如:
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
以开始使用下面的实时示例。
通常是用户首先提示 AI 代理,但如果不是这种情况,我们调用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>}
让我们测试一下我们的AI助手是否可以处理当前订单的取消。
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>}
AI助手确认了我们的订单。如果我们不喜欢这种行为,我们将使用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>}
我们使用的验证器已向 AI 助手提供了足够的信息,以证明其无法通过ValidationError
消息处理此数量的原因。
请注意,出于代币效率和性能原因,GoalChain 仅在Goal
完成后才验证输入。如果您想随时验证输入,您有两种选择:
使用只有一个Field
的Goal
,并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>}
返回的内容是从LLM的JSON模式的输出解析出来的字典。键是我们的字段实例名称。现在,我们可以使用这些数据执行某种操作,例如处理假设的 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 或为 GoalChain 做出贡献,或报告任何问题,请访问 GitHub 页面。