给 AI 项目打地基:老码的技术选型复盘
一、开场先唠两句
各位,接 AI 项目这事儿,心情大概跟第一次相亲差不多:介绍人(教程)说得天花乱坠,真坐到桌前,你才发现最该问的不是"对方会不会做饭",而是"我家那口锅配不配得上人家的灶"。
这个 ai-agent 项目就是这么开始的。任务听起来很朴素:用一个 Java 项目,把 AI 应用该有的东西跑一遍。
结果跑下来,干了四件事:
- 把 Spring Boot 工程底子搭起来,Web、依赖、文档、测试都有;
- 试了两套大模型接入框架:Spring AI 和 LangChain4j;
- 真做了一个能用的业务:AI 恋爱大师,带会话管理、多轮记忆、MySQL 落库;
- 给项目接上了 AOCI 认知索引,让下一个接手的人(或者 AI)别再从零读代码。
别慌,问题不大。咱们一件一件说。
二、这项目到底在干嘛
一句话版本:它不是"接了个大模型接口",而是把模型能力塞进了一个能维护的后端工程里。
模型本身不稀罕,网上调一次 API 只要十分钟。难的是后面这些事:用户说的话怎么记住、下次怎么接着聊、历史存哪、接口给谁调、以后怎么改。
就像开饭馆,请个厨子不难,难的是采购、库存、点单、结账得成体系。厨子心情不好还能换,系统里哪一环断了,客人当场就能看见。
三、技术选型:挑队友,不看头衔看合拍
版本清单
| 组件 | 版本 | 老码点评 |
|---|---|---|
| Spring Boot | 3.4.4 | 项目地基,生态成熟 |
| Java | 17 | 能用、够用、本机就有 |
| Spring AI | 1.0.0(BOM 管理) | 和 Spring Boot 同源,配置顺手 |
| DeepSeek | deepseek-chat |
走 OpenAI 兼容协议 |
| MySQL | 8.0.28(阿里云 RDS) | 存会话和消息 |
| Knife4j | 4.4.0 | 接口文档,中文界面 |
| Hutool | 5.8.37 | 顺手工具,比如生成 UUID |
| LangChain4j | 1.0.0-beta2 | 第二套接入验证,别轻易双开 |
| mysql-connector-j | 8.4.0 | 连库用的驱动,注意它不负责管理连接池 |
Java 版本:从 21 掉头回 17
最初按教程准备的是 Java 21。开工一看,本机只有 JDK 17,装新 JDK 又要折腾环境变量、IDE、Maven 一堆设置。
我的选择很简单:能稳定跑起来的版本,就是好版本。 Spring Boot 3.4 最低要 Java 17,够用,直接降。
项目里的 java.version 是编译目标,不是许愿池。你写 21,机器上没有 21,构建就当场翻脸。
为什么是 Spring AI
理由不复杂,就三个字:不折腾。
- 配置写在
application.yml,自动装配ChatModel; ChatClient链式调用,写起来像说人话;- 会话记忆、RAG、工具调用都有官方抽象,后面加功能不用掀桌子。
对已经在写 Spring Boot 的团队,这是上手成本最低的一条路。
顺手也接了 LangChain4j
LangChain4j 是 Java AI 圈另一套成熟方案,模型适配面广。我把它也接上,是为了做个对照:同一把 DeepSeek Key,两套框架配置起来差在哪。
但丑话说前面:两套框架并存,等于家里养两只猫。 平时各吃各的,出事的时候你分不清是谁打翻的花瓶。正式项目建议只留一套。
DeepSeek 为什么不写专属适配
因为它兼容 OpenAI 的 Chat Completions 协议。Spring AI 用 OpenAI starter 改个 base-url;LangChain4j 用 langchain4j-open-ai 改个地址。省下来的时间,够你多写两个接口。
yaml
spring:
ai:
openai:
base-url: https://api.deepseek.com
chat:
options:
model: deepseek-chat
注意一个现实问题:DeepSeek 不提供 Embedding 接口。以后要做 RAG,向量化那一步得另找模型,比如 DashScope 或本地 Ollama。别等到写检索代码那天才发现这个坑。
四、工程长什么样
ai-agent
├── src/main/java/com/yxl/aiagent
│ ├── AiAgentApplication.java # 启动类
│ ├── controller/HealthController # 健康检查
│ ├── demo/invoke/ # 模型调用示例
│ └── love/ # AI 恋爱大师业务
│ ├── controller/
│ ├── dto/
│ ├── memory/
│ └── LoveConfig / LoveService / LovePrompts
├── src/main/resources
│ ├── application.yml
│ └── schema.sql
├── pom.xml
└── .mvn/wrapper/
包结构没什么花活。业务放在 love 下面,自己的 Controller、DTO、记忆实现各归各位。以后要加新业务,照着这个盒子再开一个就行。
五、这堆东西怎么一步步长出来的
- 搭地基:建工程,加 Web 和 Lombok,先写个
/health,确认服务能起来; - 装门面:接 Hutool 和 Knife4j,让接口看得见、点得动;
- 通模型:Spring AI 和 LangChain4j 分别打通 DeepSeek;
- 做业务:恋爱大师的基础对话,加上多轮记忆;
- 落数据:MySQL 两张表,会话和消息都能查;
- 留地图:接 AOCI,把项目认知沉淀成文档,方便后面接手。
顺序不建议打乱。地基没稳就上模型,出了问题你都不知道该先看日志,还是先怀疑网络。
六、坑点提醒(这几条都是用时间换的)
- API Key 和数据库密码别写死在代码里。 演示项目也一样,哪天传到公开仓库,就得连夜轮换。
- 版本兼容比业务代码更磨人。 本项目就撞上过 IDEA 2021.3 和 Maven 3.9.9 不兼容,最后把 wrapper 降到 3.8.1 才收工。
- 两套 AI 框架别长期并存。 验证可以,长期维护要有心理准备。
- 数据库依赖要提前想清楚。 项目后来开了
schema.sql自动建表,好处是省事,代价是数据库连不上,应用就起不来。 - 记不住的东西要写下来。 所以这个知识库和 AOCI 索引都存在,不是为了好看。
七、老码的总结
技术选型这事儿,跟装修一个道理:不是把最贵的材料堆一起就住得舒服,而是水电、防水、承重墙得对得上。
这个项目的价值,不在"用上了大模型",而在于把模型调用、会话记忆、数据库、接口文档、工程认知这几根管子接成了一整条线。线通了,后面加功能就是拧螺丝;线不通,加什么都是糊墙。
先看日志,别慌,问题不大。要是需求还继续加------这个需求得加钱。