技术选型决策:对话框架与后端架构(ADR)
技术选型决策:对话框架与后端架构(ADR)
状态:已决策 · 日期:2026-06-23 · 决策者:项目负责人 + 架构评审
本文是一份 Architecture Decision Record(ADR),覆盖两件事:
- 受访者访谈端的对话框架 / generative UI 选型;
- 平台后端 Agent runtime 选型。
触发背景:有提议”整体对话框架用 Vercel AI SDK + assistant-ui”。经评估与 2026 年框架现状调研后,结论是 assistant-ui 保留、Vercel AI SDK 不采用、协议层采用 AG-UI、后端采用 Python + LangGraph。
0. 决策范围澄清(很重要)
“对话框架”这个词容易被放大成”整个前端框架”。先收敛范围:
- 只有受访者 Interview Runtime(+ Study Builder 的 Preview)是”对话 / generative UI”场景。
- Admin Console / Study Builder / Results Dashboard / Evidence Review 是常规 React 应用(表单 + 表格 + 详情面板),不套任何对话框架。让对话框架蔓延到这几块是反模式。
因此本 ADR 的”对话框架”特指:受访者端 chat timeline + Agent 工具调用驱动的交互组件渲染(render_interaction)。
关键约束(来自现有文档,决定一切)
- Agent Harness 是显式状态机,不是一个 prompt(见
02_agent_harness.md)。 - Evidence / Audit / Event-log 是一等公民:所有 tool call、interaction、transcript 必须持久化、可重放(见
01_system_architecture.md、04_structured_outputs_evidence.md)。 - 多 provider / RAG / 结构化抽取 / config 版本化(见
04_model_tool_kb_abstraction.md)。 - 开源 + 可自托管。
决策一:前端对话层 = assistant-ui + AG-UI(不引入 Vercel AI SDK)
候选与对比(假设后端非 TypeScript)
| 方案 | Python 后端契合 | generative UI | 定制自由度 | 协议/生态锁定 | 开源自托管 | 工作量 |
|---|---|---|---|---|---|---|
| A. Vercel AI SDK + assistant-ui(原提议) | ❌ 差 | ✅ | 高 | 中(Vercel 软锁定) | 中 | 中(多踩坑) |
| B2. assistant-ui + AG-UI(采用) | ✅ 好 | ✅ | 高 | 低(开放标准) | ✅ | 中 |
| B1. assistant-ui + 自定义 SSE | ✅ 好 | ✅ | 最高 | 无 | ✅ | 中 |
| C. CopilotKit + AG-UI | ✅ 好 | ✅ | 中 | 低(协议)/ 框架偏重 | ⚠️ headless 付费 | 中–高 |
| D. 完全自研 | ✅ 最好 | 自研 | 最高 | 无 | ✅ | 高 |
为什么 assistant-ui ✅
- 它不绑定 Vercel AI SDK。runtime 可插拔:
ExternalStoreRuntime/AssistantTransport/DataStream/@assistant-ui/react-ag-ui都能接自定义后端。 - generative UI(JSON-spec primitive
MessagePrimitive.GenerativeUI+ tool-UI 映射makeAssistantToolUI)正好把render_interaction工具调用映射到 React 组件,支持增量 streaming 与 component allowlist 安全机制。 - React + Next.js 的”safe default”,brownfield 友好、轻量、composable。
为什么不采用 Vercel AI SDK ❌
- 它的核心价值是 TypeScript 全栈(
streamText/generateObject/ tool orchestration 跑在 TS 后端)。本项目 Agent runtime 在 Python(见决策二),这层用不上。 - 只剩前端
useChat,而它强绑 Vercel Data Stream Protocol;v5 + FastAPI 的官方示例实测不工作(vercel/ai issue #7496),需第三方库(pydantic-ai VercelAIAdapter/py-ai-datastream/fastapi-ai-sdk)逆向实现 wire format。 - 净效果:凭空加一层协议适配 + 生态软锁定,收益≈0。本质是”让 Python 假装成 Vercel 的后端”。
- 例外:若决策二最终选 TypeScript 全栈(Mastra),则 Vercel AI SDK 重新成为自然的 UI-edge streaming 层(Mastra 在 UI edge 复用 AI SDK);此时方案退化为 A,但仍以 assistant-ui 为 UI 主体。
为什么协议层选 AG-UI
- AG-UI = Agent-User Interaction Protocol(MIT,官方 TS + Python SDK,~16 事件类型,走 HTTP/SSE/WebSocket),专解”agent ↔ 用户界面”这一段(与 MCP=agent↔tool、A2A=agent↔agent 互补)。
- 2026 已成事实标准:Google / Microsoft / AWS / Oracle 背书,LangGraph / Mastra / PydanticAI / CrewAI 原生或适配支持。
- 对本项目的直接收益:
- 前端不被后端语言绑架——后端无论 Python 还是 TS,前端 assistant-ui 都通过 AG-UI 消费,后端可替换(见决策二的”低风险”论证)。
- 原生 human-in-the-loop——受访者交互(等待用户提交)就是 HITL,AG-UI 一等支持。
- 长期可被其它 host(CopilotKit、第三方)复用。
为什么不用 CopilotKit
- 它的甜点是”在已有 app 里嵌入会读写 app-state 的 copilot”(shared state /
useCopilotReadable)。AgentSurvey 受访者端是全页、无宿主 app-state 可共享,这套能力价值不大。 - fully-headless 是 premium / 付费 early access(
useCopilotChatHeadless_c),对开源自托管是真实摩擦。 - 注:AG-UI 协议本身是 CopilotKit 开源的 MIT 标准。选 AG-UI ≠ 依赖 CopilotKit 付费;本项目用 AG-UI + assistant-ui 即可。
受访者端定制要点(无论框架,都要做对)
- 禁用 chatbot 式 edit / regenerate / branch —— 受访者不应改写 AI 的提问。
- UI 是
assistant message / interaction card / result summary混排的定制 timeline,不是标准 chatbot 气泡流。 - interaction 组件必须自研(带
output_schema/ validation /evidence_policy/ skip / a11y / 移动端),且结果走独立 session submit API(见02_api_contracts.md),而非标准 tool-result 回传。框架只负责把工具调用接到组件壳,组件本体是你的核心资产。
决策二:后端 Agent Runtime = Python + LangGraph(主线)
候选
去掉 Vercel AI SDK、前端定为 assistant-ui + AG-UI 后,后端收敛为二选一:
- Python + LangGraph(主线,本 ADR 采用)
- TypeScript 全栈 + Mastra(强备选,见决策三)
被排除:
- LangGraph 的 TS port —— 落后 Python 版 4–8 周、带 Python idioms、有真实 checkpointer 崩溃案例。要 TS 就用 Mastra,要 LangGraph 就用 Python。
- 纯自研 harness —— 把”可审计可重放的 stateful runtime”从零造一遍,不如复用成熟 runtime。
三维度评估
| 维度 | Python + LangGraph | TS 全栈 + Mastra |
|---|---|---|
| 平台能力 | ✅ 更强:checkpointing / time-travel / interrupt() 地基级;AI·RAG·抽取生态最深;LangSmith 原生可观测;企业背书广 | 够用:durable workflow(Inngest)、memory、evals、HITL;生态较新 |
| 长期演进 | ✅ 更稳:multi-agent / durable worker / cron / webhook 一方提供;explicit state-machine 可审计 | 可演进;重型 stateful / 合规验证少;2026-03 无 SOC 2 |
| 运维成本 | 略重:前端 TS + 后端 Python 双语言;部署标准(FastAPI + Postgres + Redis) | ✅ 更轻:单语言、共享 schema、单部署、上手最快 |
为什么主线选 LangGraph
AgentSurvey 是 state-heavy 平台(SessionState / CoverageState / ExtractedFieldState / DecisionLog 全是状态),核心卖点是”可信、可审计、可重放、带证据链”。LangGraph 的原语几乎是为此量身定做,把最难的基础设施直接给你:
| 文档已设计的对象 / 需求 | LangGraph 现成能力 |
|---|---|
SessionState(02_agent_harness.md) | graph state(typed,持久化) |
Session 可重放 / event-log(01_system_architecture.md) | PostgresSaver checkpointer(每个 super-step 写快照) |
| 审计 / 调试 / “为什么当时这样问” | time-travel(从任意 checkpoint fork/replay) |
waiting_for_tool 等待受访者交互 + 字段 review | interrupt()(HITL,暂停后从 checkpoint 恢复) |
| crash / 部署中断不丢会话 | durable execution(worker lease + 自动恢复) |
| Decision log / token / cost / latency | LangChain callbacks → LangSmith / OpenTelemetry / Langfuse |
MVP “固定状态机起步”(02_agent_harness.md 建议) | graph 即显式状态机,后续平滑加 multi-agent |
协同点:AG-UI 诞生自 CopilotKit × LangGraph 合作,LangGraph 上的 AG-UI 集成最一方、最成熟,与前端 assistant-ui + AG-UI 正好闭环。
落地前需验证:确认当前 LangGraph 版本对 AG-UI 事件发射的官方支持方式(原生 emitter / 适配库),以官方 AG-UI 集成文档为准。
Runtime 闭环:render_interaction 如何流动
LangGraph node 决定 render_interaction -> 通过 AG-UI 事件流(tool-call / generative-ui / state)推给前端 -> graph 调用 interrupt() 暂停,checkpointer 落盘(session=waiting_for_tool) -> assistant-ui 收到 AG-UI 事件,generative UI 解析 -> 渲染对应 interaction 组件 -> 受访者提交/跳过 -> 结果经 session submit API + AG-UI 回传 -> LangGraph 从 checkpoint resume,update state,maybe_extract / maybe_concludeinterrupt() + checkpointer 天然实现”等待受访者交互且可重放”,省去自研 pending-interaction 状态管理。
决策三:降级 / 备选路径 = TypeScript 全栈 + Mastra
触发条件(满足其一即应认真考虑切换):
- 团队 TS-only,无 Python 工程 / 运维意愿;
- MVP 极速优先,看重单语言 DX 与最低运维;
- 不需要 SOC 2 等合规背书。
对等能力: durable workflow(Inngest / 自带 runtime)、pluggable memory(Postgres / Upstash / LibSQL)、evals、time-travel、HITL(suspend/resume);与 assistant-ui + AG-UI 同属 JS 生态,集成最顺,有 18h vs 41h 的上手优势。
注意点: 2026-03 无 SOC 2;重型 stateful / 合规场景验证少于 LangGraph。
为什么这是低风险决策: AG-UI 是干净的 HTTP/SSE 边界,切换后端不触碰前端。因此后端语言可以推迟到团队能力明确后再最终拍板,不阻塞前端开发。
最终技术栈(主线)
| 层 | 选型 | 说明 |
|---|---|---|
| 前端框架 | Next.js(App Router)+ React + TypeScript | Admin/Builder/Results = 常规 React |
| 对话 UI | assistant-ui + @assistant-ui/react-ag-ui | 仅受访者 Interview + Builder Preview |
| 交互组件 | 自研(RadioCardGroup / LikertScale / RankingList…) | 见 03_frontend_components.md |
| 样式 | Tailwind + shadcn/ui | |
| Schema 校验 | zod(前端)/ pydantic(后端) | 经 AG-UI / JSON Schema 对齐 |
| 协议边界 | AG-UI(HTTP + SSE) | agent ↔ 受访者前端 |
| Agent Runtime | Python + LangGraph | Harness = graph;checkpointer = 可重放 |
| API 服务 | FastAPI | projects/studies/sessions/results/KB/tools/export |
| Model Gateway | LiteLLM | 多 provider 解耦、cost、fallback |
| 结构化抽取 | pydantic + instructor / outlines | evidence-backed extraction |
| 主数据库 | PostgreSQL | 业务数据 + LangGraph checkpoints |
| 向量检索 | pgvector | KB / RAG |
| 缓存/队列 | Redis | session / stream / queue |
| 对象存储 | S3 兼容 | 上传 / 导出 / 附件 |
| 异步 worker | Arq(或 Celery) | extraction / synthesis / KB ingestion |
| 可观测 | LangSmith + OpenTelemetry | agent decision / token / cost / latency / audit |
| 内容站 | Astro + Starlight | landing + 101 文档中心 + PRD 可视化;读 docs/(SSOT);独立 Vercel 项目 |
MVP 单体部署:Next.js(前端)+ FastAPI(API)+ Python LangGraph(agent)+ PostgreSQL/pgvector + Redis。
内容站(website) 独立于产品 app:Astro + Starlight,读
docs/(SSOT)渲染 landing / 101 文档中心 / PRD 可视化,单独部署到 Vercel。与产品主线低耦合,详见../04_roadmap/04_delivery_plan.md的「内容站轨道」。这是 “Astro 内容站 + Next.js 产品 app 并存” 的标准分工:静态内容/SEO 归 Astro,动态有状态的产品归 Next.js。
风险与缓解
| 风险 | 缓解 |
|---|---|
| 前后端双语言(TS + Python) | AG-UI 干净边界 + JSON Schema 对齐;必要时从 pydantic 生成 TS 类型 |
| LangGraph 学习曲线 | 按 02_agent_harness.md 建议:第一版固定状态机,不上 visual graph builder |
| AG-UI 仍在演进 | assistant-ui 同时支持 ExternalStoreRuntime / AssistantTransport,可作 fallback;协议层可替换 |
| LangGraph AG-UI 集成版本差异 | 落地前以官方文档验证;封装一层 AG-UI emitter,隔离版本变化 |
| provider lock-in | LiteLLM 统一 gateway;先实现 1–2 个 provider |
| 后端语言最终拍错 | AG-UI 边界使后端可替换;先开发前端 + 协议契约,后端推迟最终决策 |
对现有文档的修订建议
03_architecture/01_system_architecture.md→ “推荐技术栈”:把”可选:Vercel AI SDK”更正为不采用(除非后端转 TS);assistant-ui 从”或自研”升为确定选型;新增 AG-UI 协议层 与 LangGraph runtime。05_implementation/03_frontend_components.md→ 在组件分层之上补一层 assistant-ui runtime(AG-UI adapter) 说明;明确InteractionRenderer由 assistant-ui generative UI 驱动。05_implementation/02_api_contracts.md→ 受访者 runtime 的 streaming 段落标注:wire 层采用 AG-UI 事件(原StreamEventunion 作为业务语义层,映射到 AG-UI 事件)。03_architecture/02_agent_harness.md→ 标注 HarnessRuntime 的实现底座为 LangGraph(state=graph state,pending-interaction=interrupt(),replay=checkpointer)。
调研来源
- AI SDK Stream Protocol & Python 后端现状:https://ai-sdk.dev/docs/ai-sdk-ui/stream-protocol · vercel/ai issue #7496 https://github.com/vercel/ai/issues/7496
- assistant-ui runtimes / generative UI / AG-UI adapter:https://www.assistant-ui.com/docs/runtimes/pick-a-runtime · https://www.assistant-ui.com/docs/tools/generative-ui · https://www.assistant-ui.com/docs/runtimes/ag-ui/overview
- CopilotKit & headless:https://docs.copilotkit.ai/ · https://docs.copilotkit.ai/premium/headless-ui
- AG-UI 协议与采用:https://docs.ag-ui.com/ · https://github.com/ag-ui-protocol/ag-ui
- assistant-ui vs CopilotKit:https://dev.to/alexander_lukashov/i-evaluated-every-ai-chat-ui-library-in-2026-heres-what-i-found-and-what-i-built-4p10
- LangGraph 生产能力:https://docs.langchain.com/oss/python/langgraph/overview · https://www.langchain.com/langgraph
- Mastra vs LangGraph:https://www.generative.inc/mastra-ai-the-complete-guide-to-the-typescript-agent-framework-2026 · https://dev.to/jim_l_efc70c3a738e9f4baa7/i-switched-from-langgraph-to-mastra-for-my-typescript-agents-18-hours-vs-41-nah