news 2026/9/25 11:36:58

3步!用 Doris MCP + LangChain 搭建 AI 问数系统:TaoToken 统一 Key 配置与验证

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
3步!用 Doris MCP + LangChain 搭建 AI 问数系统:TaoToken 统一 Key 配置与验证

1. 为什么 Doris MCP + LangChain 值得你花一个下午跑通

如果你手上已经有一套 Apache Doris 集群,TPC-H 或者业务表都躺在里面,但每次取数还得写 SQL、找字段注释、跟业务方来回确认口径,那 Doris MCP + LangChain 这套组合就是为你准备的。它要做的事情很直接:把「自然语言 → Doris SQL → 执行 → 带业务解读的结果」这条链路串起来,让你用一句话就能问出「哪个客户下单最多」这种问题,而不是先翻三张表的 schema。

Doris 本身是 MPP 架构的实时分析数据库,向量化执行引擎在 PB 级数据上也能做到秒级响应,这是它能扛住 AI 问数背后高频查询的前提。LangChain 负责的是 Agent 编排:把大模型、工具调用、提示词模板拼成一个可执行链路。而 MCP(Model Context Protocol)是中间那层标准化接口,让 LangChain 不用为 Doris 单独写一堆 Connector,直接通过 MCP Server 暴露的工具就能拿到库表信息、执行 SQL。

这套方案适合谁?三类人最合适:一是已有 Doris 数据源、想快速验证 AI 问数可行性的数据开发;二是正在学 LangChain Agent、想找一个真实数据库场景练手的工程师;三是团队里负责数据平台、想给业务方做一个「能对话的取数入口」的人。整条链路跑通不需要你改 Doris 源码,也不需要自己维护元数据映射,配置量集中在两个文件和一个 Key 上。

我试过把这套流程从零搭一遍,卡点基本都在 Key 配置和 MCP 连通性上,所以下面会把 TaoToken 统一 Key 的配置骨架、三步验证动作写清楚,你照着复制就能复现。

2. TaoToken 统一 Key:一处配置,LangChain 与 MCP 共用

在原始方案里,LangChain 侧要配 DeepSeek 或其它模型的 API Key,MCP Server 侧要配 Doris 的连接信息,两边 Key 管理是分开的。如果你后面还要接 Claude Code、Cursor 或者别的 Agent 工具,Key 会散落在多个配置文件里,换一次 Key 要改一圈。

TaoToken 在这里的角色是统一入口:它提供兼容 OpenAI 协议的 API 端点,LangChain 的init_chat_model可以直接指向它,MCP 侧如果涉及模型调用也能复用同一个 Key。这样你只需要维护一份 Key,配置集中在config.toml和settings.json两个文件里。

先拿 Key。访问控制台创建 API Key:

https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=console

创建后在 API Keys 页面复制,格式通常是sk-开头的一串。这个 Key 同时用于 LangChain 的模型调用和后续 MCP 工具链里的模型请求。

接入文档在这里,配置项含义可以对照查:

https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=doc

API 基础地址是:

https://taotoken.net/api

注意这个地址不加 UTM 参数,直接作为base_url使用。LangChain 的 OpenAI 兼容接口会在这个地址后面拼/v1/chat/completions,所以你在配置里填https://taotoken.net/api即可,不要手动加/v1。

2.1 config.toml 配置骨架

config.toml放在项目根目录,用于 LangChain 侧读取模型配置:

[llm] provider = "openai" model = "claude-3-5-sonnet" base_url = "https://taotoken.net/api" api_key = "sk-你的TaoTokenKey" temperature = 0.2 max_tokens = 4096 [mcp] server_name = "doris_mcp_server" transport = "streamable_http" url = "http://localhost:3000/mcp" timeout = 30 [doris] host = "127.0.0.1" port = 9030 user = "root" password = "你的Doris密码" database = "tpch"

temperature设 0.2 是为了让 SQL 生成更稳定,问数场景不需要太高的创造性。max_tokens给 4096 是因为 Doris 表结构信息加上查询结果可能比较长。

2.2 settings.json 配置骨架

settings.json用于 MCP Server 侧和部分工具链读取,字段和config.toml对应但格式是 JSON:

{ "llm": { "provider": "openai", "model": "claude-3-5-sonnet", "base_url": "https://taotoken.net/api", "api_key": "sk-你的TaoTokenKey" }, "mcp": { "server_name": "doris_mcp_server", "transport": "streamable_http", "url": "http://localhost:3000/mcp" }, "doris": { "host": "127.0.0.1", "port": 9030, "user": "root", "password": "你的Doris密码", "database": "tpch" } }

两个文件里的api_key填同一个 TaoToken Key。如果你用环境变量管理,可以把 Key 写成${TAOTOKEN_API_KEY},然后在.env里定义,避免明文提交到仓库。

