本文是对Spring AI
中涉及到的AI相关核心概念的介绍,笔者结合LangChain
、LlamaIndex
的使用经验,尝试尽可能清晰的把这些概念解释清楚. 读者也可以参考官方文档作为补充.
模型
提到AI模型,我们的第一印象一定是GPT
,DeepSeek
这样的大语言模型(Large Language Models,LLMs),但其实还有其他的种类.
我们引用Spring AI文档的说法:
AI models are algorithms designed to process and generate information, often mimicking human cognitive functions.
AI模型是用于处理和生成信息的算法,通常模仿人类的认知功能。
我们所熟悉的Chat/文字生成的LLMs
是其中的一种,平时还经常用到的有生成图片的模型Diffusion
, 语音识别和语音合成模型ASR
,TTS
, Agents背后的知识库RAG技术的重要组件Embedding
模型等,分别都在各自领域发挥重要作用.(P.S.:笔者从事的数字人开发核心组件神经辐射场NeRF
也是一种重要的模型,被广泛运用在视频生成,自动驾驶等领域)
下图是Spring AI支持的模型类型:
Spring AI 现在支持输入/输出为文字,图片,音频的模型.
图片中最后一行的Embedding模型比较特殊,输入可以时文字、图片、音频,设置视频,输出是一个向量(称为嵌入,原因是,这个向量中包含了对于输入的很多特征信息的捕捉,可以认为是把特征信息嵌入到了向量中).
嵌入(Embedding
)模型的代表是SentenceTransformer
框架的一系列Bi-Encoder
,CrossEncoder
models,通常是基于BERT
这样的encoder-only
结构,但GPT
(Generative Pretrained Transoformer)这样的decoder-only
结构也用应用,两种架构都可以归类于Transformer
(P.S. 完整的Transformer架构是encoder-decoder结合的,但BERT
和GPT
都只用了其中一部分).
输入经过嵌入模型的处理得到的向量可以用来做分类,情感分析等.
提示词
提示词(Prompt)是和LLMs
交互中用的最多的,我们都有和Chat模型聊天的经验,并且也一定通过Chat模型来完成过一系列任务,例如翻译,文字改写、总结等. 我们的输入都可以认为是一种提示词,用来指导LLMs
完成我们给出的特定任务.
Prompts serve as the foundation for the language-based inputs that guide an AI model to produce specific outputs.
提示词(Prompts)是基于语言的输入的基础,用于指导AI模型生成特定的输出。
在调用LLMs的API进行交互的时候,和用WebUI Chat稍有不同,可以看一个OpenAI的官方例子就一目了然.
python
from openai import OpenAI
client = OpenAI()
response = client.responses.create(
model="gpt-4.1",
input=[
{
"role": "developer",
"content": "Talk like a pirate."
},
{
"role": "user",
"content": "Are semicolons optional in JavaScript?"
}
]
)
print(response.output_text)
从这个例子中我们可以看到,输入可以是一个数组,而数组中的每个对象是包括了role
,content
两个字段,content是我们的命令,而role是代表当前这个命令的角色(例如system角色就设定了对话中模型需要表现的行为和一些全局的上下文). 常用的role有 system
,assistant
,user
等,具体可以查看所调用的LLM
的文档.
提示词模板
创建有效的提示词涉及建立请求的上下文,并将请求中的部分内容替换为用户输入特定的值。
为了高效的创建提示词并且复用公共的部分,几乎所有的AI应用框架都提供了提示词模板的功能。
官方给的提示词模板的例子:
java
Tell me a {adjective} joke about {content}.
这里的{}
内的变量可以在模板生成字符串的时候被替换.
在 Spring AI 中,提示词模板可以类比为 Spring MVC
架构中的"视图"(View)。通常会提供一个模型对象(model object),例如一个 java.util.Map
,用于填充模板中的占位符。经过"渲染"后的字符串将成为提供给 AI 模型的提示内容。
发送到模型的提示的具体数据格式存在相当大的差异。最初,提示只是简单的字符串,但随着时间的推移,提示已经发展为包含多条消息,其中每条消息中的每个字符串都代表模型的一个不同角色。
Embedding

