让AI学会问你选择题:LLM Wiki用户交互表单(单选/多选/自由文本)实现解析
【免费下载链接】llm_wikiLLM Wiki is a cross-platform desktop application that turns your documents into an organized, interlinked knowledge base — automatically. Instead of traditional RAG (retrieve-and-answer from scratch every time), the LLM incrementally builds and maintains a persistent wiki from your sources。项目地址: https://gitcode.com/GitHub_Trending/ll/llm_wiki
LLM Wiki 是一款跨平台的 AI 知识管理桌面应用,它能把你的文档自动整理成互相链接的持久化 Wiki 知识库。相比传统 RAG"每次从零检索再回答"的模式,LLM Wiki 会增量地构建和维护一份可长期沉淀的知识库。而它聊天 Agent 里一个鲜少被注意的设计——用户交互表单(user.ask)——让 AI 在执行任务中途可以暂停下来,向你弹出带单选、多选、自由文本的"选择题",等你点完"提交并继续"才接着干活。本文带你用最少代码,看懂这套 AI 用户交互表单从 LLM 输出到界面渲染的完整链路。
为什么 AI 助手需要"问选择题"?
普通聊天机器人遇到不确定的事情,通常只能把问题用纯文本写在回答里,然后"猜一个默认行为"继续执行。这在 AI Agent 场景下很危险:
- 文本提问没有结构:用户回一句"就选第一个",模型还得再解析一次,容易答非所问;
- 无法预置默认值:用户面对一堆选项常常不知道该选什么,没有"推荐项"引导;
- 无法一次收集多项信息:比如"格式 + 语言 + 是否启用"三个问题,文本对话要来回三轮。
LLM Wiki 的解法是把"提问"升级成一个结构化工单:Agent 返回一段 JSON 描述表单长什么样,前端按描述动态渲染出选项卡片、复选框、输入框,用户一次性填完提交,答案再自动"回填"给 Agent 继续任务。
整体链路:LLM → 清洗 → 事件 → 表单 UI
整个交互表单分四步流转,前后端职责清晰:
- LLM 返回
user.ask工具调用:Agent 循环要求模型只输出紧凑 JSON,需要用户输入时返回user.ask动作; - 后端清洗与校验:Rust 侧把 JSON 解析成结构化的
AgentUserInputRequest,补全 ID、去重、丢弃非法字段; - 事件推送:通过
AgentEvent::UserInputRequired把表单请求推给前端; - 前端渲染 + 提交回填:React 组件按字段类型动态渲染控件,用户提交后把答案组织成一条新消息重新发给 Agent。
支持 5 种字段类型,还兼容多种别名
LLM Wiki 的用户交互表单支持 5 种控件,且对 LLM 输出"手滑"写错的类型名非常宽容——内置了一整套别名归一化(见 runtime.rs 中的normalize_user_input_field_type):
| 控件类型 | 归一化别名 | 界面表现 |
|---|---|---|
single单选 | radio/select/singleChoice | 竖向选项卡片,可带"推荐"标签 |
multi多选 | checkbox/checkboxes/multiChoice | 带勾选框的选项列表 |
text单行文本 | input | 单行输入框 |
textarea多行文本 | longText | 可拖拽高度的多行输入 |
confirm确认开关 | boolean/switch | 单个勾选开关 |
即使 LLM 把工具名写成askUserQuestion、AskUserQuestion这类 Claude Code 风格的叫法,后端也会统一归一为user.ask(见 runtime.rs 的is_user_ask_tool)。对新手来说这意味着:无论底层接哪家大模型,表单都能稳定弹出来。
后端源码解析:一次安全的表单清洗
工单结构:AgentUserInputRequest
表单在后端被建模为三层结构,定义在 types.rs:
- Option(选项):
label展示文本 +value真实取值 + 可选description说明 +recommended推荐标记; - Field(字段):
id、类型、label标题、placeholder占位提示、选项列表、defaultValue默认值; - Request(整张表单):全局唯一
request_id(UUID)、标题、描述、字段数组。
清洗逻辑:脏数据进,合法表单出
核心函数是 runtime.rs 中的sanitize_user_input_request,它做了四件对稳定性至关重要的事:
- 字段/问题双兼容:同时接受
fields或questions两个键,避免不同模型的字段名差异; - ID 自动去重:字段和选项的 key 冲突时自动加后缀(
unique_user_input_key),保证前端取值不串号; - 默认值校验:单选默认值必须真实存在于选项里,多选默认值必须都是合法选项,否则直接丢弃默认值(
validate_user_input_default); - 无效字段静默跳过:没有选项的单/多选题、未知类型直接过滤;一个字段都不合法才报错。
此外还有字段数、选项数的上限保护(MAX_USER_INPUT_FIELDS/MAX_USER_INPUT_OPTIONS),防止模型"话痨"渲染出超长表单。
前端源码解析:按 Schema 动态渲染表单
事件驱动:userInputRequired 如何到达界面
后端通过事件流推送表单请求,事件枚举定义在 events.rs 的UserInputRequired { request }变体。聊天面板 chat-panel.tsx 捕获该事件后,把表单挂到最后一条助手消息上(数据结构见 chat-store.ts 的userInputRequest字段)。
表单控件:一个组件覆盖 5 种类型
渲染逻辑集中在 chat-message.tsx 的UserInputRequestPanel:它遍历request.fields,逐个交给 UserInputFieldControl——按field.type分支渲染为选项卡片、复选框、输入框或开关。
体验上有两个细节值得新手注意:
- "推荐"徽章:
recommended: true的选项会带一枚"推荐"角标(i18n 键chat.userInputRecommended,中文即"推荐"),降低选择成本; - 智能预填:initialUserInputAnswers 会优先取
defaultValue,其次取推荐项/首选项,多选预填空数组、开关预填false——用户几乎总能在 1 秒内完成提交。
提交后:答案如何"唤醒" Agent
用户点击"提交并继续"(chat.userInputSubmit)后,handleSubmitUserInput 把所有答案格式化为一行行- 字段标题 (id): 值的文本,并附上一句提示词"Continue the previous task using these answers",作为一条新消息重新发回 Agent。也就是说,表单答案不是走特殊通道,而是回归对话上下文——这保证了任意模型、任意会话历史都能无缝续跑。
新手使用体验:三类典型场景
- 生成类技能确认参数:比如让 Agent 生成文档/页面时,它弹出"主题色?A 自动 / B 蓝色系(推荐)",你点一下推荐项即可;
- 多选式范围确认:"要同步哪些目录?"勾选若干项一次提交,省掉三轮问答;
- 补充自由文本:表单里混排
text/textarea字段,让 AI 在你确认选项的同时顺带收集一段说明文字。
总结:为什么这个设计值得借鉴
LLM Wiki 的用户交互表单用极少的代码解决了一个 Agent 通用难题:
- 协议层:把"提问"约定成
user.ask结构化 JSON,与具体 UI 解耦; - 防御层:后端对 LLM 输出做别名归一、去重、默认值校验,脏数据进合法表单出;
- 渲染层:前端纯 Schema 驱动,5 种控件一个组件全覆盖,还带推荐标记与智能预填;
- 续跑层:答案回灌为普通对话消息,任何模型都能接着干活。
这套"选择题式"交互让 AI 从"自说自话"变成了"边做边确认",对新手用户特别友好——想深入研读源码,可以从 src-tauri/src/agent/ 目录入手,重点阅读 runtime.rs 与 src/components/chat/chat-message.tsx 两个文件即可还原全文链路。
【免费下载链接】llm_wikiLLM Wiki is a cross-platform desktop application that turns your documents into an organized, interlinked knowledge base — automatically. Instead of traditional RAG (retrieve-and-answer from scratch every time), the LLM incrementally builds and maintains a persistent wiki from your sources。项目地址: https://gitcode.com/GitHub_Trending/ll/llm_wiki
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考