注意:base_url只填到https://taotoken.net/api,不要写成https://taotoken.net/api/v1,否则 LangChain 会拼出/api/v1/v1/chat/completions导致 404。

3. 可复制配置:Doris MCP Server 与 LangChain 链路搭建

配置骨架有了,接下来把 MCP Server 跑起来,再写 LangChain 侧的调用代码。这一步的目标是让 MCP 工具能被 LangChain 发现并调用。

3.1 启动 Doris MCP Server

先把 MCP Server 克隆到本地并安装依赖:

git clone https://github.com/apache/doris-mcp-server.git cd doris-mcp-server pip install -r requirements.txt

配置 Doris 连接信息,编辑.env:

cp .env.example .env vim .env

填入:

DORIS_HOST=127.0.0.1 DORIS_PORT=9030 DORIS_USER=root DORIS_PASSWORD=你的Doris密码 DORIS_DATABASE=tpch

启动服务:

./start_server.sh &

看到Uvicorn running on http://0.0.0.0:3000就说明 MCP Server 起来了。这个 3000 端口就是config.toml里mcp.url对应的地址。

3.2 LangChain 侧读取配置并初始化 Agent

Python 版本需要 >= 3.12。依赖装这些:

pip install langchain langchain-community langchain-openai langchain-mcp-adapters python-dotenv aiohttp aiofiles tomli

下面是读取config.toml并初始化 Agent 的核心代码:

import asyncio import tomli from langchain.agents import AgentExecutor, create_openai_tools_agent from langchain.chat_models import init_chat_model from langchain.prompts import ChatPromptTemplate from langchain_mcp_adapters.client import MultiServerMCPClient def load_config(path="config.toml"): with open(path, "rb") as f: return tomli.load(f) async def build_agent(): cfg = load_config() llm_cfg = cfg["llm"] mcp_cfg = cfg["mcp"] mcp_client = MultiServerMCPClient({ mcp_cfg["server_name"]: { "transport": mcp_cfg["transport"], "url": mcp_cfg["url"], } }) tools = await mcp_client.get_tools() if not tools: raise RuntimeError("MCP 工具加载为空,检查 MCP Server 是否启动") llm = init_chat_model( model=llm_cfg["model"], model_provider=llm_cfg["provider"], api_key=llm_cfg["api_key"], base_url=llm_cfg["base_url"], temperature=llm_cfg["temperature"], ) prompt = ChatPromptTemplate.from_messages([ ("system", "你是 Doris 问数助手,先调用工具获取库表信息,再生成 SQL 并执行,最后给出业务解读。"), ("human", "{input}"), ("placeholder", "{agent_scratchpad}"), ]) agent = create_openai_tools_agent(llm, tools, prompt) return AgentExecutor(agent=agent, tools=tools, verbose=True, max_iterations=3) async def main(): executor = await build_agent() result = await executor.ainvoke({"input": "当前 Doris 有哪些库表?"}) print(result["output"]) if __name__ == "__main__": asyncio.run(main())

这段代码和原始方案的区别在于:模型配置从config.toml读取,base_url指向 TaoToken,Key 只维护一份。max_iterations=3是防止 Agent 在工具调用上死循环,问数场景一般两轮内就能出结果。

3.3 关键参数对照

参数作用建议值
transportMCP 通信方式streamable_http
urlMCP Server 地址http://localhost:3000/mcp
temperature模型随机性0.2
max_iterationsAgent 最大工具调用轮数3
base_urlTaoToken API 地址https://taotoken.net/api

4. 三步验证:从 MCP 连通性到问数结果比对

配置写完不代表链路通了,按下面三步验证,每步都有明确的成功标志。

4.1 第一步:MCP 工具连通性检查

先单独验证 MCP Server 是否暴露了工具。写一个最小脚本:

import asyncio from langchain_mcp_adapters.client import MultiServerMCPClient async def check(): client = MultiServerMCPClient({ "doris_mcp_server": { "transport": "streamable_http", "url": "http://localhost:3000/mcp", } }) tools = await client.get_tools() print(f"发现 {len(tools)} 个工具") for t in tools: print("-", t.name) asyncio.run(check())

成功标志:输出工具数量大于 0,且能看到类似get_db_list、execute_sql这样的工具名。如果输出 0 个工具,先检查 MCP Server 日志里有没有报 Doris 连接失败。

4.2 第二步:LangChain 链路调用

用 3.2 的代码跑一次当前 Doris 有哪些库表?。成功标志:控制台打印出库表列表,且verbose=True下能看到 Agent 调用了 MCP 工具。这一步验证的是 LangChain → TaoToken → 模型 → MCP 工具这条完整链路。

如果报401,检查api_key是否填对;如果报404,检查base_url是否多写了/v1;如果报Connection refused,检查 MCP Server 是否还在运行。

4.3 第三步:问数结果比对

