news 2026/9/11 5:27:51

LCODER AI Agent实战:自然语言查数系统架构全拆解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LCODER AI Agent实战:自然语言查数系统架构全拆解

我上周刚把问数项目的第一个版本跑通,从零搭了一套基于LCODER的AI Agent智能体架构。问数项目说白了就是让业务人员用自然语言直接查数据库,比如"上个月华东区销售额前10的品类是什么",系统自动完成意图理解、SQL生成、查询执行、结果解读一整条链路。这篇文章是LCODER之AI Agent开发实战系列的第一篇,重点拆解项目架构设计——为什么这么分层、核心模块怎么划分、Agent的运行逻辑是什么、技术选型背后的考量。适合正在做AI Agent开发、或者准备把大模型落地到数据查询场景的工程师参考,这篇文章会给你一份可以直接抄作业的架构蓝图。

1. 项目背景与核心需求:问数这件事,到底难在哪

1.1 为什么需要"问数项目"

传统的数据查询路径是:业务提需求→数仓写SQL→出报表→业务看图。这个链路的问题在于慢,一个简单的取数需求排队下来至少半天,碰上口径来回确认,拖两天也很正常。问数项目想做的事情,就是把这个链路压缩成一句自然语言提问,让AI Agent自动完成从语义理解到结果返回的过程。

但把所有环节串起来,远比想象中复杂。最初我尝试过用纯Prompt工程来做,让大模型直接输出SQL,再执行返回结果,效果很不稳定。问题主要出在几个地方:大模型不了解库表结构导致字段名编造、长长的WHERE条件容易漏条件、多轮对话的上下文容易丢失、执行结果没法自动做可视化。这也是我决定切换到Agent架构的核心原因——问数不是一个单一的文本生成任务,而是一个需要感知、规划、行动、反思的完整智能体任务。

1.2 目标场景与核心能力边界

在动手设计架构之前,先明确问数项目的场景边界,否则很容易做成一个什么都想干但什么都干不好的系统。我圈定的核心场景是:

  • 面向内部业务人员的经营分析查询,不面向C端用户
  • 支持单表查询和简单多表关联,复杂ETL逻辑不在Agent能力范围内
  • 查询结果返回后,Agent需要给出一段自然语言的业务解读
  • 支持多轮对话,用户可以逐层追问

能力边界也画得很清楚:Agent不做数据加工和清洗,不在SQL里做复杂窗口函数,不做自助建模。边界画清楚之后,架构设计才不会跑偏,也方便后续做能力迭代。

整体设计思路是"能用Agent解决的就用Agent,不能让Agent做的一律挡住"。比如SQL生成交给Agent,但SQL的安全性校验必须走规则引擎;表结构识别交给Agent,但字段语义映射必须走元数据缓存。

2. 整体架构设计:LCODER问数项目智能体的四层结构

2.1 分层架构与核心模块划分

问数项目的整体架构分为四层:接入层、Agent核心层、工具层、数据与基础服务层。每一层解决一类问题,层与层之间只通过标准接口通信。

接入层负责对接外部使用方,包括Web端对话界面、企业IM机器人和OpenAPI三种方式。这里有一个设计决策:接入层只做协议转换和会话管理,不承载任何业务逻辑。所有请求统一封装成标准Message格式,进入Agent核心层的消息队列。

Agent核心层是整个架构的中枢,也是LCODER这个Agent框架重点解决的问题。它包含六个核心模块:

  • 意图识别模块:判断用户提问属于查数、追问、闲聊还是报表生成
  • 任务规划模块:将用户目标拆解为可执行的子任务序列
  • 工具调度模块:根据子任务类型选择合适的工具并传递参数
  • 上下文管理模块:维护多轮对话的记忆,支持指代消解
  • Schema感知模块:向大模型提供准确的库表结构信息
  • 结果解析模块:将查询结果转化为自然语言解读和可视化方案

工具层是Agent可以调用的能力集合,包括SQL执行工具、元数据查询工具、图表生成工具、数据字典工具等。每个工具都遵循统一的输入输出协议。

