项目介绍:
为新能源汽车销售开发一个agent,给想要有购车需求的用户使用。
用户可以提供个性化推荐, 开始对话前,你需要先输入基本诉求:比如用车场景、购车预算、期望的车型(SUV 还是轿车),以及对智能驾驶的具体要求。随后,Agent 会在我们的新能源汽车数据库中检索,并给出匹配度较高的推荐车型。
库内无结果 → 联网检索补全信息 如果你想要的车型在数据库里没有,聊天过程中 Agent 会自动调用 Google做全网搜索,并返回该车型的权威资料与关键信息,保证推荐不“断档”。
感兴趣 → 一键加入“喜欢”列表 当你对某个车型产生兴趣时,Agent 会把它自动加入你的喜欢列表(Favorites),存入用户侧的数据库,作为后续的购车备选清单,便于对比与复盘。
销售线索收集 → 飞书 Webhook 通知 这个 Agent 的核心目标之一,是帮助新能源车销售更早、更准确地了解用户需求。对话中它会适时引导,询问你是否需要一对一服务;若你同意并留下手机号,系统会通过飞书(Lark)的 Webhook 将线索以机器人消息的形式推送到销售群,方便销售同学及时跟进。
技术栈:
| 层级 | 技术 | 选择理由 |
|---|---|---|
| 框架 | Next.js 15.2 (App Router) | SSR/SSG 混合渲染、API Routes、React 19 |
| UI | shadcn/ui + Radix UI + Tailwind CSS | 零运行时开销、可定制、TypeScript 友好 |
| AI 后端 | Dify AI | 支持对话型应用、Agent 工具调用、SSE 流式输出 |
| 数据库 | PostgreSQL + Drizzle ORM | 类型安全、轻量、SQL 优先 |
| Markdown | react-markdown + remark-gfm | 渲染 AI 返回的富文本 |
dify Agent业务梳理:
一、入口与需求采集 用户进入后,需要先表达购车诉求。这里有两种常见方式:
- 让用户填写表单;
- 通过引导式对话,让用户逐步说出需求。
通常在选择新能源汽车时,用户会关心:预算、车型偏好、用车场景、是否考虑试驾等。这些关键信息应在首次使用时就采集完整。
二、基于诉求的核心推荐 核心功能是:根据用户的诉求,从我们自己的数据库中推荐合适的新能源汽车。因此,系统需要具备数据库的读写与检索能力,Agent 侧能够在运行时调用数据库完成查询与排序。
三、数据库与建表思路 我们需要先“建表”,为后续的工具调用打基础:
- 车型表:用来存放各类新能源汽车的基础数据与参数。
- 用户收藏表:当用户看到喜欢的车型时,可以加入“喜欢/收藏”,因此需要一张表来保存这一行为数据。
四、对话中的 AI 搜索兜底 如果聊天过程中,数据库检索没有找到合适结果,就需要启用 AI 搜索功能作为兜底。现在有不少现成组件可以提供 AI 搜索能力,我们可以按需接入并由 Agent 调用。
五、成交与服务闭环 产品的目标不仅是推荐,还希望推动真实成交,或者至少帮助用户预约线下试驾,提供一对一服务。既然 Agent 已经通过对话了解了用户的诉求,就能在这个阶段给出更精准的推荐,并把线索顺畅地交到服务侧。
为了承接线下的一对一服务,我们需要在用户允许后,让Agent给我们的销售团队发送一个消息,让我们的销售主动联系用户。这里计划使用飞书消息,来完成通知/推送,把关键信息传递给我们的销售。
数据库是核心,知识库是辅助,AI 搜索是兜底
项目结构:
find-best-ev-main/
├── app/
│ ├── layout.tsx # 根布局
│ ├── page.tsx # 首页
│ ├── globals.css # 全局样式 + CSS 变量
│ └── api/
│ ├── dify/
│ │ ├── parameters/route.ts # Dify 表单配置代理
│ │ └── chat/route.ts # Dify 聊天消息代理 (SSE)
│ └── ev-models/
│ ├── route.ts # 车型列表 API
│ └── [id]/route.ts # 车型详情 API
├── components/
│ ├── ui/ # shadcn/ui 组件
│ │ ├── button.tsx
│ │ ├── card.tsx
│ │ ├── input.tsx
│ │ ├── label.tsx
│ │ ├── select.tsx
│ │ └── textarea.tsx
│ ├── dynamic-form.tsx # 动态表单组件
│ ├── chat-page.tsx # 聊天页面
│ ├── ev-list.tsx # 车型列表
│ └── pulsing-border-shader.tsx # 动画边框着色器
├── lib/
│ ├── dify.ts # Dify 类型、解析、本地存储
│ └── db/
│ ├── index.ts # 数据库连接
│ └── schema.ts # Drizzle Schema
├── hero-section.tsx # Hero 区域 + 弹窗逻辑
└── package.json
经验与踩坑:
1. SSE 流式透传
Next.js Route Handler 中直接 new NextResponse(res.body) 转发 ReadableStream 是最简洁的 SSE 透传方案。注意设置 Content-Type: text/event-stream 和 Cache-Control: no-cache 头部。
2. Dify 原始 JSON 结构解析
Dify 的 user_input_form 使用的是”判别键”(discriminator key) 模式,每个元素只有一个 key(如 "text-input"),类型信息隐藏在 key 名中。需要遍历对象键来识别字段类型。
3. 构建内存问题
首次构建时遇到了 webpack 编译超时,清理 .next 目录后重新构建即解决。建议 CI 环境定期清理构建缓存。
4. 深色主题的 Markdown 适配
react-markdown 本身不提供样式,需要手动为所有 HTML 元素映射 Tailwind 类。推荐使用 @tailwindcss/typography 插件的 prose-invert 模式作为基础,再针对深色主题微调。
结语:
这个项目展示了如何将 Dify 这样的 AI 平台与现代化的 Next.js 应用深度集成。核心思路是:AI 能力做服务端代理,前端专注交互体验。表单由 Dify 驱动、对话通过 SSE 流式输出、思考过程可视化——这三个特性让 AI 助手既有”大脑”又有”表达力”
源码请参考:项目分类