mirror of
https://github.com/ThearchyHelios/AgentLab.git
synced 2026-11-15 02:51:58 +00:00
39e7a5b014
阶段①。产品原先能取数的只有 http_request 和沙箱里自己写代码——面对"分析上季度
华东区销量下滑"这类需求,用户得自己知道数据在哪张表、字段叫什么,再手写 SQL 塞进
代码节点。最难的部分留给了用户。
## 连接层(app/data/)
方言差异全收敛在 engine.py 一处:Oracle 要 service_name/sid、MySQL 要 charset、
各家默认端口不同。三个驱动都是 asyncio 原生且免装客户端——oracledb 走 thin 模式,
不需要 Instant Client。密码复用 app/core/crypto 的 Fernet,和 Provider 同一套;
build_url 默认把密码替换成星号,日志和错误信息里用这个版本。
introspect.py 产出两种粒度:summary()(表名+代表字段,几百 token,给 Copilot 的
system prompt 用)和 describe_table()(单表完整字段,按需取)。分两种是因为一个
中等业务库全量塞进 prompt 轻松几万 token,既贵又会把真正的需求淹掉。
## 守卫(app/data/guard.py)
这是唯一不能出错的地方:SQL 由模型生成,模型会写出什么事前无法穷举,防线不能
建立在"它应该不会这么干"上。三层:
- 只读判定用**白名单**而非黑名单——黑名单永远漏,MERGE/CALL/GRANT/各家私货写不完
- 多语句在到达驱动前就断掉,不赌驱动默认只跑第一条(MySQL 开了
CLIENT_MULTI_STATEMENTS 就会全跑)
- 行数/字节/超时三重上限,一条 SELECT * 不该把内存和模型上下文一起打爆
刻意不引 sqlparse:完整解析 SQL 方言是无底洞,而这里的判断很窄——"首关键字是
什么"和"有没有第二条语句"。窄问题用窄解法。难点是不能误杀:`SELECT ';'` 只是
一条语句,简单 split(";") 会把它切两半然后拒掉,那比漏杀更让人无从下手。
## 工具(app/tools/datasource.py)
每个数据源动态生成一对 db_query__<源> / db_schema__<源>,而不是一个通用工具带
datasource 参数:工具名自带语义,模型不会把查销售库的 SQL 发给财务库;description
里直接塞表清单,省掉"先问有哪些表"那一轮。接进 registry.build_tools 作为第四来源
(前三个是内置/MCP/自定义)。
查询结果落 put_json(kind="query_snapshot"),把 SQL 原文 + 结果集 + 数据源一起存,
出具体系的数字回指能下钻到"这个数是哪条 SQL 查出来的"。
## 实测
真实 SQLite 业务库(600 行订单,埋了华东 6 月断崖的信号)+ 真实模型:
agent 8 轮自主查询——列表 → 查三张表结构 → 探数据时间范围 → 查地区维度 →
按月汇总 → 按地区+月份下钻,准确定位到华东 6 月从 1187 件跌到 354 件。
只读守卫在 agent 路径上同样生效(UPDATE/DROP/多语句全被拒且数据未变)。
测试 55 项:守卫 30 项(含"字符串里的分号不能误杀")、连接与探查 15 项、
URL 构造 6 项、Copilot 流式 4 项。
46 lines
1.5 KiB
TOML
46 lines
1.5 KiB
TOML
[project]
|
|
name = "agentlab-backend"
|
|
version = "0.1.0"
|
|
description = "AgentLab — 可视化 Agent 编排实验台后端"
|
|
requires-python = ">=3.12"
|
|
dependencies = [
|
|
"fastapi>=0.115",
|
|
"uvicorn[standard]>=0.32",
|
|
"pydantic>=2.9",
|
|
"pydantic-settings>=2.6",
|
|
"sqlalchemy[asyncio]>=2.0.36",
|
|
"aiosqlite>=0.20",
|
|
"greenlet>=3.1",
|
|
"httpx>=0.28",
|
|
"python-multipart>=0.0.17",
|
|
"langgraph",
|
|
"langgraph-checkpoint-sqlite",
|
|
"langchain-core",
|
|
"langchain-anthropic",
|
|
"langchain-openai",
|
|
"langchain-mcp-adapters",
|
|
"mcp",
|
|
"numpy>=2.0",
|
|
"jsonschema>=4.23",
|
|
"beautifulsoup4>=4.12",
|
|
"cryptography>=43.0",
|
|
]
|
|
|
|
[project.optional-dependencies]
|
|
# microVM 沙箱(独立 Linux 内核)。约 35MB wheel + 首次约 50MB 运行时下载,
|
|
# 再加一次 OCI 镜像拉取(实测约 55s),所以不进默认安装。
|
|
# environment.yml 里已经带上了;单独装用 `pip install 'agentlab-backend[microvm]'`。
|
|
microvm = ["microsandbox>=0.6"]
|
|
# 测试:conda 环境默认不装,跑测试前 pip install 'agentlab-backend[dev]'
|
|
dev = ["pytest>=8.0", "pytest-asyncio>=0.24"]
|
|
# 数据库接入。三个驱动都是 asyncio 原生且免装数据库客户端——
|
|
# oracledb 走 thin 模式,省掉了 Oracle Instant Client 这个历来最劝退的一步。
|
|
db = ["aiomysql>=0.2", "oracledb>=2.0", "asyncpg>=0.30"]
|
|
|
|
[build-system]
|
|
requires = ["hatchling"]
|
|
build-backend = "hatchling.build"
|
|
|
|
[tool.hatch.build.targets.wheel]
|
|
packages = ["app"]
|