这不是一个简单的聊天机器人项目,而是一个 “AI 能力全家桶”
从普通的对话、带记忆的角色扮演,到能查课程、预约的智能客服,再到能读懂 PDF 的文档问答,甚至还有爬取并分析政府采购数据的图数据库应用……
我会带着你,先理解它为什么这样设计,再一步步把它跑起来。


第一部分:设计思想与架构详解

一、项目定位 —— 一个可以“长大”的 AI 应用原型

想象一下:你有一个 AI 助手,平时陪你闲聊,切换到客服模式就能查课表、帮客户预约,还能把上百页的 PDF 合同“吃”进去,然后直接回答你的问题。再进一步,它能自动爬取政府采购公告,画出投标关系网……
这就是本项目的目标 —— 展示 Spring AI Alibaba 如何集成各种主流 AI 能力,并提供一个可扩展、可落地的设计模板。

二、核心能力一览(表中带原理说明)

能力模块 实现技术 它做了什么?为什么这么设计?
智能对话 Spring AI + DashScope 调用通义千问大模型,你问它答。支持多场景定制:你可以为每个场景设定不同的“人设”(System Prompt)。
多模态交互 Qwen-VL 模型 不仅能读文字,还能“看”图片。你上传一张图表,它能描述内容。背后是多模态大模型对图像和文本的联合理解。
工具调用 Function Calling 客服问你“有什么编程课”,大模型不会瞎编,而是自动调用数据库查询函数,拿到真实课程后再回答你。这就是 AI 连接现实世界数据的桥梁。
RAG 知识库 Milvus 向量库 将 PDF 文档切块、向量化(变成数学向量),存入向量数据库。提问时,先把问题也向量化,然后从数据库中找回最相关的几个片段,连同问题一起交给大模型 —— 这样它就能基于你的文档作答,不胡说八道。
聊天记忆 MessageWindowChatMemory 默认记住最近 N 轮对话,让聊天有上下文。不同的 ChatClient 可以有自己的记忆窗口,互不干扰。
网页爬虫 WebMagic 模拟浏览器抓取政府采购网站,提取项目、招标单位等信息。
图数据库 Neo4j 存储实体(采购单位、项目、供应商)以及它们之间的关系(谁招标、谁中标)。用图查询能轻松回答“A 公司投过哪些标”这类复杂关联问题。

三、技术栈清单

后端

  • Spring Boot 3.5.3
  • Spring AI Alibaba 1.0.0.2
  • 阿里云 DashScope(通义千问系列模型 + 向量模型)
  • MySQL + MyBatis Plus(业务数据)
  • Neo4j(图数据)
  • Milvus(向量数据)
  • WebMagic(爬虫)

前端

  • Vue 3 + TypeScript + Vite + Naive UI

用 Spring AI Alibaba 的好处是:你不用自己写 HTTP 调用阿里云 API 的代码,它提供了统一的 ChatClient 接口,切换模型、配置工具都非常方便。


四、系统架构 —— 每个组件各司其职

下面这张架构图展示了从前端到后端再到各种数据库的完整调用链路。你可以把它想象成一个分工明确的工厂:

Spring Boot 后端

前端 Vue3

数据存储层

AI 服务层

HTTP

可选工具调用

Web界面

Controller 层
Chat/Game/PDF/Procurement

ChatClient 工厂
chatClient / gameChatClient
serviceChatClient / pdfChatClient

DashScope 大模型
通义千问

Milvus 向量检索

工具执行器
CourseTools

MySQL

Neo4j

Milvus

本地文件系统

核心设计亮点解读

1. 多 ChatClient 策略:为每个场景定制一个“专属大脑”

项目中配置了 4 个不同的 ChatClient

ChatClient System Prompt 示例 特殊配置 为什么分开?
chatClient “你是一个可爱的小助手,说话带点二次元风格” 支持多模态(图+文) 闲聊场景需要活泼,且能识别图片
gameChatClient “你是游戏中的勇士,回答要中二” 仅聊天记忆 角色扮演不需要查数据库
serviceChatClient “你是专业的课程顾问,准确提供课程信息” 挂载课程查询/预约工具 客服必须调用真实数据
pdfChatClient “你是一个知识渊博的文档专家” RAG 向量检索 文档问答需要从向量库里找上下文

如果只用一个通用的 Client,你就会遇到“角色错乱”——客服突然卖萌,或者文档问答胡说八道。分离配置,各司其职,是工程化落地的好习惯。

2. RAG(检索增强生成)让 PDF 不再是“哑巴”

传统大模型只知道训练数据里的内容,你私有的 PDF 它看不到。RAG 的解决思路是:
先检索,后生成

流程如下:

大模型 Milvus 向量库 后端 /pdf/chat 用户 大模型 Milvus 向量库 后端 /pdf/chat 用户 提问:“这份合同里违约金是多少?” 将问题向量化, 检索 topK=10 相关片段 返回最相似的3个段落 构建 Prompt: “参考以下文档片段:...\n问题:违约金是多少?” 根据片段生成准确答案 流式输出答案