最后用一句自然语言查询验证端到端效果:

result = await executor.ainvoke({ "input": "请切换到 tpch 库,分析哪个客户下单最多" }) print(result["output"])

成功标志:Agent 自动生成 Doris SQL、执行查询、返回客户名称和订单数,并附带业务解读。为了确认结果可信,你可以手动在 Doris 里跑一遍对应的 SQL 比对:

SELECT c_name, COUNT(*) AS order_count FROM tpch.orders o JOIN tpch.customer c ON o.o_custkey = c.c_custkey GROUP BY c_name ORDER BY order_count DESC LIMIT 1;

两边结果一致,说明问数链路从配置到出数全程可复现。

5. 本篇常见错排查

5.1 MCP Server 启动后工具列表为空

最常见的原因是.env里 Doris 连接信息不对。MCP Server 启动时如果连不上 Doris,工具注册会失败但进程不一定退出。检查DORIS_HOST、DORIS_PORT、DORIS_USER、DORIS_PASSWORD四项,确认 Doris FE 的 9030 端口可以从本机访问。

5.2 LangChain 报 base_url 相关 404

TaoToken 的 API 地址是https://taotoken.net/api,LangChain 的 OpenAI 兼容层会自动拼/v1/chat/completions。如果你在config.toml里写成https://taotoken.net/api/v1,最终请求路径会变成/api/v1/v1/chat/completions,返回 404。改回不带/v1的地址即可。

5.3 Agent 不调用工具直接回答

如果模型没有调用 MCP 工具,而是直接编造了一个答案,通常是 system prompt 不够明确。把 system prompt 改成「必须先调用工具获取库表信息,再生成 SQL,禁止凭记忆回答」,并把temperature降到 0.1。另外确认tools列表非空,空工具列表下 Agent 只能靠模型自身知识回答。

5.4 查询结果与手动 SQL 不一致

先确认 Agent 生成的 SQL 里库名和表名是否正确。Doris 里跨库查询需要写全库名.表名,如果 Agent 只写了表名,可能查到了默认库。可以在 system prompt 里加上「生成 SQL 时必须带库名前缀」。另外检查tpch数据是否完整导入,TPC-H 的orders和customer表数据量对不上会导致结果偏差。

5.5 长时间无响应或超时

MCP 的timeout默认 30 秒,如果 Doris 查询本身较慢,可以调到 60。LangChain 侧如果max_iterations设得过大,Agent 可能反复调用工具,建议保持 3。TaoToken 侧如果模型响应慢,可以在config.toml里换一个更轻量的模型做问数场景。

6. 继续往下走:从跑通到日常使用

三步验证跑通之后,这套系统就可以进入日常使用了。如果你主要用它做交互式问数,可以直接在模型对话页面测试不同问法,观察 Agent 的工具调用策略:

https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=model-chat

如果你打算把问数能力接到长期运行的编码或 Agent 工作流里,比如让 Claude Code 通过 MCP 直接查 Doris,那 Key 的稳定性和额度管理就比单次调用更重要,可以看 Coding Plan:

https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=coding-plan

Key 管理和新建入口在控制台:

https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=console

API Keys 页面:

https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=api-keys

接入文档:

https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=doc

Claude Code 接入说明:

https://taotoken.net/ClaudeCodeAnthropic?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=ClaudeCodeAnthropic

最后留一个实操建议:把config.toml和settings.json里的 Key 换成环境变量引用,然后在.gitignore里加上.env。问数系统跑通只是第一步,Key 不泄露、配置可复现,才能让这套链路在团队里真正用起来。

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

Backspace长按失效?Windows与Linux键盘重复机制排查指南

1. 问题现象与核心影响范围Backspace 键长按不能连续删除、按一下只删一个字符,这个问题我前后遇到过不下十次,分布在 Windows 10、Windows 11、Windows Server 2016 以及几台 Ubuntu 和统信 UOS 机器上。表面上看是个小毛病,但它对日常操作效…

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

P201Pro与GNU Radio实战:AD9361 SDR链路QPSK星座图调试全解析

1. 从一根天线到一串比特:这条链路到底在做什么把一台 P201Pro 插上电脑,打开 GNU Radio,拖几个模块连起来,屏幕上就能看到 QPSK 的星座点簇——这件事听起来像是"点几下鼠标"的活儿,但真正做过的人都知道&a…

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

sqli-labs 29-32关:HPP与宽字节注入绕过WAF全解析

如果你刷到了 sqli-labs 的 29 关,前面那些“加个引号就报错、union select 就出数据”的快乐日子基本到头了。从这一关开始,靶场给你模拟了一个 WAF,到 32 关又给参数套上了 addslashes 转义,之前那些裸奔的 payload 打过去&…

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

n8n智能体开发:Docker-Compose 部署配 TaoToken 统一 Key 通道

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

作者头像 李华