LangChain异步链调用在Python中卡在await chain.invoke()环节
解决LangChain异步调用chain.invoke()无限挂起问题
针对你用LangChain开发PDF查询项目时异步调用挂起的问题,结合你用到的组件,给出以下排查和解决步骤:
1. 检查Ollama组件的异步兼容性
Ollama相关的LangChain封装(ChatOllama、OllamaEmbeddings)默认可能用同步模式,在异步流程中会阻塞事件循环:
- 初始化
OllamaEmbeddings时开启异步模式:embeddings = OllamaEmbeddings(model="你的模型名", async_mode=True) - 初始化
ChatOllama时确保支持异步调用:llm = ChatOllama(model="你的模型名", temperature=0, async_mode=True)
2. 修复MultiQueryRetriever的异步执行
MultiQueryRetriever默认同步生成查询语句,放到异步链中会导致阻塞,需启用异步模式:
from langchain.retrievers.multi_query import MultiQueryRetriever async_retriever = MultiQueryRetriever.from_llm( retriever=vectorstore.as_retriever(), llm=llm, use_async=True # 关键:开启异步查询生成 )
3. 确保Chroma向量库使用异步客户端
如果Chroma用的是同步客户端,异步操作会卡住,切换为异步客户端:
from langchain_community.vectorstores import Chroma from chromadb.api.asyncio import AsyncChromaClient client = AsyncChromaClient() vectorstore = Chroma( embedding_function=embeddings, client=client, collection_name="pdf_collection" )
4. 包装同步阻塞操作到线程池
PDF加载、文本分块这类同步步骤在异步函数中调用会阻塞事件循环,用ThreadPoolExecutor包装:
import asyncio from concurrent.futures import ThreadPoolExecutor executor = ThreadPoolExecutor(max_workers=4) async def load_pdf_async(pdf_path): loop = asyncio.get_event_loop() loader = UnstructuredPDFLoader(pdf_path) docs = await loop.run_in_executor(executor, loader.load) return docs async def split_text_async(docs): loop = asyncio.get_event_loop() splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200) splits = await loop.run_in_executor(executor, splitter.split_documents, docs) return splits
5. 检查事件循环的正确使用
确保脚本的异步入口正确启动事件循环,避免手动管理循环导致的冲突:
async def main(): # 完整异步流程:加载PDF -> 分块 -> 存入向量库 -> 构建链 -> 调用 docs = await load_pdf_async("your_pdf.pdf") splits = await split_text_async(docs) await vectorstore.aadd_documents(splits) # 用Chroma的异步添加方法 # 构建异步链 from langchain.chains import RetrievalQA chain = RetrievalQA.from_chain_type( llm=llm, chain_type="stuff", retriever=async_retriever ) # 异步调用用ainvoke而非invoke result = await chain.ainvoke({"query": "你的问题"}) print(result["result"]) if __name__ == "__main__": asyncio.run(main())
额外排查点
- 检查Ollama本地服务是否正常运行,用
ollama list确认模型已下载,ollama serve是否有报错 - 确保所有依赖包是最新版本,尤其是langchain、langchain-community、chromadb、ollama-python,避免版本兼容问题
内容的提问来源于stack exchange,提问作者Andriq Klyne Ajido
相关产品推荐
相关产品推荐