注意:向量数据库不存储原文,而是存储文档块的高维向量(1024维)。检索时计算余弦相似度,找到最“像”问题的那些块。阈值 similarityThreshold=0.2 可以过滤掉不相关的噪声。

3. 工具调用(Function Calling)原理 —— 大模型的手和脚

客服场景中,用户问“有什么编程课?”,大模型本身不知道公司内部课程表。但是,我们给它配了一个“工具箱”——CourseTools 类中带有 @Tool 注解的方法。

大模型看到用户问题后,会做两件事:

  1. 理解意图:“哦,用户想查课程,需要调用 queryCourse 工具,参数是课程类型=编程”。
  2. 返回一个工具调用请求(而不是直接回答)。
    后端收到这个请求后,真正执行 Java 方法去查 MySQL,拿到结果(比如 [Java入门, Python全栈])后再把结果“喂”给模型。
    模型最后才生成自然语言:“我们有以下编程课程:Java入门、Python全栈……”

这就相当于大模型有了“干事”的能力,而不仅仅是“聊天”。

返回工具调用

结果集

生成最终答案

用户: 有什么编程课

ServiceChatClient

大模型判断需要工具

CourseTools.queryCourse

MySQL 课程表


五、数据库设计 —— 三种数据库,三种用途

1. MySQL:存业务结构化数据
表名 作用
school 校区(比如“海淀校区”“朝阳校区”)
course 课程名称、类型、学时、所属校区
course_reservation 谁预约了哪个课程、联系方式
procurement_project 爬虫抓来的政府采购项目
procurement_organization 采购单位(甲方)

关系很简单,用 MyBatis Plus 做 ORM。

2. Neo4j:图数据库,存“关系网”

政府采购数据中有很多关联关系:某个采购单位发布了哪些招标?某个供应商投了哪些标?用 SQL 做多表 JOIN 非常麻烦,而图数据库直接存成节点和边。

示例图模型:

发布

中标

投标

采购单位: 市财政局

项目: 服务器采购

供应商: 浪潮公司

供应商: 华为公司

查询“市财政局的所有中标供应商”只需要遍历图,一步到位。

3. Milvus:向量数据库,存“语义”
  • Collection 名:chatPDF
  • 向量维度:1024(与 text-embedding-v3 模型输出维度一致)
  • 每条记录包含:文件名字、文本块内容、文本块的 1024 维向量

上传一个 PDF,后台会自动切块(chunk),调用嵌入模型向量化,存入 Milvus。提问时,同样向量化问题,检索最相似的块。


六、接口设计 —— 你只需要知道这几个 API

接口 方法 说明 举例
/ai/chat POST 基础聊天,可传图片 {"prompt":"你好","chatId":"001"}
/ai/game POST 游戏角色聊天 同上
/ai/service POST 客服(带工具) {"prompt":"有Python课吗","chatId":"002"}
/ai/pdf/chat POST PDF 问答 {"prompt":"总结文档","chatId":"003"}
/ai/pdf/upload/{chatId} POST 上传 PDF 文件 form-data: file
/procurement/crawl/start POST 启动爬虫 可选 url 参数

chatId 用于区分不同对话,实现记忆隔离。同一个 chatId 的多次请求会共享对话历史。


第二部分:从零到一部署实操(手把手,保你跑起来)

一、准备工作

1. 硬件/软件最低要求

  • JDK 17(必须)
  • Maven 3.8+
  • Docker(强烈推荐,快速启动数据库)
  • Node.js 18+(如果要跑前端)

2. 申请阿里云 DashScope API Key

  • 访问 DashScope 控制台,注册/登录。
  • 开通服务(一般送免费额度)。
  • 进入 API Key 管理 → 创建 API Key → 复制保存

没有这个 Key,所有 AI 接口都会报错。

二、三步搭好所有数据库(用 Docker 最省心)

MySQL(业务数据)
docker run -d \
  --name mysql-chatai \
  -e MYSQL_ROOT_PASSWORD=123456 \
  -e MYSQL_DATABASE=chatAiDemo \
  -p 3306:3306 \
  mysql:8.0

等容器起来后,需要初始化表结构。项目里没有 SQL 文件,你可以手动建表,也可以使用下面这个简化 SQL(在 MySQL 中执行):

CREATE TABLE school (id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255), address VARCHAR(255));
CREATE TABLE course (id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255), type VARCHAR(50), edu INT, school_id BIGINT);
CREATE TABLE course_reservation (id BIGINT PRIMARY KEY AUTO_INCREMENT, course VARCHAR(255), school VARCHAR(255), student_name VARCHAR(100), contact_info VARCHAR(100), remark TEXT);
Neo4j(图数据库)
docker run -d \
  --name neo4j-chatai \
  -p 7474:7474 -p 7687:7687 \
  -e NEO4J_AUTH=neo4j/123456 \
  neo4j:latest

