对话式界面定制系统(★★)


文档摘要

源文件:chapter5/conversational-ui/README.md 实验 5-11:对话式界面定制系统(★★) 用户用自然语言提出 UI 定制需求(颜色 / 字体 / 文案 / 布局 / 组件位置), Agent 自主定位并修改前端源码,开发模式下的热加载(HMR)让改动即时生效, 支持多轮迭代定制。 目的 把"一刀切"的标准前端,变成"千人千面"的可对话定制界面: 基础 chatbot 应用 = React(Vite) 前端 + FastAPI 后端; 前后端都跑在开发模式:前端 Vite HMR、后端 uvicorn --reload; 用户说"把发送按钮改成蓝色 / 换成等宽字体 / 标题改成 XXX", Agent(OpenAI,默认 ;

源文件:chapter5/conversational-ui/README.md

实验 5-11:对话式界面定制系统(★★)

用户用自然语言提出 UI 定制需求(颜色 / 字体 / 文案 / 布局 / 组件位置),
Agent 自主定位并修改前端源码,开发模式下的**热加载(HMR)**让改动即时生效,
支持多轮迭代定制。

目的

把"一刀切"的标准前端,变成"千人千面"的可对话定制界面:

  • 基础 chatbot 应用 = React(Vite) 前端 + FastAPI 后端
  • 前后端都跑在开发模式:前端 Vite HMR、后端 uvicorn --reload
  • 用户说"把发送按钮改成蓝色 / 换成等宽字体 / 标题改成 XXX",
    Agent(OpenAI,默认 gpt-5.6-luna;未配置 OPENAI_API_KEY 时设 OPENROUTER_API_KEY 自动改走 OpenRouter)读懂需求 → 改 frontend/src 里的源码文件;
  • 热加载检测到文件变化,浏览器无需整页刷新即可看到界面变化。

原理 / 架构(简述)

整个系统由四部分组成,各司其职:

  • agent.py(定制 Agent):核心。把一条自然语言需求 + 当前可编辑源码喂给 OpenAI,
    用 function calling 的 apply_edits 工具让模型返回"改写后的文件全文"。
    只暴露白名单文件(src/App.jsxsrc/theme.css)给模型,并在返回后校验路径,
    防止模型改错/新增文件。它只产出改写方案,不落盘(便于展示 diff 与验证)。
  • baseline/src/(基线快照):前端源码的"出厂原样"。demo.py 每轮开始前把它
    拷回 frontend/src,保证多次运行结果可重复、互不污染——这也是 Agent 改动与
    原始界面做 diff 的对照基准。
  • frontend/(React + Vite 前端):被定制的对象。Agent 改的就是这里的 src/*
    开发模式下 Vite HMR 让改动即时可见,vite build 用于验证"改动没破坏应用"。
  • backend/(FastAPI 后端):最小 chatbot 服务(/api/chat),为前端提供可对话的载体;
    默认 echo 回声模式(开箱即用、无需任何 Key),也可用 --model 一键切到真实 LLM 对话
    自带命令行入口(python main.py --help),--reload 演示"后端热加载"。它不参与 UI 定制,
    是让整套界面能真实跑起来的配角。

一句话:Agent 读需求 → 改前端源码 → 断言改动生效 + 构建不破坏
baseline 保证可重复,backend 让界面能真实对话。

关于热加载(HMR)

  • 前端npm run dev 启动的 Vite dev server 自带 HMR。Agent 一改 src/*.jsx
    src/theme.css,浏览器局部热替换、保留应用状态,界面即时更新。
  • 后端uvicorn main:app --reload 监听 .py 变化自动重启。
  • 本实验的定制主要作用于前端源码,所以视觉效果靠前端 HMR 体现。

目录结构

conversational-ui/ ├── frontend/ # React + Vite 前端(基础 chatbot 界面) │ ├── src/App.jsx # 界面与 UI 文案(Agent 改"文案/组件") │ ├── src/theme.css # 颜色/字体/布局样式(Agent 改"样式") │ ├── src/main.jsx │ ├── index.html │ ├── vite.config.js # 开启 HMR + /api 代理到后端 │ └── package.json ├── backend/ │ ├── main.py # FastAPI 后端(/api/chat) │ └── requirements.txt ├── baseline/src/ # 前端源码初始快照(demo 每次运行前恢复,保证可重复) ├── agent.py # 定制 Agent:NL 需求 → 用 OpenAI 改写源码 ├── demo.py # 端到端演示 + 自动验证(NL→代码→断言→构建) ├── requirements.txt # 后端 + Agent 依赖 ├── env.example └── .gitignore # node_modules / dist / .env 均已忽略

运行方式

1) 准备环境

# Python 依赖(Agent + 后端) pip install -r requirements.txt # 前端依赖(首次 npm install 较慢属正常) cd frontend && npm install && cd .. # 配置 OpenAI Key cp env.example .env # 然后填入 OPENAI_API_KEY(或设 OPENROUTER_API_KEY 兜底)

2) 自动验证闭环(无需浏览器)

python demo.py # 跑全部 3 轮定制并做完整验证 python demo.py --quick # 只跑第 1 轮(省时,用于快速冒烟) python demo.py --rounds 2 # 只跑前 2 轮 python demo.py --no-build # 跳过 vite build(仅验证"改动被正确应用",更快) python demo.py -h # 查看全部参数

demo.py 会连续跑 3 轮自然语言定制,每轮:
调用真实 OpenAI 改写源码 → 打印改动 diff → 读回源码断言"改动符合需求" →
vite build 验证"没破坏应用"。首轮较慢多因 npm install 或首次构建,
想快速验证可用 --quick--no-build

3) 手动体验真实 HMR(可选,需要浏览器)

# 终端 A:后端(热加载)。两种启动方式行为一致,任选其一: cd backend && python main.py --reload --port 8000 # 本文件自带命令行入口 # 或: cd backend && uvicorn main:app --reload --port 8000 # 书中示例写法 # 想让运行起来的 chatbot 真会说话(而非回声):加 --model gpt-5.6-luna(需 OPENAI_API_KEY 或 OPENROUTER_API_KEY) # 终端 B:前端(HMR) cd frontend && npm run dev # 打开 http://localhost:5173 # 终端 C:跑一条定制需求,回到浏览器即可看到界面即时变化 python -c "import agent,pathlib; c,m=agent.build_client_and_model(); \ r=agent.customize(c,m,pathlib.Path('frontend'),'把发送按钮改成橙色'); \ [pathlib.Path('frontend',f['path']).write_text(f['content']) for f in r['files']]"

后端命令行参数(cd backend && python main.py --help):

参数 说明 默认
--host 监听地址(对外可用 0.0.0.0 127.0.0.1
--port 监听端口(前端把 /api 代理到此端口) 8000
--reload / --no-reload 是否开启后端热加载 开启
--model NAME 指定模型名,切到真实 LLM 对话;缺省为 echo 回声模式(也可用环境变量 CHAT_MODEL 无(echo)
--log-level uvicorn 日志/输出级别 info
--print-config 只打印生效配置(JSON)后退出,不监听端口(便于无端口环境下校验)

echo 与 LLM 两种模式都不影响 UI 定制闭环——定制作用于前端源码,后端只是让界面能真实对话的载体。
LLM 模式复用与 agent.py 相同的 OPENAI_API_KEY / OPENAI_BASE_URL 配置;缺 Key 或调用失败会自动回退占位提示,绝不编造回复。

验证方式与局限

  • 本 demo 自动验证的是:自然语言 → 代码修改被正确应用不破坏构建的闭环。
    • 读回源码断言:如"改成蓝色 #2563eb"→ 源码里确实出现该色值;
      "换成等宽字体"→ 出现 monospace;"标题改成 XXX"→ 出现该文案。
    • 每轮改动后 vite build 必须编译通过,证明改动没破坏应用。
  • 本 demo 不做的:真实浏览器内 HMR 的视觉即时刷新。
    本机无 Playwright/浏览器,无法自动截图验证视觉效果——
    这部分需手动 npm run dev + 打开浏览器查看(见上文第 3 步)。
  • Agent 只被允许改写白名单文件(src/App.jsxsrc/theme.css),
    降低改错文件的风险;改写采用"整文件重写",对小文件比零散替换更稳。

真实运行输出(节选)

第 1 轮 NL 定制需求:把发送按钮和用户消息气泡的主题色从绿色改成蓝色,用 #2563eb 这个蓝。 [改动文件] src/theme.css - --color-primary: #16a34a; /* 初始为绿色 */ + --color-primary: #2563eb; /* 改为蓝色 */ 断言:源码中出现蓝色值 #2563eb -> 通过 ✅ 构建结果:通过 ✅ 第 2 轮 NL 定制需求:把整个界面的字体换成等宽字体(monospace)。 [改动文件] src/theme.css - --font-family: system-ui, "PingFang SC", ... sans-serif; + --font-family: monospace; 断言:源码中出现 monospace 等宽字体 -> 通过 ✅ 构建结果:通过 ✅ 第 3 轮 NL 定制需求:把顶部的标题文案改成"我的专属客服"。 [改动文件] src/App.jsx - const HEADER_TITLE = "智能助手"; + const HEADER_TITLE = "我的专属客服"; 断言:源码中出现新标题文案"我的专属客服" -> 通过 ✅ 构建结果:通过 ✅ 多轮定制总结:全部通过 ✅

环境变量

变量 说明
OPENAI_API_KEY 必填其一,本实验读取此项(未配置时用 OPENROUTER_API_KEY 兜底)
OPENAI_BASE_URL 可选,切换到兼容 OpenAI 协议的服务端点
MODEL 可选,默认 gpt-5.6-luna

如何适配 / 扩展

  • 换模型 / 换供应商:Agent 走标准 OpenAI SDK,任何"兼容 OpenAI 协议"的服务都能接。
    只需在 .env 或环境变量里设置 OPENAI_BASE_URL + MODEL + 对应的 OPENAI_API_KEY
    代码无需改动。例如:
    • Kimi / Moonshot:OPENAI_BASE_URL=https://api.moonshot.cn/v1MODEL=kimi-k3
    • 火山方舟(ARK):OPENAI_BASE_URL=https://ark.cn-beijing.volces.com/api/v3MODEL=<endpoint-id>
    • 本地 vLLM / Ollama 等:把 OPENAI_BASE_URL 指向本地端点即可。
  • 扩展可定制范围:默认只允许改 src/App.jsxsrc/theme.css。想让 Agent 能改更多文件,
    agent.pyEDITABLE_FILES 白名单里增删路径即可(白名单越大越灵活,但改错风险也越大)。
  • 新增验证轮次:在 demo.pyROUNDS 里追加 {"requirement": ..., "verify": ...}
    即可把自己的定制需求纳入自动断言闭环。
  • 接前端frontend/ 是标准 Vite 工程,npm run dev 起 HMR、npm run build 出静态产物。
    想接自己的界面,替换 src/* 并同步更新白名单与 baseline/ 快照即可。
  • 接后端 / 真实 LLM 对话backend/main.py/api/chat 默认是回声式占位回复,
    --model <模型名>(或设 CHAT_MODEL)即可切到真实 LLM 对话(复用上面的 OPENAI_* 配置)变成真实客服;
    想换成自定义业务逻辑,改写 _llm_replychat 里的返回即可。

作者与出处
原作者: bojieli
来源:bojieli
许可证:Apache-2.0
整理: 灏天文库整理
由灏天文库结构化整理,提供目录导航、全文检索与在线阅读,便于系统化学习
发布者: 作者: bojieli 转发
评论区 (0)
U