
ai搭建步骤和踩坑记录
构思:目的是学习并了解ai
技术选择:本项目是springboot3,所以自然先选择spring ai。但spring ai高级特性没有langchain4j方便,作为入门探索应该还是足够,后续可以考虑更换。
先去了解基本的llm基本知识,可以看之前那篇
[Agent与大模型学习路线整理] (https://shijiucode.cn/posts/67)
[深入探讨AI Agents(大佬力作,强烈推荐!持续更新)] (https://github.com/bojieli/ai-agent-book) [或者点这里下载] (https://github.com/bojieli/ai-agent-book/releases/download/latest/AI-Agents-in-Depth-zh-CN.pdf)
简单的对话壳子
开干:网页端印象中ai的主流交互是:流式对话,会话管理
先做会话,先不做登录登出,而是基于浏览器device-id+session(uuid),单个session独立会话
简单的flux chat,流式输出完成后保存对话记录到数据库留档
第二次对话:发现丢失了上次对话的记忆,发现ai是没有记忆的,所谓的记忆 本质是本次内容携带上之前的对话内容
但是ai是有上下文长度的,输入和输出是有限制的,无脑拼接终究会撑爆。
于是我需要对上下文进行压缩,了解到上下文压缩有很多种方式
-
简单滑动窗口(保留前n条对话历史,超过的部分丢弃)
-
摘要窗口(截取前n条,超过n条做一次摘要压缩,远古内容细节也会丢失,但是比简单截取好点)
上面是短期记忆(即会话级别),
长期记忆还可以这样做(跨会话):对话内容存为向量,对话前执行相似度检索到相关上下文拼接,语义更加精准,复杂度更高
其中最简单的是:粗暴截取前20条。超过20条的记忆会丢失。
我选择先做简单截取,后续再考虑优化别的方案,我前端限制了输入的长度,输出的长度也可控,20条对于目前的模型来说还是能够支持。
系统提示词管理
简单的对话没有特色,只是调通了api,想再深入做一些高级的东西,那干脆结合博客本身
先做了文章的ai摘要,自动ai评论,也是很简单的功能。
然后我注意到有的人的ai是有人设的,所谓自定义的智能体(当然智能体更加复杂一点),输入一段提示词作为它的人设,那对应到这里就算system message(系统提示词)
它区别于用户每次对话输入的提示词,作用于全局,角色,位置,权重都更高。
所以我干脆也整了个系统提示词,设定我的ai是什么样的人设。同时加了一些限制,避免被回答诱导性问题。
好了,现在我的提示词都写死在后端代码,改起来非常不方便,那我就把它抽离到系统配置中,在后台可以随时自定义修改。
接入RAG
我希望ai能结合我站内的文章内容进行回答,尤其是有相关资料的时候最好能够贴出来,我一点击直接跳转到对应的文章。那就需要RAG。
RAG本质还是一样的,llm最基础的交互只有输入和输出,它只能听/说,在传给ai前,把检索到的知识内容塞给ai,让它来基于这些知识来回答。
向量数据库做RAG是目前主流且推荐的方式(其实用传统数据库也能实现,本质是一样的)
对于向量我的理解就是可以用来做相似度检索,它每次返回的结果区别于传统数据库,不是固定的,像传统的检索可能需要匹配到关键字,或者分词匹配到(elastic search),而相似度检索就可以做到查到和我语义相近的内容,所以它比关键字匹配更加适合,
前提需要你的数据库能够存向量,很遗憾博主用的mysql8并不支持向量(更高版本支持),所以又整了个Milvus。
需要把文章转为ai模型可识别的向量,也需要经过专门的embedding模型来嵌入,而且协议不同的话,换了个embedding,ai就不认识内容了。(只有在转成向量时需要嵌入,后续的向量检索就不需要啦)
于是加上向量,一顿调试后,输入相关内容,就能召回关联的文章,在对话后贴出对应的文章,可以直接跳转啦。
然后发现我有时输入不相干的问题,它也召回了文章,最后发现是参数没设置对,修改参数调试解决。相似度阈值0.5 => 0.6。
当然RAG检索也有更加深入的门道,比如做语义优化等。(后续再做,todolist +1)
AI功能打算上线,那就不能用会话机制了,于是修改了原先的会话机制,改为基于登录注册用户,且限制日对话次数(预算有限T_T)
工具-给模型手脚
正宗的智能体,有llm,记忆,工具调用,规划,反馈执行。
那下一步就是做工具调用了
Function Call 虽然听起来高大上,其实就是告诉ai 我有哪些神奇妙妙工具,你在需要的时候可以调用,然后它以某种格式告诉业务层,ok啊我要调用锤子模块,业务层帮忙调用,然后ai拿到调用接口再次进行处理。
简单的FC其实没什么必要上MCP
MCP是一种协议,规范了AI与工具之间的调用方式,比如你的工具并非本地,或者想共享,可以遵循这个协议,复用性更强。
那么我这里只是探索FC的使用,就没先实现MCP了,其实也简单,理解了它的作用就行了(之前让ai生成了个代码生成的MCP,结果那会同事都不愿意用,哈哈)
简单写了几个工具类(查看当前时间,数学计算,文本替换),每个工具要有描述,告诉ai是做什么用的,输入输出的格式,丢给ai一个工具列表。ai模型自己决策何时调用。
我这里用的qwen-3.7 max,发现开了工具调用后,模型的响应明显变慢,优化了tools的描述也不行,可能是模型层的原因,有解决方案是在工具决策时采用别的模型,在回答时采用主模型。这里涉及到多模型切换,也是后续可能考虑做的东西。
目前进度就到这里,虽然现在还是demo级别,但作为学习探索,也收获了一些。
持续更新中,,,未完待续。
结尾
vibe coding的时代,你不必把时间耗费到编写-调试上,更重要的还是架构思维,无论是写代码,AI生图,生视频,还是其他领域,不同思维生成出来的东西完全不同,技术不再是壁垒,决定高度的是你本人的专业性。