在 Open WebUI 中构建 MCP 代理:从基础工具到智能规划器
在 Open WebUI 中,MCP 代理的起点很简单——我们给大语言模型(LLM)一组与 ClickHouse 交互的工具,然后观察其表现。最初,系统提供三个基础工具:list_databases、list_tables 和 run_select_queries,它们能处理简单的 SQL 查询。但随着任务复杂度提升,模型开始难以理解数据结构。
解决方案:使用包含具体查询示例的详细提示词。提示结构中包含变量(如 portfolio_name、start_date、end_date),明确说明 LIKE 过滤规则,并采用类似 Dt::date >= '{start_date}' 的模式。例如,计算投资组合绩效时可使用窗口函数:
WITH log_coef as (SELECT Portfolio, Dt,
sum(log(TWR_dod+1)) OVER (
PARTITION BY InvestmentPortfolioID
ORDER BY Dt ASC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 FOLLOWING
) AS TWR_cumulative_coef
FROM Contribution.contribution_twr_1s_mcp
WHERE lowerUTF8(Portfolio) LIKE '%{portfolio_name}%'
AND Dt::date >= {start_date}
AND Dt::date <= {end_date}
ORDER BY Dt DESC)
SELECT Portfolio, Dt, exp(TWR_cumulative_coef) - 1 AS TWR_cumulative
FROM log_coef;
结果有所改善,但仍不稳定——语法错误和指标错误持续存在。Open WebUI 中的 RAG 也无法解决这些问题。
扩展工具集:无幻觉的自定义工具
迈向确定性:我们基于 Pydantic 模型构建预定义工具。LLM 只负责选择并参数化这些工具,而查询逻辑固定不变。工具类包括:
ClickHouseClientBase:封装核心 MCP 操作的包装器。ProfitTool:计算收益(按日期的 TWR,算术/几何平均)。PortfolioDiscoveryTool:发现投资组合属性(列表、类型、策略)。PortfolioCashflowTool:追踪资金流入流出,进行现金流分析。
以 ClickHouseClientBaseParams 为例:
class ClickHouseClientBaseParams(BaseModel):
operation: Literal['list_databases', 'list_tables', 'run_select_query'] = Field(
description='操作类型:list_databases、list_tables 或 run_select_query'
)
database: Optional[str] = Field(default=None, description='数据库名称')
query: Optional[str] = Field(default=None, description='SQL 查询语句')
like: Optional[str] = Field(default=None, description='LIKE 匹配条件')
not_like: Optional[str] = Field(default=None, description='NOT LIKE 条件')
def clickhouse_client_base(params: ClickHouseClientBaseParams) -> str:
# 通过 HTTP 请求调用 http://clickhouse-mcp.services.kfim.int
# 处理 list_databases、list_tables、run_select_query
# 自动将 contribution_twr_1s_mcp 替换为完整表名
pydantic_to_openai_schema 函数将这些模型转换为 OpenAI 兼容格式,彻底消除幻觉——工具始终返回可预测的 JSON 结果。
此方法的优势:
- 确定性:相同输入 → 相同输出。
- 可扩展性:新增指标只需添加新工具。
- 可调试性:查询逻辑清晰透明,无黑箱 LLM 行为。
简单性的局限:当工具无法应对复杂任务
一个简单的代理在复杂任务面前失效:多投资组合、聚合计算、JOIN 操作。模型容易混淆窗口函数与日期过滤逻辑。即使提供示例,错误率仍高达 30–40%。要实现大规模投资组合分析,必须处理海量数据——数以千计的 TWR 行记录和现金流条目。
升级方案:拆分为规划器与执行器
第二代架构:代理升级为 ReWOO(推理 + 执行)。规划器(独立的 LLM)将任务分解为步骤;执行器则调用工具按计划执行。该方案解决了以下问题:
- 数据筛选:通过
PortfolioDiscoveryTool实现跨投资组合的全文搜索。 - 流程控制:链式查询(列出 → 过滤 → 聚合)。
- 上下文管理:将多个表格合并为单一数据集用于前端渲染。
规划器生成执行计划:
- 第一步:查找
LIKE '%name%'的投资组合。 - 第二步:运行 TWR 查询。
- 第三步:聚合结果并展示。
执行器严格遵循计划,不擅自发挥。
全文搜索实战应用
面对大型数据表,预过滤至关重要。该工具使用 lowerUTF8(Portfolio) LIKE '%query%' 进行搜索,返回 ID 和类型信息。这极大提升了 run_select_query 的效率——避免全表扫描,转为精准查询。
示例流程链:
PortfolioDiscoveryTool(like='stocks')→ 返回 ID 列表。ProfitTool(portfolios=ids, dates=range)→ 获取 TWR 数据。- 合并至 Pandas/DataFrame,供前端界面使用。
核心要点总结
- 基于 Pydantic 的确定性工具 显著降低 LLM 在 SQL 生成中的错误率。
- ReWOO 架构 将规划与执行分离,适用于复杂工作流。
- 全文搜索 是高效过滤大规模 ClickHouse 数据的关键。
- Open WebUI 集成 支持顺序调用并最终呈现结果表格。
- 思维链提示 提升稳定性,即使在较弱模型上也有效。
— Editorial Team
暂无评论。