Skip to content

技术选型决策:对话框架与后端架构(ADR)

技术选型决策:对话框架与后端架构(ADR)

状态:已决策 · 日期:2026-06-23 · 决策者:项目负责人 + 架构评审

本文是一份 Architecture Decision Record(ADR),覆盖两件事:

  1. 受访者访谈端的对话框架 / generative UI 选型;
  2. 平台后端 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.md04_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 即可。

受访者端定制要点(无论框架,都要做对)

  1. 禁用 chatbot 式 edit / regenerate / branch —— 受访者不应改写 AI 的提问。
  2. UI 是 assistant message / interaction card / result summary 混排的定制 timeline,不是标准 chatbot 气泡流。
  3. 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 + LangGraphTS 全栈 + 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 等待受访者交互 + 字段 reviewinterrupt()(HITL,暂停后从 checkpoint 恢复)
crash / 部署中断不丢会话durable execution(worker lease + 自动恢复)
Decision log / token / cost / latencyLangChain 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_conclude

interrupt() + 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 + TypeScriptAdmin/Builder/Results = 常规 React
对话 UIassistant-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 RuntimePython + LangGraphHarness = graph;checkpointer = 可重放
API 服务FastAPIprojects/studies/sessions/results/KB/tools/export
Model GatewayLiteLLM多 provider 解耦、cost、fallback
结构化抽取pydantic + instructor / outlinesevidence-backed extraction
主数据库PostgreSQL业务数据 + LangGraph checkpoints
向量检索pgvectorKB / RAG
缓存/队列Redissession / stream / queue
对象存储S3 兼容上传 / 导出 / 附件
异步 workerArq(或 Celery)extraction / synthesis / KB ingestion
可观测LangSmith + OpenTelemetryagent decision / token / cost / latency / audit
内容站Astro + Starlightlanding + 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-inLiteLLM 统一 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 事件(原 StreamEvent union 作为业务语义层,映射到 AG-UI 事件)。
  • 03_architecture/02_agent_harness.md → 标注 HarnessRuntime 的实现底座为 LangGraph(state=graph state,pending-interaction=interrupt(),replay=checkpointer)。

调研来源