基于LangGraph与Qwen构建金融AI Agent:RAG增强与工作流编排实战

📅 2026/7/4 18:15:02
基于LangGraph与Qwen构建金融AI Agent:RAG增强与工作流编排实战
1. 项目概述从零到一构建一个AI Agent最近几年AI Agent智能体从一个学术概念迅速演变为落地应用的热点。简单来说一个AI Agent就是一个能感知环境、自主决策并执行任务来达成目标的智能程序。它不再是简单的“一问一答”聊天机器人而是一个拥有“大脑”大语言模型、“记忆”上下文管理、“工具”调用外部API或函数和“规划”任务分解与执行能力的数字员工。我最近主导完成了一个“金融大模型问答机器人”项目核心目标就是打造这样一个AI Agent。它需要能理解复杂的金融咨询问题从海量的内部文档、市场研报和实时数据中精准检索信息并生成专业、合规且易于理解的回答。这个项目让我对如何使用LangChain等框架搭建一个生产级的AI Agent有了深刻的理解。今天我就把这个从设计到落地的完整过程拆解出来希望能给正在或计划踏入AI Agent开发领域的同行一些实实在在的参考。这个项目非常适合以下几类朋友一是希望将大模型能力与具体业务深度结合的开发者二是正在寻找RAG检索增强生成和智能体技术实战案例的技术负责人三是想了解如何将Qwen、LangChain、FastAPI等技术栈整合应用的工程师。无论你是想快速搭建一个原型还是规划一个企业级应用这里面的设计思路、技术选型考量以及踩过的坑都值得一看。2. 项目整体设计与核心思路拆解2.1 核心需求与业务挑战解析这个金融问答机器人的需求源于业务部门对高效、准确信息服务的迫切需求。传统的客服或分析师需要花费大量时间查阅文档和报告来回答用户问题效率低下且难以保证一致性。我们的目标是构建一个7x24小时在线的“数字分析师”。具体来说它需要解决几个核心挑战专业性与准确性金融领域的术语严谨数据敏感回答必须绝对准确不能出现“幻觉”即模型编造信息。一个关于财报数据的错误回答可能导致严重后果。知识实时性与广度金融信息更新极快Agent的知识不能只依赖于训练时的大模型静态知识必须能接入最新的市场数据、公司公告和内部政策文档。复杂问题处理能力用户的问题很少是单一的。例如“对比一下A公司和B公司过去一年的股价表现并分析其背后的主要原因”。这需要Agent能拆解成多个子任务检索两家公司的历史股价数据、查找相关的财报和新闻事件最后进行对比分析。可控与可审计所有生成的内容必须可追溯。我们需要知道回答是基于哪份文档的哪部分内容生成的以便复核和审计这在金融合规中至关重要。基于这些挑战我们决定采用“大语言模型LLM 检索增强生成RAG 智能体Agent工作流”的核心架构。LLM作为大脑负责理解和生成RAG系统作为外部知识库提供准确依据而Agent框架则负责协调整个任务执行流程。2.2 技术选型背后的深层逻辑技术选型不是堆砌热门词汇每一项选择背后都有其针对性的考量。核心框架为什么是LangChain和LangGraph这是项目的基石。很多人会问LangChain和LangGraph到底有什么区别简单类比LangChain像是一个提供了丰富预制件各种链、工具、记忆模块和快速组装指南的“智能乐高套装”。它抽象了常见模式如QA链让你能快速搭建起一个可用的原型特别适合入门和标准场景。 而LangGraph则像是一套更底层的“齿轮、轴承和控制器”它基于有向图来定义工作流让你能精细地控制Agent的每一步状态流转、循环和分支。我们的项目涉及多步骤决策比如先检索再判断是否需要计算最后生成报告这种需要强状态管理和自定义工作流的场景LangGraph提供了更优雅和可控的解决方案。实际上新版的LangChain其Agent核心也构建在LangGraph之上二者是互补关系。大模型基座选择Qwen在基座模型选择上我们评估了多个开源和商用模型。最终选择Qwen通义千问主要基于以下几点优秀的中文理解与生成能力在金融中文语料上表现稳定对专业术语和复杂句式处理得当。强大的函数调用Function Calling能力这是构建工具型Agent的核心。Qwen对工具调用格式的遵循程度和稳定性很好能准确理解何时该调用工具、以及如何解析工具返回的结果。可控的部署与微调成本作为开源模型我们可以将其部署在私有环境保障数据安全。同时其开放的权重也为我们后续的领域适配微调SFT/LoRA提供了可能。上下文长度支持长达32K甚至更长的上下文这对于处理长文档和维持多轮对话记忆非常关键。其他关键技术组件RAG框架LangChain / LangIndex用于文档的加载、切分、向量化存储和检索。我们利用LangChain丰富的Document Loader处理PDF、Word、HTML等格式的金融文档并用其Text Splitter进行智能分块。向量数据库我们选择了Chroma轻量、易用和Milvus生产级、高性能进行分级存储。后端服务FastAPI提供稳定、高性能的HTTP API接口封装整个Agent的推理流程。FastAPI的异步特性、自动生成API文档以及高性能非常适合AI应用后端。图增强RAGGraphRAG这是针对复杂金融关系的优化。传统RAG基于语义相似度检索可能丢失文档间的逻辑关联如“公司A收购了公司B”。GraphRAG通过从文档中提取实体和关系构建知识图谱使Agent能进行“关系推理”比如回答“哪些公司是这家投资机构的主要投资对象”这类问题。微调与优化技术LoRA, SFT, 量化用于让通用大模型更“懂”金融。我们收集了高质量的金融问答对使用SFT监督微调和高效的LoRA低秩适配技术对Qwen进行微调使其输出风格更专业。量化技术则用于模型部署时压缩模型大小、提升推理速度使服务成本可控。注意技术选型没有银弹。这个组合是基于我们对可控性、性能、成本以及团队技术栈的综合考量。例如如果追求极致开发速度且业务逻辑简单可能只用LangChain就够了如果涉及非常复杂、环环相扣的业务流程那么从一开始就基于LangGraph设计会是更明智的选择。3. 核心模块解析与实操要点3.1 知识库构建RAG系统的基石一个AI Agent的智商很大程度上取决于它的“知识库”。金融领域的RAG系统构建远比简单的文本切分向量化要复杂。文档处理流水线我们设计了一个多阶段的处理流水线加载与解析使用Unstructured库和LangChain的PDFLoader、DocxLoader等处理格式各异的文档。关键点在于保留元数据如文档标题、章节、页码这对后续的可追溯性至关重要。智能切分Chunking这是最容易出问题的一环。简单的按固定长度切分会把表格、段落从中切断破坏语义。我们的策略是混合切分递归切分优先按段落、标题等自然分隔符切分。固定长度重叠切分对长段落再进行二次切分并设置一定的重叠长度如200字符确保上下文连贯。表格特殊处理使用Markdownify等工具将表格转换为Markdown格式并将其作为一个独立的Chunk避免被拆散。向量化Embedding与存储我们测试了多种嵌入模型最终为中文金融文本选择了BGE系列的嵌入模型它在中文语义相似度任务上表现优异。向量存储我们采用了分层策略近期高频文档存入Chroma内存检索速度快全量历史文档存入Milvus持久化存储支持大规模数据。实操心得元数据是黄金为每个文本块Chunk添加丰富的元数据如source文件名、page、section、date等。在检索时不仅可以按语义相似度排序还可以按元数据过滤例如“只检索2023年以后的年报”极大提升检索精度。检索不是终点传统的“检索Top-K个片段”直接扔给LLM效果可能不佳。我们引入了重排序Re-ranking技术使用一个更精细的交叉编码器模型如BGE-Reranker对初步检索出的片段进行二次排序将最相关的片段排到最前面显著改善了生成答案的质量。3.2 Agent大脑LLM的集成与提示工程将Qwen模型集成到LangChain/LangGraph框架中并让它“听话”地执行复杂任务是核心环节。模型集成与对话管理我们通过LangChain的ChatQwen类或自定义的BaseChatModel来封装Qwen的API调用。更关键的是记忆Memory管理。金融问答往往是多轮的用户会基于上一个回答追问。我们使用了ConversationSummaryBufferMemory它不仅能保存最近的对话历史还会自动对较早的对话进行摘要既保持了上下文连贯性又不会因上下文过长而挤占关键信息的位置。提示词Prompt工程实战提示词是引导Agent行为的“指挥棒”。我们为不同的任务设计了不同的提示词模板。例如对于一个分析型任务的提示词可能包含你是一位资深的金融分析师。请基于以下提供的背景信息专业、严谨地回答用户的问题。 背景信息 {context} --- 当前对话历史摘要 {history} --- 用户问题{question} --- 请按以下步骤思考 1. 首先判断用户问题需要哪些信息背景信息是否足够。 2. 如果背景信息不足请明确指出还需要哪些方面的数据。 3. 如果信息足够请组织一个结构清晰、数据支撑的回答避免主观臆断。 4. 在回答末尾注明你的结论主要依据了背景信息中的哪部分内容请引用来源。我们利用LangChain的PromptTemplate和FewShotPromptTemplate来动态构建这些提示词。一个关键技巧是使用“系统消息System Message”来固定Agent的角色和基础行为准则这比把所有指令都放在用户消息里更稳定。3.3 工具赋能让Agent“手眼通天”一个只会聊天的Agent价值有限。真正的能力体现在它能调用工具完成任务。工具Tools的设计与实现我们为金融Agent设计了以下几类工具知识检索工具核心工具。它接收用户问题调用上述的RAG检索系统返回最相关的文档片段。金融数据查询工具封装内部API用于查询实时股价、历史K线、财务指标等。使用LangChain的tool装饰器或继承BaseTool类来创建。计算工具例如计算复合增长率、夏普比率等。这些工具确保数值计算的绝对准确性避免LLM自己“心算”出错。报告生成工具调用内部模板系统将分析结果格式化为标准的Word或PDF报告。在LangGraph中这些工具被定义为图中的节点Node。AgentLLM作为一个“路由器”节点根据当前状态决定下一个该调用哪个工具节点。工具调用的稳定性保障LLM决定是否调用、以及如何调用工具这个过程有时会不稳定。我们采取了以下措施结构化输出Structured Output要求Qwen以严格的JSON格式输出工具调用请求包括tool_name和tool_input便于程序解析。验证与重试在工具调用节点对LLM的输出进行格式验证。如果格式错误则进入一个“修复”节点让LLM重新生成或由简单规则修复。工具描述精细化为每个工具编写清晰、无歧义的描述包括功能、输入参数格式和示例。这是LLM能否正确使用工具的关键。4. 基于LangGraph的工作流编排实战4.1 定义Agent的状态与工作流图LangGraph的核心思想是状态机。我们首先定义整个Agent工作流需要维护的“状态”State。我们定义了一个AgentState类通常使用TypedDict来声明from typing import TypedDict, List, Annotated import operator class AgentState(TypedDict): # 用户输入的问题 question: str # 多轮对话历史 conversation_history: List[str] # 从知识库检索到的上下文 retrieved_context: str # LLM的思考过程或中间答案 analysis: str # 最终要返回给用户的答案 final_answer: str # 记录已调用过的工具防止循环 used_tools: Annotated[list, operator.add]接下来我们绘制工作流图。一个典型的金融问答Agent工作流可能包含以下节点和边路由节点Router接收用户问题判断问题类型如简单查询、复杂分析、数据计算、报告生成。这个判断由LLM做出。检索节点Retrieve调用知识检索工具获取相关背景信息并更新retrieved_context状态。分析节点AnalyzeLLM结合问题、历史、检索到的上下文进行思考分析生成初步分析或答案草稿更新analysis状态。工具调用节点Call Tool如果需要具体数据或计算LLM决定调用哪个工具并传入正确参数。工具执行结果被写回状态例如更新retrieved_context或analysis。生成节点Generate整合所有信息问题、历史、上下文、分析结果、工具结果生成最终面向用户的、格式友好的回答更新final_answer状态。条件边Conditional Edges连接这些节点的“边”决定了流程走向。例如从“路由节点”出来后根据判断的“问题类型”值决定是流向“检索节点”还是直接流向“计算工具节点”。4.2 关键节点实现与状态流转我们用代码来具体说明“检索节点”和“条件路由”的实现。检索节点实现示例from langgraph.graph import StateGraph, END import asyncio # 假设我们已经有了一个检索函数 retrieve_documents async def retrieve_node(state: AgentState): question state[question] # 调用RAG检索系统 relevant_docs await retrieve_documents(question) # 将检索结果拼接成上下文字符串并附上来源 context_with_sources \n\n.join([f内容{doc.page_content}\n[来源{doc.metadata[source]}] for doc in relevant_docs]) # 更新状态 return {retrieved_context: context_with_sources}条件路由逻辑示例def route_question(state: AgentState): # 这里可以调用一个LLM来判断问题类型也可以使用规则 # 简单示例如果问题包含“计算”或“比率”则去工具调用节点 question state[question] if any(word in question for word in [计算, 比率, 增长率]): return call_calculator_tool elif 报告 in question: return generate_report else: # 普通问答先检索再分析 return retrieve构建图并运行# 初始化图 workflow StateGraph(AgentState) # 添加节点 workflow.add_node(router, router_node) # 路由节点 workflow.add_node(retrieve, retrieve_node) workflow.add_node(analyze, analyze_node) workflow.add_node(call_calculator_tool, calculator_tool_node) workflow.add_node(generate, generate_node) # 设置入口点 workflow.set_entry_point(router) # 添加条件边 workflow.add_conditional_edges( router, route_question, # 上面定义的路由函数 { call_calculator_tool: call_calculator_tool, generate_report: generate_report, retrieve: retrieve, } ) workflow.add_edge(retrieve, analyze) workflow.add_edge(analyze, generate) workflow.add_edge(generate, END) # 编译图 app workflow.compile() # 运行Agent async def run_agent(question: str): initial_state AgentState( questionquestion, conversation_history[], retrieved_context, analysis, final_answer, used_tools[] ) final_state await app.ainvoke(initial_state) return final_state[final_answer]这个工作流确保了任务的标准化执行并且通过LangGraph的持久化功能我们可以随时中断和恢复一个长任务或者对执行过程进行调试和复盘。5. 系统集成、优化与部署5.1 后端API与服务化我们将编译好的LangGraph工作流即上面的app封装到FastAPI应用中。核心端点如下from fastapi import FastAPI, HTTPException from pydantic import BaseModel from .agent_workflow import run_agent # 导入上面定义的agent运行函数 app FastAPI(title金融智能问答Agent API) class QueryRequest(BaseModel): question: str session_id: str None # 用于多轮对话会话管理 class QueryResponse(BaseModel): answer: str sources: List[str] # 引用的来源列表 session_id: str app.post(/query, response_modelQueryResponse) async def query_agent(request: QueryRequest): try: answer await run_agent(request.question) # 在实际中run_agent会返回更结构化的结果这里简化处理 return QueryResponse(answeranswer, sources[], session_idrequest.session_id or generate_session_id()) except Exception as e: raise HTTPException(status_code500, detailfAgent处理失败: {str(e)})我们使用session_id来关联同一用户的多次问答并在后端维护对应的对话记忆Memory对象。FastAPI的依赖注入系统用来管理数据库连接、模型客户端等全局资源。5.2 性能优化与效果提升策略1. 推理加速与成本控制模型量化使用AWQ或GPTQ等量化技术将Qwen模型从FP16精度量化到INT4或INT8在几乎不损失精度的情况下将推理速度提升1.5-3倍显存消耗降低60%-70%。这对于降低部署成本和提升并发能力至关重要。缓存对频繁出现的、结果确定的查询如定义类问题的Embedding结果和最终答案进行缓存减少对模型和向量数据库的重复调用。流式响应Streaming对于生成时间较长的回答实现Token级的流式返回提升用户体验。2. 效果提升迭代式RAGIterative RAG不是一次检索就结束。让Agent在初步分析后如果发现信息不足或需要澄清可以主动提出反问或者基于已有信息生成更精准的搜索查询进行二次检索。智能体反思Agent Reflection在生成最终答案前增加一个“自我审查”节点。让LLM以批判性视角检查自己即将输出的答案事实是否与检索内容一致逻辑是否自洽是否有遗漏这能有效减少事实性错误。持续微调收集线上用户与Agent的实际交互数据特别是那些被用户纠正或评分低的案例构造高质量的SFT数据定期对模型进行增量微调让Agent越用越聪明。5.3 监控、评估与持续迭代一个上线的AI应用必须有完善的监控和评估体系。链路追踪Tracing我们集成了LangSmith。每个用户查询在系统中的完整生命周期——调用了哪些工具、检索了哪些文档、LLM的中间思考过程、耗时多少——都被完整记录。这是排查问题、理解Agent行为的“黑匣子”。核心指标监控端到端响应延迟P95、P99延迟。工具调用成功率各类工具调用失败的比例。答案质量评估既通过自动评估如利用GPT-4评估答案与检索内容的相关性、事实一致性也通过人工抽检打分。幻觉率随机抽样答案人工判断其中是否存在事实性编造。反馈闭环在客户端提供“回答是否有用”的反馈按钮将负反馈案例自动纳入待审查和改进队列。6. 常见问题与排查技巧实录在实际开发和运维中我们遇到了形形色色的问题。这里记录几个最具代表性的案例和解决思路。6.1 检索相关总是找不到对的文档问题现象用户问“XX公司2023年净利润”Agent检索出来的却是该公司2022年的社会责任报告片段。排查与解决检查Embedding模型测试Embedding模型在金融数字、年份上的敏感性。我们发现有些通用模型对数字不敏感。解决方案换用或在金融语料上微调过的Embedding模型如BGE-financial。检查元数据过滤我们的检索器是否支持按“年份”元数据过滤解决方案在检索时使用LLM或规则从问题中提取关键过滤条件如“2023年”并将其作为元数据过滤器传入向量数据库查询。检查分块策略净利润数据可能在一个很大的表格里而我们的分块可能把表格切碎了。解决方案优化分块逻辑对识别出的表格进行特殊处理保持其完整性。6.2 Agent逻辑相关陷入死循环或无效调用问题现象Agent在“检索-分析-觉得信息不够-再检索”的循环中出不来或者反复调用同一个工具。排查与解决检查状态设计在AgentState中是否缺少了记录“循环次数”或“已尝试步骤”的字段解决方案在状态中增加iteration_count并在路由节点判断如果超过阈值如5次则强制跳转到生成节点并给出“信息不足请补充说明”的提示。优化工具描述和提示词工具描述是否清晰LLM是否理解每个工具的准确用途和边界解决方案精炼工具描述加入明确的适用场景和不适用场景。在系统提示词中强调“避免重复调用已提供相同信息的工具”。利用LangGraph的检查点Checkpoint和中断LangGraph支持设置检查点当检测到循环时可以从上一个检查点恢复并尝试不同分支。这是一个高级但非常有效的控制机制。6.3 性能与稳定性相关响应慢或间歇性失败问题现象服务在高峰期响应时间飙升或偶尔出现超时错误。排查与解决定位瓶颈使用LangSmith的Trace视图可以清晰看到一次调用中时间主要花费在哪个环节是EmbeddingLLM生成还是工具调用API。实施限流与降级LLM调用限流对调用Qwen API的环节进行并发控制防止瞬时高并发击穿服务。降级策略当RAG检索超时是否可以降级为直接使用LLM的固有知识回答并明确告知用户此答案未经验证当复杂分析流程超时是否可以降级为只提供检索到的原始文档片段异步化改造检查整个工作流中是否存在可以并行执行的步骤。例如如果一个问题需要调用两个独立的API工具可以在LangGraph中使用异步节点并行调用而不是串行。一个实用的排查清单问题大类可能原因排查步骤答案质量差1. 检索不准2. LLM指令遵循不好3. 上下文过长关键信息被截断1. 检查检索到的片段是否相关看Trace2. 简化/强化系统提示词3. 检查ConversationSummaryBufferMemory的max_token_limit设置工具调用错误1. LLM生成的参数格式不对2. 工具本身API异常3. 网络超时1. 在工具调用节点前增加参数格式验证和修复逻辑2. 为工具调用添加重试机制和断路器3. 检查网络连接和防火墙响应速度慢1. Embedding或LLM推理慢2. 外部工具API慢3. 工作流串行步骤多1. 启用模型量化、使用更快的Embedding模型2. 为外部API调用设置合理超时并考虑缓存3. 用LangGraph重构工作流将可并行步骤异步化这个项目从零开始到最终稳定服务业务部门整个过程充满了挑战但也收获了巨大的价值。最大的体会是构建一个成功的AI Agent技术选型只是起点更关键的是对业务逻辑的深度理解、对异常情况的周密考虑以及建立一套可观测、可评估、可迭代的工程体系。LangChain和LangGraph提供了强大的武器但如何用好它们打造出真正解决实际问题的智能体还需要我们不断地在实战中打磨和思考。