在Streamlit中集成LangChain异步astream_log函数的技术咨询
解答
1. 是否可以在不将整个脚本改为异步的情况下集成该异步函数?
可以。Python的asyncio模块允许在同步代码中通过asyncio.run()执行异步函数,无需重构整个同步代码结构。Streamlit本身也提供了异步代码兼容支持,不需要把所有逻辑都改成异步。
2. 需要对代码做出哪些修改才能实现功能?
以下是具体修改步骤:
- 导入
asyncio模块:import asyncio - 封装调用
astream_log的逻辑为异步函数,同时处理中间值提取:async def run_chain_with_log(chain, user_input): async for event in chain.astream_log(input={"question": user_input}): # 提取检索到的文档等中间值 if event.event == "on_retriever_end": retrieved_docs = event.data["output"] # 在Streamlit中展示检索结果 st.subheader("检索到的相关文档") for idx, doc in enumerate(retrieved_docs, 1): st.write(f"文档 {idx}:") st.write(doc.page_content) # 处理最终的聊天回复 if event.event == "on_chain_end": final_response = event.data["output"]["answer"] st.write(f"助手回复:{final_response}") - 在原同步代码中调用这个异步函数:
# 假设chain是你的LangChain链实例,user_input是用户输入内容 asyncio.run(run_chain_with_log(chain, user_input)) - 若使用Streamlit 1.28及以上版本,推荐用
st.async_runner避免重复创建事件循环的问题:with st.async_runner(): await run_chain_with_log(chain, user_input)
3. 这种处理方式是否为最优方案?
- 如果现有同步代码逻辑复杂、暂时不想全面重构,用
asyncio.run()包裹异步调用是最快捷的兼容方案,能快速实现中间值获取的需求。 - 若后续需要添加更多异步操作(比如异步API调用、多链并行执行),逐步将核心逻辑迁移为全异步会更优——Streamlit对异步函数的支持已成熟,全异步代码可避免同步/异步切换的开销,逻辑也更统一。
- 直接在异步遍历中处理中间值的方式,能实时获取链的执行日志,适合在聊天界面中实时展示检索结果等中间步骤,符合用户体验需求。
内容的提问来源于stack exchange,提问作者Doktrino
相关产品推荐
相关产品推荐

