我使用Flask和Langchain作为QA微服务,根据前端(react)和后端(express)的一些参数,它会调用:
- 一个简单的问题服务(没有索引,没有代理)
- 索引问题服务(ChromaDB索引,无代理)
- 代理服务(无索引,ZapierNLA代理)
我们使用Websockets流式传输响应(如果我们不想流式传输答案,我们也有一个REST API替代方案),下面是我这边的自定义回调处理程序的实现:
class CustomHandler(StreamingStdOutCallbackHandler):
user_id = None
def __init__(self, user_id):
self.user_id = user_id
def on_llm_new_token(self, token: str, **kwargs):
emit('result', {'message_id': self.user_id, 'data': token})
if token == '':
emit('result', {'message_id': self.user_id, 'data': 'STREAM_END'})
字符串
这是我们如何将其添加到聊天模型中:
handler = CustomHandler(user_id)
llm = ChatOpenAI(model_name=model_name, temperature=temperature, streaming=streaming,
callback_manager=CallbackManager([handler]), verbose=True)
# Somehow, this does not work if verbose=False or if we ommit the verbose
型
对于前两个服务,流按预期工作,但代理服务流式传输他的整个思维过程,如下所示:
I need to use the Gmail: Create Draft tool to create a draft email with the ten greek god names listed in the body. Action: Gmail: Create Draft Action Input: Body: "1. Zeus\n2. Hera\n3. Poseidon\n4. Demeter\n5. Athena\n6. Apollo\n7. Artemis\n8. Ares\n9. Aphrodite\n10. Hephaestus", To: my own email address, Subject: "List of Ten Greek Gods"The draft email has been created successfully. Action: None Action Input: NoneI need to use the Gmail: Send Email tool to send the draft email I just created. Action: Gmail: Send Email Action Input: Body: "1. Zeus\n2. Hera\n3. Poseidon\n4. Demeter\n5. Athena\n6. Apollo\n7. Artemis\n8. Ares\n9. Aphrodite\n10. Hephaestus", To: my own email address, Subject: "List of Ten Greek Gods"I need to go back to using the Gmail: Create Draft tool and add in the parameter for "To" to send the email to myself. Action: Gmail: Create Draft Action Input: Body: "1. Zeus\n2. Hera\n3. Poseidon\n4. Demeter\n5. Athena\n6. Apollo\n7. Artemis\n8. Ares\n9. Aphrodite\n10. Hephaestus", To: my own email address, Subject: "List of Ten Greek Gods"The draft email has been created and I can now send it to myself by using Gmail: Send Draft tool. Action: Gmail: Send Draft Action Input: Thread Id: "188e72dae1b0f2b7"I need to go back to using the Gmail: Create Draft tool and add in the parameter for "To" to send the email to myself. After that, I should use Gmail: Send Message tool to send the email. Action: Gmail: Create Draft Action Input: Body: "1. Zeus\n2. Hera\n3. Poseidon\n4. Demeter\n5. Athena\n6. Apollo\n7. Artemis\n8. Ares\n9. Aphrodite\n10. Hephaestus", To: my own email address, Subject: "List of Ten Greek Gods"Now that the draft email has been created with the correct parameters, I can use the Gmail: Send Message tool to send the email to myself. Action: Gmail: Send Message Action Input: Id: "188e72dec0ec5524"I need to review the list of available tools and find one that can send an email given a draft message Id. Action: None Action Input: NoneI know that the Gmail API has a function to send draft messages using the draft Id, so I can use a code snippet to accomplish this. Action: Code Execution Action Input: Use the Gmail API to send the email draft with Id "188e72dec0ec5524" to my own email addressI will need to use some external method or language to execute the code to send the email using the Gmail API. I can use a programming language like Python or a tool like Postman. Action: Python Code Execution Action Input: Use the Gmail API to send the email draft with Id "188e72dec0ec5524" to my own email addressI can use a third-party integration tool like Zapier or IFTTT to automate the process of sending the email draft from Gmail to my own email address. Action: Zapier Integration Action Input: Set up a Zapier integration to automatically send the email draft with Id "188e72dec0ec5524" to my own email addressSince I am not able to use any of the tools provided to directly send the email draft, I will have to manually copy and paste the contents of the draft and email it to myself. Final Answer: Manually copy and paste the contents of the draft and email it to myself.
型
这是调用ZapierNLA代理的函数:
def simple_order(human_message: str, system_message: str, model_name: str = 'gpt-3.5-turbo', streaming: bool = False, temperature: float = 0.6, user_id: str = None, history=None):
if history is None:
history = []
handler = CustomHandler(user_id)
llm = ChatOpenAI(model_name=model_name, temperature=temperature)
if streaming:
llm = ChatOpenAI(model_name=model_name, temperature=temperature, streaming=streaming, callback_manager=CallbackManager([handler]), verbose=True)
messages = generate_messages(history=history, system_message=system_message, human_message=human_message)
zapier = ZapierNLAWrapper()
toolkit = ZapierToolkit.from_zapier_nla_wrapper(zapier)
agent = initialize_agent(tools=toolkit.get_tools(), llm=llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION)
return agent.run(messages)
型
我知道verbose=True
是导致这一切的原因。也许是因为我采用了类似的方法来实现一个简单的问题,我可能需要调整一些东西。
我已经尝试在CustomHandler
类中将ignore_agent
定义为True
,但没有任何变化。
我已经尝试删除verbose
,但没有发出任何东西,在前面,它只是显示一个“输入”的动画从服务
我曾尝试将verbose
参数放入initialize_agent
调用中,但它给出的结果与我前面刚刚提到的结果相同
如何仅流式传输座席的Final Answer
?
2条答案
按热度按时间cuxqih211#
看来你的方向是对的您可以尝试将
CustomHandler
更改为仅在看到指示“最终答案:”的连续令牌后才发出。也许您可以在看到这些令牌后在CustomHandler
示例上设置一个标志,并在每个新的LLM请求上重置该标志。我不确定这是否是最好的方法,但它应该有效。rdlzhqv92#
你可以做这样的事。我使用FinalStreamingStdOutCallbackHandler作为参考创建了这个
个字符