数据与基础服务层包括MySQL、Redis、向量数据库、对象存储和模型网关。模型网关在这里是个关键设计,统一封装了与不同大模型的交互方式。

2.2 技术选型与选型理由

技术选型是架构设计里最容易被低估的环节。很多团队一上来就选了最热门的框架,结果项目做到一半发现某层不合适,推翻重来。

我在LCODER问数项目里的核心选型是:Python 3.11 + FastAPI作为服务框架,LangGraph负责Agent的编排,MySQL和向量数据库搭配存储元数据,Redis做缓存和会话管理,模型网关兼容主流的闭源和开源大模型。

先解释为什么用LangGraph而不是LangChain。LangChain的问题在于抽象层级太高,当Agent的流程比较复杂时,流程控制能力会很弱。LangGraph提供了图结构的编排方式,可以把意图识别、SQL生成、SQL校验、结果解读这些节点定义成一张有向图,每个节点是一个可编程的步骤,节点之间通过状态对象传递数据,这对问数这类多步骤强交互的场景非常合适。

数据库选MySQL而不是PG,主要是历史原因,数仓已经跑在MySQL上。向量数据库选的是开源的Milvus,存表结构信息、字段描述和查询历史的Embedding。用向量检索而不是直接查元数据表,是因为用户在提问时的表述经常和表名/字段名不一致,向量检索能做语义匹配。比如用户问"销量",实际字段名是"sale_cnt",光靠字符串匹配是匹配不上的。

2.3 为什么不用一个巨型Prompt解决问题

这里分享一个我踩过坑之后的反思。在项目初期,我试过把系统提示词写得极其详细,把数据库所有表结构、字段注释、业务口径全部塞进一个Prompt里,期望大模型"看完就能查"。实际效果很差。

原因主要有三个。第一是上下文窗口有限,表结构一多,几千个字段灌进去,Token成本高且有效信息被稀释。第二是大模型的注意力机制决定了它对Prompt中间位置的敏感度低于开头和结尾,埋在一大堆表结构中最关键的表反而不容易被注意到。第三是字段口径常有冲突,比如"销售额"在订单表是去掉退款后的净额,在报表表是含退款的总金额,同一个词在不同表里语义完全不同,一个巨型Prompt没法处理这种细粒度差异。

所以架构上必须拆开:表结构不靠人工写死在Prompt里,而是按需通过Schema感知模块检索出来,动态注入Prompt。这就是Agent架构相比纯Prompt工程的核心优势——具备感知能力,能够动态决定要"看"什么信息。

3. Agent核心运行逻辑:智能体是怎么"想"的

3.1 从用户提问到Agent决策的完整链路

要理解Agent的运行方式,首先得跳出"大模型问答"的思维框架。Agent不是简单地"输入问题→输出答案",而是"感知状态→规划动作→调用工具→更新状态→继续决策"的循环。

以"上个月华东区销售额前10的品类"这个问题为例,Agent的处理链路是这样的:

  1. 接入层收到用户消息,带上会话ID进入Agent核心层
  2. 意图识别节点判断这是一次数据查询请求,类型为"查数"
  3. Schema感知节点从元数据库检索出与"销售额""华东区""品类"相关的表和字段
  4. SQL生成节点基于检索到的Schema信息和用户问题生成SQL候选
  5. SQL校验节点对生成的SQL做安全性检查,包括是否只读、是否有LIMIT、是否有明显语法错误
  6. SQL执行工具执行查询,返回结果集
  7. 结果解析节点根据结果集生成自然语言解读,同时判断是否需要生成图表
  8. 最终回复返回给用户,同时把本轮对话写入上下文管理器

这个过程看起来是线性的,但在LangGraph里是图结构,节点之间有分支和跳转。比如第5步SQL校验如果发现生成的SQL有问题,会直接回到第4步让大模型重新生成,而不是直接报错给用户。

3.2 LLM在问数链路中的三个关键角色