访问 http://localhost:7474 可以打开浏览器界面,密码是 123456

Milvus(向量数据库,稍微复杂)

用 Docker 启动 Milvus Standalone(推荐本地开发):

# 创建网络
docker network create milvus-net

# 启动 etcd
docker run -d --name milvus-etcd --network milvus-net \
  -p 2379:2379 quay.io/coreos/etcd:v3.5.5 \
  etcd -advertise-client-urls=http://0.0.0.0:2379 -listen-client-urls http://0.0.0.0:2379

# 启动 Milvus
docker run -d --name milvus-standalone --network milvus-net \
  -p 19530:19530 \
  -e ETCD_ENDPOINTS=milvus-etcd:2379 \
  milvusdb/milvus:v2.3.3

如果只想快速体验 PDF 问答,也可以改用 Milvus Lite(嵌入式),但要修改项目配置文件,难度稍大。建议先按 Docker 方式。

三、环境变量 —— 连接数据库和 AI 的钥匙

在你的终端里执行(最好写到 ~/.bashrc 里永久生效):

export AI_DASHSCOPE_API_KEY="sk-xxxxxxxxxxxxxx"
export MYSQL_PASSWORD="123456"
export NEO4J_PASSWORD="123456"
export MILVUS_HOST="localhost"

然后 source ~/.bashrc 让变量生效。
验证:echo $AI_DASHSCOPE_API_KEY 能看到内容就对了。

四、启动后端

cd spring-ai-alibaba-comprehensive-example   # 进入项目根目录
mvn clean compile                             # 第一次会下载很多依赖,耐心等
mvn spring-boot:run

看到类似 Started ChatAiDemoApplication in 6.8 seconds 即成功。
后端地址:http://localhost:8080

常见失败原因

  • Could not resolve placeholder 'AI_DASHSCOPE_API_KEY' → 环境变量没设或没生效。
  • Communications link failure → MySQL 未启动或密码错误。
  • Port 8080 already in use → 关掉占用 8080 的进程,或者改 application.yml 中的 server.port

五、启动前端(可选,但推荐)

cd chatAiDemo-frontend
npm install
npm run dev

访问 http://localhost:5173,你会看到一个漂亮的聊天界面,可以选择不同场景。

六、测试接口 —— 不用前端也能玩

1. 基础聊天

curl -X POST http://localhost:8080/ai/chat \
  -H "Content-Type: application/json" \
  -d '{"prompt":"你好,请介绍自己","chatId":"test123"}'

2. 客服场景(自动调用课程查询工具)

curl -X POST http://localhost:8080/ai/service \
  -H "Content-Type: application/json" \
  -d '{"prompt":"有什么编程课","chatId":"test456"}'

你会看到大模型返回真实课程列表(因为它调用了 MySQL 查询)。

3. PDF 问答
先上传一个 PDF:

curl -X POST http://localhost:8080/ai/pdf/upload/test999 \
  -F "file=@/你的文档.pdf"

然后提问:

curl -X POST http://localhost:8080/ai/pdf/chat \
  -H "Content-Type: application/json" \
  -d '{"prompt":"这个文档的核心观点是什么","chatId":"test999"}'

第三部分:优化与扩展 —— 把它变成你自己的产品

一、发现的问题与替代方案

问题 影响 解决方案
缺少 SQL 初始化脚本 新手容易卡在建表上 上面已提供简化 SQL,或者根据 entity 包下的 PO 类手动建表
Neo4j 云端地址示例写死 必须改配置 改成你自己的 Neo4j URI(本地 Docker 用 bolt://localhost:7687
Milvus 需要独立部署 增加了环境复杂度 开发阶段可以用 Milvus Lite,但需要调整代码;也可以暂时注释掉 PDF 相关功能

二、你可以继续添加的功能

1. 增加更多工具
@Tool(description = "查询实时天气")
public String getWeather(@ToolParam(description = "城市") String city) {
    // 调用高德/和风天气 API
}

只要在 serviceChatClient 的配置里注册这个工具,客服就能回答“今天上海天气怎么样”了。

2. 接入企业知识库

把公司内部的 Confluence、Notion 文档导出为 PDF 或 Markdown,批量向量化后存入 Milvus,你的 AI 助手就变成了公司知识专家。

3. 优化 RAG 效果
  • 使用更强的嵌入模型(如 text-embedding-v3 已经很好)。
  • 增加 重排序(Rerank) 环节:第一次检索出 20 个候选块,再用一个更精密的模型重新排序,取最相关的 3 个。
  • 实现 混合检索:向量检索 + 关键词(BM25)加权。
4. 爬虫扩展

ProcurementCrawlerService 目前只抓特定网站,你可以修改 WebMagic 的规则,抓取任意公开招标网站,存入 Neo4j 后做投标关系分析。


可以在这个骨架之上,构建自己真正需要的 AI 应用 —— 祝编码愉快! 🚀

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