嵌入(Embeddings)是文本、图像或视频的数值表示,能够捕捉输入之间的关系。
嵌入的工作原理是将文本、图像和视频转换为浮点数数组,称为向量。这些向量旨在捕捉文本、图像和视频的含义。嵌入数组的长度称为向量的维度。
通过计算两段文本的向量表示之间的数值距离,应用程序可以确定用于生成嵌入向量的对象之间的相似性。
作为Java 开发者,其实没有必要去理解这些向量表示背后的复杂数学理论或具体实现。只要对它们在人工智能系统中的角色和功能有一个基本的了解就足够.
嵌入(Embeddings)在实际应用中还是能发挥很大作用的,例如前文所述. 在检索增强生成(Retrieval Augmented Generation, RAG)模式中, 它们能够将数据表示为语义空间中的点,这类似于欧几里得几何中的二维空间,但维度更高(BERT系列通常维度有768)。这意味着,就像欧几里得几何中平面上的点可以根据其坐标彼此靠近或远离一样,在语义空间中,点的接近程度反映了它们在含义上的相似性。关于相似主题的句子在这个多维空间中会被放置得更接近,就像图表上彼此靠近的点一样。这种接近性有助于执行诸如文本分类、语义搜索甚至产品推荐等任务,因为它允许人工智能根据这些概念在扩展的语义景观中的"位置"来识别和分组相关概念。
Token
只要调用过LLMs API,就或多或少会听说过token的概念。token可以近似 理解成单词,但是注意它不是单词.
先补充一下相关背景:
"Tokenize" 是一个在自然语言处理(NLP)和计算机科学中常用的术语,指的是将文本分割成更小的单元(称为"token")的过程。这些单元可以是单词、数字、符号或其他有意义的片段。Tokenization 是文本预处理的重要步骤,为后续的文本分析、机器学习或深度学习任务做准备。
在NLP
领域早期的分词(tokenize)处理中,的确是按照单词去切分(英语等印欧语系,单词被空格分开),但是随着词嵌入技术的发展,需要处理一些没有见过的词,即未登录词(Out-of-Vocabulary, OOV), 此时,按照统计来确定词表的方法就效果不好,于是开始通过一些算法来把单词进一步切分为词元,也就是这里的token,具体原理和算法就不在这里展开,huggingface上有具体的说明.
Token是人工智能模型工作方式的基本组成部分。在输入时,模型将单词转换为标记;在输出时,它们将标记再转换回单词。
在英语中,一个标记大致对应于一个单词的75%。作为参考,莎士比亚的全部作品,总共约90万单词,转换成大约120万标记。
也许更重要的是,标记 = 金钱。在托管的人工智能模型的上下文中,你的费用是由使用的标记数量决定的。输入和输出都对总标记数量有贡献。
此外,模型还受到标记限制,这限制了单次API调用中处理的文本量。这个阈值通常被称为"上下文窗口"。超出这个限制的文本将不会被模型处理。
结构化输出
人工智能模型的输出通常是一个java.lang.String
(在当前我们讨论的Spring AI领域中,如果是讨论LangChain
,那么输出的就是一个python字符串了),即使你要求回复是JSON
格式也是如此。它可能是一个正确的JSON
,但它并不是一个JSON
数据结构,只是一个字符串。此外,将"要求输出为JSON
"作为提示的一部分也并不是100%准确的。
P.S.:LangChain提供了JsonOutputParser
来将输出转为JSON
这种复杂性促使了一个专门领域的出现,该领域涉及创建能够产生预期输出的提示,然后将生成的简单字符串转换为可用于应用程序集成的可用数据结构。
模型能力的增强
LLMs只会掌握它的训练数据的知识,然而事物是一直在发展的,如何让模型利用最新的知识,当前主要有3种方法:
- 微调(Fine Tuning):这种传统的机器学习技术涉及调整模型并改变其内部权重。然而,对于像GPT这样规模庞大的模型来说,这是一个对机器学习专家来说极具挑战性且极其耗费资源的过程。此外,有些模型可能根本不提供这种选项;
- 提示嵌入(Prompt Stuffing):这是一种更实用的替代方法,涉及将你的数据嵌入到提供给模型的提示中。鉴于模型的标记限制,需要采用技术手段将相关数据呈现于模型的上下文窗口内。这种方法通常被称为"填充提示"(stuffing the prompt)。Spring AI库可以帮助你实现基于"填充提示"技术的解决方案,这种技术也被称为检索增强生成(Retrieval Augmented Generation,简称RAG);
- 工具调用(Tool Calling):这种技术允许注册工具(用户定义的服务),将大型语言模型连接到外部系统的API。Spring AI极大地简化了支持工具调用所需的代码编写.
RAG