同一个大模型,在问数项目里实际上承担了三种不同的角色,这也是Agent架构与传统Chatbot最不一样的地方。

第一个角色是意图理解和任务规划器。这个环节大模型需要判断用户的意图类型,并决定需要调用哪些工具。这里我用的是Function Calling机制,让大模型从预设的工具列表中选择,而不是让它自由发挥。比如用户说"帮我看看这个数据",意图识别模块需要结合上下文判断"这个数据"指的是上轮查询的结果集,还是需要重新发起一次查询。

第二个角色是SQL生成器。这是问数项目里最核心也是最难的部分。这里的大模型实际上在做"受约束的生成"——约束来自两个方面,一是Schema感知模块提供的表结构信息,二是SQL规范里的业务口径定义。我测试过不下十种Prompt模板,最终发现效果最好的是"先解释再生成"模式:要求大模型先说明自己理解了这个表是干什么的、用户想问的是什么,然后再生成SQL。这个中间推理步骤对提升准确率帮助很大。

第三个角色是结果解读器。查询返回的是结构化数据,用户要的是通俗易懂的结论。这个环节大模型需要把数据转化为文字描述,比如"销售额排名第一的是休闲食品,达到2300万,环比增长12%"。这个角色对上下文的要求很高,因为它需要引用上轮生成的SQL和结果集来做分析。

3.3 需要几个Agent?单Agent还是多Agent

架构设计时我面临一个选择:是一个Agent从头干到尾,还是拆成多个各司其职的子Agent。这个取舍在LangGraph里尤其重要,因为图编排可以很灵活地组合节点。

我的最终方案是"单Agent核心 + 多专家节点"。也就是从用户视角看是一个Agent在对话,但从架构视角看,内部有多个专家节点承担不同职责。核心Agent负责任务调度和上下文维护,专家节点专注于特定任务。

为什么不用多Agent独立部署呢?我实测下来,多Agent通信的开销和复杂度远超收益。每个Agent都有独立的上下文和记忆,当A Agent的输出需要传给B Agent时,序列化/反序列化是有信息损失的。更头疼的是问题定位,多Agent场景下你很难追踪到底是哪个Agent给出了错误结果。

单Agent核心加多专家节点的模式,既保留了任务分工的优势,又避免了多Agent通信的复杂度。专家的上下文由核心Agent统一管理,相当于是一个大脑指挥多双手,而不是多个大脑各自决策。

4. 关键链路设计:从自然语言到查询结果的落地细节

4.1 完整问数流程的状态管理与数据流

在LangGraph里,状态对象是整个图流转的"中枢神经"。每个节点执行完毕后,都要把结果写入状态对象,下一个节点从状态里读取需要的数据。这条数据链路设计得好不好,直接影响系统的稳定性和可调试性。

我这里定义了一个基础状态对象,包含以下核心字段:

  • session_id: 会话标识,用于区分不同用户和对话
  • user_query: 原始用户问题
  • clarified_query: 经过指代消解后的问题(把"上个月""这个品类"这种指代替换为具体内容)
  • intent: 意图识别结果
  • retrieved_schema: Schema感知模块检索到的表结构信息
  • generated_sql: 生成的SQL
  • sql_validated: SQL校验结果
  • query_result: SQL执行返回的结果集
  • final_response: 最终拼装好的回复内容
  • 上下文存储:包含历史问题的压缩摘要和最近几轮的完整记录

每个节点只负责读取自己需要的字段,在结束时更新自己的输出字段。这样做的好处是支持链路追踪——任何一轮对话都能从日志里完整复盘状态对象的变化过程,定位问题非常高效。

4.2 Schema感知:让大模型"读懂"数据库的关键机制

Schema感知是问数项目里最容易被忽视但影响最大的模块。很多团队做问数项目效果差,追根溯源就是Schema感知没做好,大模型拿到的表结构信息要么不够、要么不准确。

