
本教程旨在解决Chainlit应用中与LangChain集成时常见的`UserSession.set() missing 1 required positional argument: ‘value’`错误。文章将深入解释`cl.user_session.set()`用于存储数据与`cl.user_session.get()`用于检索数据之间的关键区别,并提供一个直接的解决方案,确保您的LangChain链在整个聊天会话中被正确访问和复用。
1. 理解问题:Chainlit用户会话的误用
在构建基于Chainlit和LangChain的交互式AI应用时,通常需要在用户会话开始时(即@cl.on_chat_start装饰器下的函数)初始化一些计算成本较高的对象,例如大型语言模型(LLM)、嵌入模型、向量存储或复杂的LangChain链。这些对象被初始化后,需要被存储起来,以便在用户后续的每次消息交互中(即@cl.on_message装饰器下的函数)复用,从而避免重复加载和初始化,提高效率。
Chainlit提供了cl.user_session这一机制来实现会话级别的状态管理。然而,一个常见的错误是混淆了cl.user_session的存储(set)和检索(get)操作,导致在尝试获取已存储对象时,错误地调用了set()方法而未提供完整的参数,进而引发UserSession.set() missing 1 required positional argument: ‘value’这样的错误信息。
在原始代码中,用户还曾遇到与context变量相关的ValidationError。虽然LangChain的RetrievalQA链(特别是chain_type=”stuff”)确实需要context和question作为其内部提示的输入变量,但上述UserSession.set()错误则指向了Chainlit会话管理中更根本的操作问题,即如何正确地在不同回调函数之间传递和访问已初始化的chain对象。
2. 核心区别:set() 与 get()
cl.user_session是Chainlit为每个用户会话提供的专属键值存储空间。理解set()和get()的明确用途是解决此类问题的关键:
cl.user_session.set(key, value): 这个方法用于将一个value值存储在用户会话中,并为其指定一个key(字符串)。它必须同时提供key和value两个参数。cl.user_session.get(key): 这个方法用于从用户会话中检索先前存储在指定key下的value。它只需要提供key一个参数。
3. 原始代码中的错误识别
让我们分析一下提供的代码片段中@cl.on_chat_start和@cl.on_message函数的相关部分:
# ... (qa_bot 函数及其他辅助函数) ...@cl.on_chat_startasync def start(): chain = qa_bot() # 在会话开始时初始化 LangChain 链 msg = cl.Message(content="Starting the bot......") await msg.send() msg.content = "Hi, Welcome to the Medical Bot. What is your query?" await msg.update() cl.user_session.set('chain', chain) # 正确地将初始化的 chain 对象存储到会话中@cl.on_messageasync def main(message): # 错误之处:试图通过调用 set() 方法来检索 chain 对象,但未提供 value 参数 chain = cl.user_session.set("chain") cb = cl.AsyncLangchainCallbackHandler( stream_final_answer = True, answer_prefix_tokens = ["FINAL", "ANSWER"] ) cb.answer_reached = True # 原始代码中使用 message 对象,但 LangChain 链通常期望字符串输入 res = await chain.acall(message, callbacks = [cb]) answer = res["result"] sources = res["source_documents"] if sources: answer += f"nSources:" + str(sources) else: answer += f"nNo Sources Found" await cl.Message(content = answer).send()
在@cl.on_chat_start函数中,cl.user_session.set(‘chain’, chain)是正确的用法,它将qa_bot()返回的chain对象以键’chain’存储起来。
然而,在@cl.on_message函数中,chain = cl.user_session.set(“chain”)这行代码是错误的。这里的意图显然是想检索之前存储的chain对象,但却错误地调用了set()方法,并且只提供了一个key参数,而缺少了必需的value参数。这就是导致UserSession.set() missing 1 required positional argument: ‘value’错误的原因。
神采PromeAI
将涂鸦和照片转化为插画,将线稿转化为完整的上色稿。
97 查看详情
此外,在chain.acall(message, callbacks = [cb])这一行,LangChain链的acall方法通常期望接收一个字符串作为查询输入,而不是整个message对象。正确的做法是访问message.content来获取用户输入的文本。
4. 解决方案:使用 cl.user_session.get() 进行检索
要正确地从用户会话中检索在@cl.on_chat_start中存储的chain对象,只需将set()方法替换为get()方法即可。同时,修正acall方法的输入参数。
修正后的代码片段:
# ... (qa_bot 函数及其他辅助函数保持不变) ...@cl.on_chat_startasync def start(): chain = qa_bot() # 在会话开始时初始化 LangChain 链 msg = cl.Message(content="Starting the bot......") await msg.send() msg.content = "Hi, Welcome to the Medical Bot. What is your query?" await msg.update() cl.user_session.set('chain', chain) # 正确地将初始化的 chain 对象存储到会话中@cl.on_messageasync def main(message: cl.Message): # 明确message的类型提示 # 正确之处:使用 get() 方法检索已存储的 chain 对象 chain = cl.user_session.get("chain") # 确保 chain 对象已成功检索 if chain is None: await cl.Message(content="Bot not initialized. Please restart the chat.").send() return cb = cl.AsyncLangchainCallbackHandler( stream_final_answer = True, answer_prefix_tokens = ["FINAL", "ANSWER"] ) cb.answer_reached = True # 修正:将 message.content 作为查询输入传递给 chain.acall res = await chain.acall(message.content, callbacks = [cb]) answer = res["result"] sources = res["source_documents"] if sources: answer += f"nSources:" + str(sources) else: answer += f"nNo Sources Found" await cl.Message(content = answer).send()
通过将chain = cl.user_session.set(“chain”)修改为chain = cl.user_session.get(“chain”),我们确保了在@cl.on_message函数中能够正确地获取到在会话开始时创建的LangChain链实例,从而避免了UserSession.set()的错误。同时,将message替换为message.content,确保了向LangChain链传递的是正确的字符串查询内容。
5. Chainlit 会话管理最佳实践
为了构建健壮且高效的Chainlit应用,请遵循以下会话管理最佳实践:
初始化一次,多次检索:将成本高昂的对象(如LLM、嵌入模型、向量存储或复杂的LangChain链)在@cl.on_chat_start中初始化,并使用cl.user_session.set()存储。在后续的@cl.on_message调用中,使用cl.user_session.get()来检索这些对象,避免重复创建。清晰的命名:为会话变量使用描述性强的键名,以便于代码的可读性和维护。空值检查:cl.user_session.get()在键不存在时会返回None。虽然@cl.on_chat_start通常会确保设置这些变量,但在@cl.on_message中进行简单的None检查(如上述示例所示)可以增加代码的鲁棒性,尤其是在开发或调试阶段。异步操作:在Chainlit和LangChain集成中,特别是在使用acall等异步方法时,务必注意await和async关键字的正确使用,以确保非阻塞操作和并发性。
总结
正确管理cl.user_session对于构建状态化且高效的Chainlit应用至关重要。通过理解cl.user_session.set()用于存储和cl.user_session.get()用于检索的明确职责,开发者可以避免常见的错误,并确保其LangChain组件能够无缝集成并在用户交互中被有效复用。这个简单的修正不仅解决了特定的UserSession.set()错误,也显著提升了Chainlit机器人的健壮性和功能性。
以上就是正确管理Chainlit用户会话:解决UserSession.set()错误的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/851235.html
微信扫一扫
支付宝扫一扫