jiawei 83b1742e8f
my-v0-server / deploy (push) Successful in 49s
Merge pull request 'feat:优化演示' (#15) from feat/0.3.0 into main
Reviewed-on: #15
2026-10-18 20:27:33 +08:00
2026-10-18 05:24:29 -07:00
2026-10-02 02:36:11 -07:00
2026-10-15 03:38:20 -07:00
2026-10-13 02:41:13 -07:00
2026-10-18 02:51:44 -07:00
2026-10-12 00:07:07 -07:00
2026-10-14 08:19:52 -07:00
2026-10-01 23:08:06 -07:00
2026-10-10 02:02:17 -07:00
2026-10-14 08:33:32 -07:00
2026-10-10 02:02:17 -07:00

Screen Agent

前端仓库:jiawei/my-v0

可视化大屏编辑器的后端服务,提供两部分能力:

  • AI 编辑:把自然语言需求转换为经过校验的结构化编辑动作,由前端应用到画布;支持上传数据文件,并用查询结果直接制图。
  • 大屏管理:大屏的保存、版本发布、回收站与线上访问。

功能

  • 自然语言新建大屏,增删、更换图表,修改组件属性、位置、尺寸与画布,支持对齐和分布。
  • 上传 CSV / TSV / Excel / JSON / JSONL / Parquet,对数据问答、汇总,并将查询结果填入图表。
  • 动作按物料字段定义校验,并在画布副本上整批模拟执行;失败原因回传 Agent 修正,仅交付通过的动作。
  • 多轮对话;信息不足时暂停任务向用户澄清,回答后继续,也可取消。
  • 通过 SSE 推送处理进度、问答文本增量与最终结果。
  • 大屏保存(乐观锁)、发布快照与历史版本、分享链接、回收站、封面图、数据源服务端代理。

架构

flowchart LR
    Client[大屏编辑器] --> API[FastAPI]
    API --> Graph[LangGraph 工作流]
    Graph --> Intent[意图判断]
    Intent -->|问答| QA[问答 Agent]
    Intent -->|其他| Screen[大屏 Agent]
    Screen --> MCP[MCP 物料查询]
    Screen --> Batch[动作校验与模拟]
    QA --> Data[DuckDB / Parquet]
    Screen --> Data
    Graph -->|SSE| Client
    API --> Mongo[(MongoDB)]

外层 LangGraph 负责路由、状态检查点与澄清恢复,内层 LangChain Agent 通过工具循环完成任务。意图由 TypeSafe Jev 判断,仅在明确为问答且概率达到阈值时进入问答分支。

组件 技术
Web / 模型 FastAPI、Pydantic
Agent 工作流 LangGraph、LangChain(langchain-openai)
意图判断 TypeSafe Jev
物料与字段查询 MCP(mcp_servers/,由应用自动拉起,端口 8201)
存储 MongoDB(物料、会话、检查点、文件元数据、大屏)
数据文件 python-calamine、PyArrow(Parquet)、DuckDB
观测 Loguru、Langfuse(可选)

记忆与上下文管理

大屏是唯一的事实来源:每次请求由前端带来完整画布,记忆只保存画布上看不出来的东西,例如做过哪些修改、问答用过哪些查询。画布状态不进记忆,用户在前端手动修改或撤销后,不会出现记忆和画布不一致。

范围 做法
单次运行 Agent 在工具循环里完成任务,模型调用次数有上限(MAX_AGENT_STEPS、MAX_QA_STEPS),上下文不压缩
同一会话 服务端按 conversation_id 读取历史,不采用前端传来的历史。最多带最近 CONVERSATION_HISTORY_TURNS(20)轮,再按 HISTORY_MAX_TOKENS(10000,o200k 计数,消息和记录合计)从最近一轮往前整轮保留;最近一轮总是保留,单独超出预算时截掉中间、保留开头和结尾
澄清恢复 任务暂停时状态存入检查点,恢复后同一任务覆盖保存为一轮,追问和回答记在这一轮里
跨会话 暂不做,新会话从当前画布开始

每轮除用户原话和回复外,服务端从运行结果中记下轮次记录,不经过模型:

  • changes:交付的修改,按原始画布与交付后画布逐组件比较,记为新增、修改或删除
  • queries:问答中成功执行的 SQL,以及结果的列和行数,不保存结果本身
  • clarifications:本轮的追问和用户的回答

下一轮请求时,原话和回复作为对话消息;记录作为 history_records 放进请求 JSON,不拼进消息。其中 on_screen 按当前画布计算,组件被撤销后不会被误认为还在。读取规则见 app/prompt/domain.py。意图判断只看原话、回复和澄清,不看 SQL 和修改记录。

暂不采用滚动摘要、向量检索和用户级偏好:各轮多是对可见画布的独立修改,摘要容易失真。跨会话的长期要求(如“金额统一用万元”)计划以大屏级备忘实现,待真实使用中出现需要时再做。

快速开始

依赖:Python ≥ 3.11、uv、MongoDB、支持工具调用与结构化输出的 OpenAI 兼容聊天模型服务、TypeSafe API Key。

uv sync --locked
cp .env.example .env     # 填写下表中的配置
uv run python -m scripts.seed_materials   # 导入物料目录,见下方说明
uv run uvicorn app.main:app --host 127.0.0.1 --port 8000

启动后访问 http://127.0.0.1:8000/docs 查看完整接口文档。

配置 说明
LLM_API_KEY LLM_MODEL LLM_BASE_URL 聊天模型。默认发送 reasoning_effort=low,服务端不支持时设 LLM_REASONING_EFFORT=
TYPESAFE_API_KEY TYPESAFE_DEFAULT_MODEL 意图判断。模型固定为 jev-1.13.0,阈值按该版本校准,换版本需重新评测
MONGODB_URI MONGODB_DB 物料目录与大屏存取必需;未配置时会话与检查点退回进程内存,大屏接口返回 503
AUTH_ENABLED USER_CENTER_URL 鉴权。本地开发设 AUTH_ENABLED=false;开启后请求携带 Authorization: Bearer <token>,服务调用用户中心 GET /api/users/me 校验
LANGFUSE_TRACING_ENABLED 未部署 Langfuse 时设为 false

全部配置及默认值见 .env.example 与 app/config.py。

物料初始化:物料定义位于 app/resources/materials,必须导入 MongoDB 后服务才能增改组件;导入会整体替换现有目录,之后需重启服务。导入脚本为 scripts/seed_materials.py,可附带自定义物料目录作为参数。

接口

所有接口以 /api 为前缀,JSON 响应统一为 {code, data, msg}。除标注外均需登录。

Agent

接口 说明
POST /agent/run 提交需求与当前画布,返回 SSE
POST /agent/resume 回答澄清、选择选项或取消任务,返回 SSE

请求示例:

{
  "prompt": "在画布顶部添加标题:销售数据概览",
  "screen": { "canvas": { "width": 1920, "height": 1080 }, "nodes": [] },
  "context": { "conversation_id": "<POST /conversations 返回的 ID>" }
}

每次 run 提交画布的完整快照;同一段对话复用 conversation_id,历史由服务端读取。

SSE 事件:

事件 含义
progress 当前处理阶段
answer_delta 问答文本增量,最终以 final.data.answer 为准
final 本轮结果,data.status 见下
error 流开始后的执行异常

final.data.status:completed(有 actions 时由前端按序应用)、waiting_for_input(展示 clarification,用 thread_id 调用 resume)、failed(业务失败,不交付动作)、cancelled。流开始前的错误以 HTTP 状态码返回;未收到 final 或 error 即断开,应视为结果不完整。

会话

接口 说明
POST /conversations 创建会话
GET /conversations 分页列出当前用户的会话
GET /conversations/{id} 读取会话历史
PATCH /conversations/{id} 重命名
DELETE /conversations/{id} 删除

数据文件

上传后后台解析(HTTP 202),轮询进度至 ready 后即可在同一会话中被 Agent 使用;已解析且未过期的文件自动带入后续对话。

接口 说明
GET /files/limits 上传限制与支持格式(无需登录)
POST /files multipart/form-data 上传,需带 conversation_id
GET /files?conversation_id= 会话下的文件
GET /files/{id} 文件详情与表信息
GET /files/{id}/progress 解析进度
GET /files/{id}/tables/{table}/rows 分页、排序读取
POST /files/{id}/tables/{table}/aggregate 分组汇总
DELETE /files/{id} 删除

大屏管理

大屏仅所有者可访问,他人的大屏与不存在同样返回 404。保存与发布需携带 revision,与服务端不一致时返回 409。

接口 说明
POST /screens 创建
GET /screens 列表:关键字、状态、排序、分页,deleted=true 查看回收站
GET /screens/{id} 详情
PUT /screens/{id} 保存(乐观锁)
PATCH /screens/{id} 重命名
DELETE /screens/{id} 移入回收站,默认保留 30 天后自动清除
POST /screens/{id}/restore 从回收站恢复
DELETE /screens/trash 清空回收站
POST /screens/{id}/publish 发布当前版本,首次发布生成 share_id
POST /screens/{id}/unpublish 下线
GET /screens/{id}/publishes 发布历史
POST /screens/{id}/publishes/{version}/restore 将历史版本恢复为草稿
POST /screens/{id}/copy 复制
PUT /screens/{id}/thumbnail 上传封面图(≤ 1 MB)

公开与其他

接口 说明
GET /public/screens/{share_id} 线上版本(发布快照),匿名;数据源 headers 不下发
GET /public/screens/{share_id}/datasources/{id} 线上取数,请求配置取自发布快照,匿名
GET /public/thumbnails/{id} 封面图,匿名
POST /datasource/fetch 编辑态数据源代理;仅允许公网 http(s) 地址,限 5 秒、2 MB
GET /materials 组件物料目录(无需登录)

项目结构

app/
├── api/          HTTP 路由
├── services/     会话、大屏、物料、数据源代理与持久化装配
├── processor/    LangGraph 工作流与节点
├── agent/        大屏 / 问答 Agent、工具、Skills 加载
├── actions/      动作执行、布局计算、整批模拟
├── datafiles/    数据文件解析、存储、查询与后台任务
├── schemas/      请求、画布、动作、会话、大屏模型
├── resources/    物料定义与字段规则
├── clients/      LLM、Jev、MCP、用户中心客户端
├── prompt/       提示词
└── core/ common/ observability/   认证、异常、日志、响应与 SSE、追踪
mcp_servers/      应用管理的本地 MCP 服务(配置见 mcp_servers.json)
skills/           大屏设计、编辑、图表替换与数据制图规则

阅读主链路:app/api/agent.py → app/services/agent.py → app/processor/graph.py → app/agent/screen_agent.py → app/actions/batch.py。动作协议定义在 app/schemas/actions。

部署注意

  • 单实例:任务与会话的并发控制、上传进度保存在进程内,请以单 worker 运行;同一会话同时只能执行一个任务。
  • 本地存储:数据文件与封面图写入磁盘(DATA_FILE_DIR、THUMBNAIL_DIR,默认在 data/ 下),容器部署需挂载持久卷。
  • 反向代理:SSE 需关闭响应缓冲并放宽读取超时;上传大小限制需与 DATA_FILE_MAX_MB 一致。应用未配置 CORS,请通过同源代理转发 /api。
  • 连接中断:客户端断开会取消当前任务,不支持心跳、事件重放或断线续传。
  • 历史计数:会话历史用 tiktoken 的 o200k 编码表计数。Docker 镜像在构建时下载好;其他方式部署时首次请求会联网下载,离线环境需预先放入 TIKTOKEN_CACHE_DIR。下载失败时退回按字符估算,不影响请求。
  • 日志:写入 logs/app.log。

开发

扩展组件:修改物料定义,重新导入后重启。调整 Agent 行为:修改 skills 与 app/prompt。新增 MCP 服务:修改 mcp_servers.json,连接配置支持 ${环境变量} 展开。

S
Description
No description provided
Readme
963 KiB
Languages
Python 99.8%
Dockerfile 0.2%