我这里的Schema感知模块采用"离线索引 + 在线检索"的设计。离线阶段,把数据库里每张表的表名、字段名、字段注释、字段类型、枚举值、表之间的主外键关系全部抽取出来,做一个清洗和向量化,写入向量数据库。同时,业务口径文档也被向量化保存,比如"销售额=订单金额-退款金额"这条口径定义,会被关联到订单表和退款表的相关字段上。

在线检索阶段,当用户发起查询时,Schema感知模块把用户问题做向量化,在向量数据库里做相似度检索,筛出最相关的表结构信息,限制在15个字段以内。检索条件同时包含表名/字段名的文本匹配和向量语义匹配,双路召回再融合排序。

这套机制最重要的价值,是把"大模型需要知道的信息"从全量缩小到"与本次问题相关的信息",既是效果保障也是成本控制手段。实测下来,加上Schema感知之后,SQL生成准确率从52%提升到了81%。

4.3 SQL生成与校验的双保险机制

SQL生成是问数项目的核心,但再强的模型也会犯错,所以安全兜底和准确性校验绝对不能省。我这里的做法是生成和校验双保险。

生成阶段,我要求大模型输出SQL的同时输出一段自解释。为什么一定要自解释?因为这段文字可以强制大模型"想清楚再写"。我实测过,加入自解释之后,SQL的语法错误率下降了30%以上。同时生成阶段会给定几个约束:只能SELECT,不能多语句,必须有LIMIT子句,表名和字段名必须来自提供的Schema列表。

校验阶段做了三层规则校验加一层语义校验。规则校验包括:SQL语句是否以SELECT开头、是否包含INSERT/UPDATE/DELETE/DROP/ALTER等危险关键字、LIMIT子句是否存在且值是否合理、表名字段名是否在Schema白名单内。语义校验交给LLM再做一次审查:把最终生成的SQL和用户问题、Schema信息一起发给模型,让模型判断"这个SQL和用户的问题是否一致、有没有明显的逻辑矛盾"。

这里给一个参考的校验结果处理方式:规则校验不通过的直接打回重新生成,重新生成两次仍不通过的返回给用户"抱歉暂不支持该查询";语义校验不通过的会提示大模型修正。这些规则都写入配置文件,方便后续调整,不写死在代码里。

4.4 多轮对话的上下文管理与指代消解

问数项目的多轮对话比普通客服机器人复杂得多,因为每一轮都可能产生新的SQL和结果集,上下文里同时存在"语义信息"和"数据结构信息"。

我的上下文管理分两层。短期记忆存最近5轮的完整对话记录、每轮生成的SQL和执行结果;长期记忆存用户在整个会话中的核心关注点、常用查询维度、经常用到的业务口径,做摘要后存入Redis。

指代消解是另一件很麻烦的事。用户说"上个月"到底是哪个月?"这个品类"指的是前一轮结果里的哪个品类?我的做法是在每次处理新问题前,先让大模型结合历史上下文做一次"问题改写",把指代词替换为具体内容。改写后的问题才进入Schema感知和SQL生成流程。实测这个前置步骤对多轮追问的准确率提升非常明显,从63%提高到了比首轮查询只低5个百分点的水平。

5. 工程化落地:代码结构、环境准备与开发顺序

5.1 项目工程结构是怎么组织的

架构如果只停留在文档里,那就不叫落地。下面是这个问数项目第一版的核心代码结构,实际项目的结构会多一些模块,但骨架就是这个。每个目录的职责在代码里通过命名和注释做了明确区分,避免后续越写越乱。