检索增强生成(Retrieval Augmented Generation,简称RAG)旨在解决如何将相关数据整合到提示中以实现准确的人工智能模型响应。
这种方法采用批处理风格的编程模型,主工作流程是从文档中读取非结构化数据,对其进行转换,然后将其写入向量数据库 。总的来看,这是一个ETL
(提取、转换和加载)流程。向量数据库用于RAG技术的检索部分。
在将非结构化数据加载到向量数据库的过程中,最重要的转换之一是将原始文档拆分成更小的部分。将原始文档拆分成更小部分的过程包含两个重要步骤:
- 在拆分文档时,要保留内容的语义边界。例如,对于包含段落和表格的文档,应避免在段落或表格的中间进行拆分。对于代码,应避免在方法实现的中间进行拆分。
- 将文档的各个部分进一步拆分成大小仅为人工智能模型令牌限制的小百分比的部分。
RAG的下一个阶段是处理用户输入。当用户的问题需要由人工智能模型回答时,问题以及所有"相似"的文档片段都会被放入发送给人工智能模型的提示中。这就是使用向量数据库的原因,它非常擅长找到相似的内容。
ETL流程进一步介绍了如何协调从数据源提取数据并将其存储到结构化的向量存储库中的流程,确保数据在传递给人工智能模型时处于最佳检索格式。
ChatClient - RAG解释了如何使用QuestionAnswerAdvisor在您的应用程序中启用RAG功能。
更多细节可以参考Spring AI的详细文档.
工具调用
LLMs在训练完成后会被冻结,这导致其知识陈旧,且无法访问或修改外部数据。
工具调用机制解决了这些缺点。它允许你将自有的服务注册为工具,从而将大型语言模型连接到外部系统的API。这些系统可以为LLMs提供实时数据,并代表它们执行数据处理操作。
Spring AI
极大地简化了支持工具调用所需的代码。它为你处理工具调用对话。你可以将工具作为带有@Tool
注解的方法提供,并在提示选项中提供它,使其可供模型使用。此外,你还可以在单个提示中定义和引用多个工具。具体步骤如下:
-
当我们希望将工具提供给模型时,我们会将其定义包含在聊天请求中。每个工具定义包括名称、描述以及输入参数的模式。
-
当模型决定调用工具时,它会发送一个包含工具名称和符合定义模式的输入参数的响应。
-
应用程序负责使用工具名称来识别并执行工具,并使用提供的输入参数。
-
工具调用的结果由应用程序处理。
-
应用程序将工具调用的结果发送回模型。
-
模型使用工具调用结果作为附加上下文生成最终响应。
模型评估
有效评估人工智能系统对用户请求的输出对于确保最终应用的准确性和实用性至关重要。一些新兴技术使得可以利用预训练模型本身来实现这一目的。
这种评估过程涉及分析生成的响应是否与用户的意图以及查询的上下文一致。相关性、连贯性和事实正确性等指标被用来衡量人工智能生成响应的质量。
一种方法是将用户的请求和人工智能模型的响应同时呈现给模型,查询该响应是否与提供的数据一致。
此外,利用存储在向量数据库中的信息作为补充数据,可以增强评估过程,有助于确定响应的相关性。
Spring AI项目提供了一个评估器API,目前该API提供了用于评估模型响应的基本策略。请参阅评估测试文档以获取更多信息。
总结
本文介绍了Spring AI中和AI模型相关的核心概念并且适当做了一些科普性扩展,希望对大家使用Spring AI开发应用有所帮助.