1 环境介绍 在SpringAI中支持的SpringBoot是3.4.x,JDK的版本是17及以上的版本!
提供一个JDK17的下载地址: https://www.injdk.cn
2 第一个案例 通过idea来创建SpringBoot项目。idea的版本最好有比较新的版本。不然不支持JDK17的特性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 <?xml version="1.0" encoding="UTF-8" ?> <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-parent</artifactId > <version > 3.4.5</version > <relativePath /> </parent > <groupId > com.boge.ai</groupId > <artifactId > AiDemo1</artifactId > <version > 0.0.1-SNAPSHOT</version > <name > AiDemo1</name > <description > AiDemo1</description > <url /> <licenses > <license /> </licenses > <developers > <developer /> </developers > <scm > <connection /> <developerConnection /> <tag /> <url /> </scm > <properties > <java.version > 17</java.version > <spring-ai.version > 1.0.0-M8</spring-ai.version > </properties > <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > <dependency > <groupId > org.springframework.ai</groupId > <artifactId > spring-ai-starter-modelopenai</artifactId > </dependency > <dependency > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > <optional > true</optional > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-test</artifactId > <scope > test</scope > </dependency > </dependencies > <dependencyManagement > <dependencies > <dependency > <groupId > org.springframework.ai</groupId > <artifactId > spring-ai-bom</artifactId > <version > ${spring-ai.version}</version > <type > pom</type > <scope > import</scope > </dependency > </dependencies > </dependencyManagement > <build > <plugins > <plugin > <groupId > org.apache.maven.plugins</groupId > <artifactId > maven-compiler-plugin</artifactId > <configuration > <annotationProcessorPaths > <path > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > </path > </annotationProcessorPaths > </configuration > </plugin > <plugin > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-maven-plugin</artifactId > <configuration > <excludes > <exclude > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > </exclude > </excludes > </configuration > </plugin > </plugins > </build > </project >
然后在application.properties 中添加DeepSeek的配置信息
1 2 3 4 5 6 spring.ai.openai.api-key =sk-0a40f9289beb4017af7bf9910f9646d2412 spring.ai.openai.base-url =https://api.deepseek.com spring.ai.openai.chat.options.model =deepseek-chat spring.ai.openai.chat.options.temperature =0.7 spring.ai.openai.embedding.enabled =false
这块的api-key需要替换为自己的key,DeepSeek的站点: https://platform.deepseek.com/api_keys
然后就可以创建对应的controller来实现和DeepSeek的通信了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import org.springframework.ai.chat.messages.UserMessage;import org.springframework.ai.chat.model.ChatResponse;import org.springframework.ai.chat.prompt.Prompt;import org.springframework.ai.openai.OpenAiChatModel;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import reactor.core.publisher.Flux;import java.util.Map;@RestController public class ChatController { private final OpenAiChatModel chatModel; @Autowired public ChatController (OpenAiChatModel chatModel) { this .chatModel = chatModel; } @GetMapping("/ai/generate") public Map generate (@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) { return Map.of("generation" , this .chatModel.call(message)); } @GetMapping("/ai/generateStream") public Flux<ChatResponse> generateStream (@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) { Prompt prompt = new Prompt (new UserMessage (message)); return this .chatModel.stream(prompt); } }
浏览器的方式: localhost:8080/ai/generate?message=你好啊,你能介绍下你自己吗
3 ChatGPT 如果想和ChatGPT来交互,这块的实现方式比较多,比如直接去OpenAi的官网申请账号并充值,但是这种方式需要科学上网,我们也可以通过国内的代理来实现,比如https://www.openai-hk.com/docs/getting-started.html , https://ai-yyds.com/about
通过ddys来测试下:
然后修改下配置就可以了
1 2 3 4 5 6 spring.application.name =AiDemo1 spring.ai.openai.api-key =hk-w3q3id1000054953c829f33c861457133e3048fa220f1076 spring.ai.openai.base-url =https://api.openai-hk.com spring.ai.openai.chat.options.model =gpt-4o spring.ai.openai.chat.options.temperature =0.7
4 LLM输出配置 在深入研究即时工程技术之前,我们有必要了解如何配置 LLM 的输出行为。Spring AI 提供了多个配置选项,可让您通过 ChatOptions构建器控制生成的各个方 面。
4.1 temperature Temperature控制模型响应的随机性或“创造性”。
较低值(0.0-0.3):响应更确定、更集中。更适合事实类问题、分类问题或一致性至关重要的任务。
中等值(0.4-0.7):在确定性和创造性之间取得平衡。适用于一般用例。
值越高 (0.8-1.0):回复更具创意、多样性,且可能带来惊喜。更适合创意写作、头脑风暴或生成多样化选项。
问个问题给大模型:讲一个关于猫的故事。
当temperature=0.1的时候
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 从前,有一只名叫小白的猫,它住在一个宁静的小村庄里。小白是一只全身雪白的猫,只有 尾巴尖是黑色的,村子里的每个人都喜欢它,因为它不仅长得漂亮,还非常聪明。 小白每天都会在村子里四处游荡,和村民们打招呼。它最喜欢去的是村子中央的广场,因为 那里总是有许多孩子在玩耍。孩子们也很喜欢小白,他们会给它带来小鱼干和玩具球,小白 则会和他们一起玩耍,追逐着滚动的球,或是在阳光下懒洋洋地打盹。 有一天,小白在广场上发现了一只受伤的小鸟。小鸟的翅膀受了伤,无法飞翔。小白轻轻地 用鼻子碰了碰小鸟,小鸟发出微弱的叫声。小白知道它需要帮助,于是用嘴轻轻叼起小鸟, 把它带到了村子里最善良的老人家里。 老人看到小白带来的小鸟,立刻明白了情况。他小心翼翼地为小鸟包扎了翅膀,并给它准备 了一个舒适的小窝。小白每天都会来看望小鸟,陪伴它,直到小鸟的翅膀完全康复。 几周后,小鸟终于能够重新飞翔了。它在广场上空飞舞,向小白和村民们表达感谢。村子里 的孩子们欢呼雀跃,而小白则坐在广场中央,仰望着天空,满意地眯起了眼睛。 从那以后,小白不仅是村子里的宠儿,还成了村子里的小英雄。村民们更加爱护它,而小白 也继续在村子里快乐地生活着,帮助着每一个需要帮助的小动物。这个宁静的小村庄因为小 白的善良和聪明,变得更加温暖和幸福。
当temperature=0.7的时候
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 从前有一只名叫米娅的猫,她生活在一个宁静的小村庄里。米娅是一只全身雪白的猫咪,眼 睛像两颗蓝色的宝石,常常在村庄的花园里穿梭,像个小精灵似的。 米娅的主人,是村里的一位和蔼的老奶奶。老奶奶每天都会在院子里种花,米娅则在旁边玩 耍,时不时地用小爪子拨弄一下花瓣。村子里的每个人都喜欢米娅,因为她总是用她独特的 方式给大家带来欢乐。 有一天,村子里来了一个旅行者,他带着一个神秘的箱子。旅行者在村子里停留了一段时 间,米娅对他的箱子充满了好奇。她悄悄地靠近旅行者的住处,想看看箱子里到底藏着什么 秘密。 在一个月光明亮的夜晚,米娅终于有机会接近那个神秘的箱子。她发现箱子里居然是一架古 老的相机。旅行者用这架相机拍下了村庄的美丽景色,也拍下了米娅在花园里嬉戏的画面。 照片洗出来之后,村庄的人们都惊讶地发现,米娅的照片仿佛有一种神奇的魔力,每一个看 过照片的人都会感到一种莫名的快乐和宁静。 旅行者告诉大家,这架相机据说能捕捉到每一个被拍摄对象的灵魂之美,而米娅则是他见过 的最美丽的灵魂。村庄的人们纷纷感谢米娅为他们带来的快乐,并开始更加珍惜这个可爱的 小猫咪。 最终,旅行者离开了村庄,但他留下了一张米娅的照片,挂在村庄的广场上。从此,米娅成 了村子里的小明星,每个人都为她的存在而感到幸福和温暖。 这个故事告诉我们,有时候最简单的快乐就藏在我们身边,只需用心去发现与珍惜。米娅用 她的方式让村庄变得更加美好,也让每个人都意识到爱与快乐的重要。
当temperature=1的时候
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 从前有一只名叫小米的橘猫,住在一个宁静的小村庄里。小米是一只非常好奇的猫,每天都 喜欢在村庄里探险。村庄的居民都很喜欢它,因为它总是带来欢乐和惊喜。 一天,小米发现村庄边缘有一片从未探索过的森林。它决定去那里看看,兴奋地开始了新的 冒险。进入森林后,小米被那里的景色迷住了。树木高大翠绿,阳光透过树叶洒下斑驳的光 影,空气中弥漫着清新的泥土气息。 在森林里漫步时,小米听到了一阵轻柔的声音。它顺着声音走去,发现一只小鸟被困在树枝 之间。小米小心翼翼地用爪子拨开树枝,帮助小鸟恢复自由。小鸟感激地拍打翅膀,围着小 米转了几圈,然后飞向蓝天。 继续前进时,小米在一个小溪边发现了一只金色的鱼在欢快地游来游去。小米不禁停下来观 察那条鱼,惊讶于它的速度和优雅。就在这时,小米听到轻轻的笑声,转过头去,看到一群 小鹿正在草丛中嬉戏。它们的动作轻盈而快速,仿佛在与风舞蹈。 天色逐渐暗下来,小米意识到是时候回家了。它依依不舍地离开了这个如梦似幻的地方。但 是回到村庄后,小米的心情依然充满了温暖和喜悦,因为它知道,森林里的每一次冒险,都 是对生活的新的认识和探寻。 从此以后,小米经常去森林探险,并成为村庄的孩子们的引路者,它把自己在森林里的发现 告诉大家,带领孩子们一起感受自然的奇妙。小米的故事在村庄里传开,它成为所有人心中 的小英雄。 通过这段经历,小米不仅满足了自己的好奇心,还与森林里的动物们建立了深厚的友谊,证 明了帮助和友爱能够创造无限的好奇和快乐。这个故事告诉我们,探索未知不仅能让我们了 解世界,还能让我们发现心灵深处的美好。
配置temperature的信息
4.2 MaxTokens 该 maxTokens参数限制了模型在响应中可以生成的标记(词片段)的数量。
低值(5-25):适用于单个单词、短语或分类标签。
中等值(50-500):用于段落或简短解释。
高值(1000+):适用于长篇内容、故事或复杂的解释。
4.3 Top-K 和 Top-P 这些参数可以对生成过程中的令牌选择过程进行细粒度的控制。
Top-K:将 token 的选择范围限制为 K 个最有可能的后续 token。值越高(例如 40-50),多样性越好。
Top-P(核采样):从最小的标记集中动态选择,其累积概率超过 P。0.8-0.95 之类的值很常见。
注意:
top_p 是 OpenAI 模型普遍支持的参数。
top_k 并不是所有模型都支持(OpenAI 的 gpt-3.5-turbo默认不支持top_k,但某些 Hugging Face 模型支持)。
Spring AI 会自动映射这些配置到底层模型调用参数中。
让我们通过一个具体的例子来理解 top-k 和 top-p 的工作原理。 假设我们正在生成下一个单词,模型预测了以下10个可能的单词及其对应的概率:
单词
概率
猫
0.3
狗
0.25
鱼
0.15
老鼠
0.1
兔子
0.08
鸟
0.04
蛇
0.03
龟
0.02
松鼠
0.02
蝴蝶
0.01
Top-K 示例
如果我们使用 top-k=3(即只考虑概率最高的前3个单词),那么我们将只关注“猫”、“狗”和“鱼”,这三个单词的概率分别是0.3、0.25和0.15。在这种情况下,模型将从这三个单词中选择下一个单词输出。这就像你只能从三个最有可能的选项中选一个,这样可能会错过一些虽然不太常见但有趣的单词,比如“兔子”。
Top-P 示例
现在,如果我们使用 top-p=0.7,我们需要找到累积概率达到或超过70%的最小集合。按照上面的概率表,累加顺序如下:
“猫”的概率是0.3
加上“狗”的概率0.25后,总和为0.55
加上“鱼”的概率0.15后,总和变为0.7
所以,在这种情况下,累积概率达到70%所需的单词集合是“猫”、“狗”和“鱼”。这意味着,与 top-k=3 类似,但是这里的标准是基于累积概率而不是固定的单词数量。如果我们将 top-p 设置得更高,比如说0.9,那么我们会包括更多的单词直到累积概率达到90%,这样就会包含“老鼠”和“兔子”,从而提供更丰富的词汇选择范围。
通过这个例子可以看出, top-k 直接限定了要考虑的选择范围,而 top-p 则根据单词的概率分布动态调整范围,使得输出既可以集中在高概率单词上,也能在一定程度上探索更多样化的选择。这两种方法都可以用来调节语言模型生成文本时的多样性和质量。