lcoder_agent/ ├── api/ # 接入层:HTTP接口、WS接口、IM机器人适配 │ ├── routes/ │ ├── schemas/ # 请求/响应模型 │ └── middleware/ ├── agent/ # Agent核心层 │ ├── graph/ # LangGraph状态图定义 │ ├── nodes/ # 每个图节点的具体实现 │ │ ├── intent_node.py │ │ ├── schema_node.py │ │ ├── sql_gen_node.py │ │ ├── sql_check_node.py │ │ ├── exec_node.py │ │ └── response_node.py │ ├── memory/ # 上下文管理、指代消解 │ └── state.py # 状态对象定义 ├── tools/ # 工具层 │ ├── sql_executor.py │ ├── schema_retriever.py │ ├── chart_generator.py │ └── registry.py # 工具注册中心 ├── meta/ # Schema离线索引构建 │ ├── extractor.py │ ├── vectorizer.py │ └── indexer.py ├── llm/ # 模型网关封装 │ ├── base.py │ ├── factory.py │ └── providers/ ├── config/ # 配置文件 └── tests/ # 单元测试和回归测试

5.2 开发顺序建议:先跑通一条最简链路

一开始别想着把完整架构都实现出来,那样会陷入无尽的调试。我给出的建议是先跑通一条最简链路:用户输入→意图识别→SQL生成→SQL执行→结果返回。这五个节点串起来能跑以后,再逐一把Schema感知、SQL校验、上下文管理、结果解读这些模块加进去。

开发顺序可以按依赖关系分四步走。第一步是初始化LangGraph状态图,定义好状态对象,把最简单的几个节点挂上去,用假数据跑通整个图。第二步接入Schema感知模块,建好离线索引管道,把向量数据库打通,这样才能在SQL生成时动态注入Schema信息。第三步做SQL校验和重试机制,这是保障安全的关键,必须尽早补上。第四步加上下文管理和多轮对话增强。

每一步都有明确的验证标准。第一步的标准是"任意一段写死的SQL能返回结果",第二步的标准是"同一句自然语言查询,5次生成SQL的准确率能达到80%以上",第三步的标准是"危险SQL能被拦截且正常SQL不受影响",第四步的标准是"连续三轮追问能正确指代历史结果"。

5.3 环境准备与依赖清单

环境依赖的坑比想象中多,这里梳理一份第一版实际用到的依赖清单,省得大家在装环境时踩重复的坑。

Python环境建议用3.11,太旧的版本对LangGraph和Pydantic的兼容性都不太好。核心依赖包括langgraph、langchain-core、fastapi、uvicorn、pydantic、sqlalchemy、pymysql、redis、openai、milvus-python。模型方面,第一版建议直接用主流的闭源API,开发效率最高,等流程跑通了再考虑替换成私有化部署的开源模型。

数据库账号建议单独创建一个只读账号给Agent用,这和后面要讲的安全机制是配套的。向量数据库用Milvus的话注意先在本地起一个Standalone模式的实例,等联调环境再切集群模式。

5.4 配置管理的设计要点

问数项目的配置项并不少,而且同类配置的形态差异很大。我拆成了三类配置来管理,避免把所有东西堆在一个文件里。

第一类是模型配置,包括API地址、密钥、模型名称、温度参数、max_tokens等。第二类是工具配置,包括数据库连接信息、Redis连接、向量数据库连接、SQL执行超时时间、LIMIT默认值。第三类是Agent行为配置,包括意图类型列表、SQL校验规则、重试次数、上下文轮数等。

模型配置和工具配置用YAML文件管理,Agent行为配置因为经常调整,放到配置中心里,支持热更新。有一个实用的经验:SQL生成相关的Prompt不要写在代码文件里,单独维护一个prompt目录,用版本管理。每次Prompt改动都留档,方便回溯是哪次Prompt改动影响了效果。

提示:SQL执行超时时间建议设为10秒,超过直接终止并提示用户"查询超时"。数据库层面还要再设一个statement级别的超时,双保险,防止慢SQL拖垮连接池。

6. 常见问题与排查实录:这些坑我替你们踩过了

6.1 问题排查速查表

开发过程中遇到的高频问题,整理成速查表,遇到类似问题可以直接对照排查。

现象大概率原因排查思路
SQL生成总用错字段Schema感知注入的表结构不完整查看检索到的字段列表,确认是否匹配用户问题
生成的SQL语法正确但执行超时缺少LIMIT约束或表连接条件缺失检查SQL校验规则,加LIMIT强制约束
多轮对话答非所问指代消解失败查看clarified_query,确认指代词是否被正确替换
查询结果正确但解读错误结果解读Prompt缺少数据上下文检查最终生成解读时是否传入了完整结果集
同一问题不同结果大模型温度参数偏高调低temperature,必要时改为0.1
Agent流程卡住不执行下一步LangGraph状态对象字段更新异常打开状态追踪日志,检查各节点输出

6.2 关于SQL安全的设计底线

问数项目直接操作数据库,安全设计必须放在第一位。我第一版就确定了几条原则,后续不管是加功能还是改架构都不会突破这层底线。

数据库账号用只读账号,从根源上杜绝写操作。SQL校验在应用层做一层规则拦截,危险关键字直接打回。但规则拦截不是全部,数据库账号层面的只读是最底层的保证,这两者不能互相替代。

所有查询强制加LIMIT,默认100行,防止业务人员一条SQL拉千万行数据。查询打标,用户ID、会话ID、生成的SQL、执行耗时全部写入日志,方便做审计回溯。

6.3 现阶段的心得与后续架构演进方向

问数项目第一版跑通之后,我对AI Agent开发最大的感受是:架构的价值不在"用上最新框架",而在把复杂问题拆解成可维护的模块,每个模块负责一小块,出了问题能快速定位修补。

LandGraph这套图编排的方式,在问数这个场景下真的比传统Agent框架顺手得多。之前用纯LangChain的时候,每个节点的输入输出全靠模型自己控制,排错经常要靠猜。换成LangGraph之后,每个节点是明确的Python函数,状态流转清清楚楚,调试的时候直接打印状态对象就能看到全部信息。

接下来的演进方向,我打算在几个方面继续深入:一是Schema感知维度继续扩展,增加数据血缘信息,让Agent能理解"这个字段是从哪张表汇总出来的";二是结果可视化能力增强,不只是生成图表,而是能根据数据特征自动选择最合适的图表类型;三是引入反馈闭环,把用户的点赞点踩数据收集起来,作为Prompt优化和Schema权重调整的依据。

最后分享一个小技巧:问数项目的Prompt测试一定要做成自动化。我维护了一个覆盖50多个典型问题的测试集,每次改Prompt都跑一遍回归,用"SQL生成是否准确、结果是否有重大偏差"做自动判定。别信"感觉变好了"这种主观判断,AI项目的效果评估必须量化。

这个系列后续会继续更新,下一篇文章重点讲Schema感知模块的实现细节,包括离线索引管道怎么搭建、向量检索的排序策略怎么调优,到时候再聊。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 5:27:24

收银系统怎么选?从餐饮到零售的选型避坑指南与主流厂商盘点

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 5:25:52

Python+SQLite+tkinter构建图书馆管理系统:数据库设计大作业全解析

简介:一份面向高校数据库系统大作业的图书馆管理系统完整方案,采用Python与PyQt5开发GUI图形界面,后端使用MySQL 8.0,资源内包含完整SQL脚本和程序源码,适合正在完成课程设计或需要快速搭建可运行项目、同时想学习数据…

作者头像 李华
网站建设 2026/9/11 5:24:41

滚刀状态识别实战:从振动信号特征工程到CNN/SVM模型部署

简介:面向刀具磨损状态识别场景的机器学习项目资源包,整合CNN、LSTM、GRU、SVM、随机森林等多种模型,用于解决滚刀走刀数据下的磨损阶段分类问题。整个资源包共包含15个文件,核心为8个Python脚本,分别负责数据合并、特…

作者头像 李华
网站建设 2026/9/11 5:24:03

机器学习量化策略实战:backtrader多股回测与过拟合检验

简介:面向金融量化入门者及Python开发者的机器学习量化投资实战项目,集数据获取、特征工程、LightGBM建模与历史回测于一体。项目内置10支股票样例,通过命令行即可完成从安装依赖到回测评估的完整流程,并输出累积收益、最大回撤、…

作者头像 李华