大模型集成实现分析
请关注微信公众号:阿呆-bot
1. 工程结构概览
Spring AI 支持多种大模型提供商,每个提供商都有独立的实现模块。虽然实现细节不同,但它们都遵循统一的抽象模式。下面我们来看看主要的模型实现:- models/
- ├── spring-ai-openai/ # OpenAI 实现
- │ ├── OpenAiChatModel.java
- │ ├── OpenAiEmbeddingModel.java
- │ └── api/ # 底层 API 客户端
- │ └── OpenAiApi.java
- │
- ├── spring-ai-deepseek/ # DeepSeek 实现
- │ ├── DeepSeekChatModel.java
- │ └── api/
- │ └── DeepSeekApi.java
- │
- ├── spring-ai-oci-genai/ # Oracle OCI GenAI 实现
- │ ├── OCICohereChatModel.java
- │ └── OCIEmbeddingModel.java
- │
- └── spring-ai-transformers/ # 本地 Transformer 模型
- └── TransformersEmbeddingModel.java
复制代码 2. 通用实现模式
所有大模型实现都遵循相同的模式:
- 实现核心接口:实现 ChatModel 或 EmbeddingModel
- 底层 API 客户端:封装提供商的 HTTP API
- 选项管理:每个模型有自己的 Options 类
- 密钥管理:通过 ApiKey 接口管理认证
- 重试机制:集成 Spring Retry
- 观察性:集成 Micrometer
3. 实现模式关系图
4. 密钥管理机制
4.1 ApiKey 接口设计
Spring AI 使用 ApiKey 接口统一管理所有模型的密钥:- public interface ApiKey {
- String getValue(); // 获取当前有效的密钥
- }
复制代码 这个设计的巧妙之处在于:
- 支持静态密钥:SimpleApiKey 直接存储密钥
- 支持动态刷新:可以实现自动刷新的密钥(比如 GCP 的短期密钥)
- 类型安全:所有模型都使用相同的接口
4.2 密钥使用方式
在 API 客户端中,密钥通过 HTTP Header 传递:- // OpenAiApi 中的密钥使用
- this.restClient = restClientBuilder.clone()
- .baseUrl(baseUrl)
- .defaultRequest(requestHeadersSpec -> {
- if (!(apiKey instanceof NoopApiKey)) {
- requestHeadersSpec.header(HttpHeaders.AUTHORIZATION,
- "Bearer " + apiKey.getValue());
- }
- })
- .build();
复制代码 每次请求都会调用 apiKey.getValue(),这样如果密钥需要刷新,实现类可以在内部处理。
4.3 密钥配置方式
密钥可以通过多种方式配置:
方式一:配置文件- spring.ai.openai.api-key=${OPENAI_API_KEY}
复制代码 方式二:环境变量- export OPENAI_API_KEY=sk-xxx
复制代码 方式三:程序化配置- OpenAiApi api = OpenAiApi.builder()
- .apiKey(new SimpleApiKey("sk-xxx"))
- .build();
复制代码 5. 具体实现分析
5.1 OpenAI 实现
OpenAI 的实现是最完整的,支持同步和流式调用:- public class OpenAiChatModel implements ChatModel {
- private final OpenAiApi openAiApi;
- private final OpenAiChatOptions defaultOptions;
- private final RetryTemplate retryTemplate;
- private final ToolCallingManager toolCallingManager;
-
- @Override
- public ChatResponse call(Prompt prompt) {
- // 1. 构建请求 Prompt(处理工具调用)
- Prompt requestPrompt = buildRequestPrompt(prompt);
-
- // 2. 调用底层 API
- ResponseEntity<ChatCompletion> response = retryTemplate.execute(
- ctx -> openAiApi.chatCompletion(toRequest(requestPrompt))
- );
-
- // 3. 转换响应
- return toChatResponse(response);
- }
-
- @Override
- public Flux<ChatResponse> stream(Prompt prompt) {
- // 流式调用类似,但返回 Flux
- return openAiApi.chatCompletionStream(toRequest(prompt))
- .map(this::toChatResponse);
- }
- }
复制代码 特点:
- 完整的工具调用支持
- 支持流式响应
- 完善的错误处理和重试
- 支持多模态(图像、音频)
5.2 DeepSeek 实现
DeepSeek 的实现与 OpenAI 类似,但更简洁:- public class DeepSeekChatModel implements ChatModel {
- private final DeepSeekApi deepSeekApi;
- private final DeepSeekChatOptions defaultOptions;
-
- @Override
- public ChatResponse call(Prompt prompt) {
- Prompt requestPrompt = buildRequestPrompt(prompt);
- ChatModelObservationContext context = ChatModelObservationContext.builder()
- .prompt(requestPrompt)
- .provider("DEEPSEEK")
- .build();
-
- return ChatModelObservationDocumentation.CHAT_MODEL_OPERATION
- .observation(...)
- .observe(() -> {
- ResponseEntity<ChatCompletion> response =
- deepSeekApi.chatCompletion(toRequest(requestPrompt));
- return toChatResponse(response);
- });
- }
- }
复制代码 特点:
- 结构清晰,代码简洁
- 支持观察性(Micrometer)
- 支持工具调用
5.3 OCI GenAI 实现
OCI 的实现使用了 Oracle 的官方 SDK:- public class OCICohereChatModel implements ChatModel {
- private final GenerativeAiInference genAi; // OCI SDK 客户端
- private final OCICohereChatOptions defaultOptions;
-
- @Override
- public ChatResponse call(Prompt prompt) {
- // 使用 OCI SDK 调用
- ChatRequest request = toCohereChatRequest(prompt, options);
- ChatResponse ociResponse = this.genAi.chat(request);
- return toGenerations(ociResponse, options);
- }
- }
复制代码 特点:
- 使用官方 OCI SDK
- 需要配置 compartment 和 serving mode
- 支持 Cohere 模型
5.4 Transformers 实现(本地模型)
Transformers 实现比较特殊,它不调用远程 API,而是在本地运行 ONNX 模型:- public class TransformersEmbeddingModel extends AbstractEmbeddingModel {
- private OrtSession session; // ONNX Runtime 会话
- private HuggingFaceTokenizer tokenizer;
-
- @Override
- public EmbeddingResponse call(EmbeddingRequest request) {
- // 1. Tokenize 输入文本
- Encoding encoding = tokenizer.encode(request.getInstructions());
-
- // 2. 运行 ONNX 模型
- OnnxTensor inputTensor = OnnxTensor.createTensor(
- ortEnvironment,
- encoding.getIds()
- );
- OrtSession.Result result = session.run(
- Map.of("input_ids", inputTensor)
- );
-
- // 3. 提取嵌入向量
- float[] embedding = extractEmbedding(result);
-
- return new EmbeddingResponse(List.of(new Embedding(embedding)));
- }
- }
复制代码 特点:
- 完全本地运行:不需要 API 密钥
- 使用 ONNX Runtime:高性能推理引擎
- 支持 GPU 加速:可以配置 GPU 推理
- 模型缓存:自动下载和缓存模型文件
6. 实现对比分析
特性OpenAIDeepSeekOCITransformersAPI 类型REST APIREST APIOCI SDK本地 ONNX密钥管理ApiKey 接口ApiKey 接口OCI 认证无需密钥流式支持✅✅❌❌工具调用✅✅✅N/A多模态✅❌❌N/A重试机制✅✅✅N/A观察性✅✅✅✅7. 关键实现细节
7.1 请求构建模式
所有实现都遵循相同的请求构建模式:- // 1. 合并默认选项和运行时选项
- ChatOptions requestOptions = ModelOptionsUtils.merge(
- prompt.getOptions(),
- this.defaultOptions,
- ChatOptions.class
- );
- // 2. 转换为提供商特定的请求对象
- ProviderRequest providerRequest = toProviderRequest(prompt, requestOptions);
- // 3. 调用底层 API
- ProviderResponse providerResponse = apiClient.call(providerRequest);
- // 4. 转换为 Spring AI 响应
- ChatResponse chatResponse = toChatResponse(providerResponse);
复制代码 7.2 工具调用处理
支持工具调用的模型(如 OpenAI、DeepSeek)都实现了类似的工具调用流程:- // 1. 解析工具定义
- List<ToolDefinition> toolDefinitions =
- toolCallingManager.resolveToolDefinitions(options);
- // 2. 将工具定义添加到请求中
- request.setTools(toolDefinitions);
- // 3. 调用模型
- ChatResponse response = apiClient.call(request);
- // 4. 检查是否有工具调用请求
- if (response.hasToolCalls()) {
- // 5. 执行工具调用
- ToolExecutionResult toolResult =
- toolCallingManager.executeToolCalls(prompt, response);
-
- // 6. 将工具结果作为新的 Prompt 再次调用
- return call(new Prompt(toolResult.getConversationHistory()));
- }
复制代码 7.3 流式处理实现
流式处理使用 Reactor 的 Flux:- @Override
- public Flux<ChatResponse> stream(Prompt prompt) {
- return webClient.post()
- .uri("/v1/chat/completions")
- .bodyValue(toRequest(prompt))
- .retrieve()
- .bodyToFlux(ServerSentEvent.class)
- .filter(event -> !"[DONE]".equals(event.data()))
- .map(this::toChatResponse);
- }
复制代码 8. 外部依赖
不同实现的依赖差异:
8.1 OpenAI/DeepSeek
- Spring Web:RestClient 和 WebClient
- Jackson:JSON 处理
- Spring Retry:重试机制
8.2 OCI GenAI
- OCI SDK:Oracle 官方 SDK
- Spring Web:HTTP 客户端(如果需要)
8.3 Transformers
- ONNX Runtime:ONNX 模型推理
- DJL:Deep Java Library(Tokenizer)
- 无网络依赖:完全本地运行
9. 工程总结
Spring AI 的大模型集成实现有几个亮点:
统一抽象,灵活实现。所有模型都实现相同的接口(ChatModel、EmbeddingModel),但底层实现可以完全不同。这种设计让用户可以轻松切换模型,而不需要改业务代码。今天用 OpenAI,明天想换 DeepSeek?改个配置就行。
密钥管理统一化。通过 ApiKey 接口,所有模型使用相同的密钥管理方式。这简化了配置,也为未来的动态密钥刷新提供了扩展点。想从配置中心动态获取密钥?实现 ApiKey 接口就行。
选项合并机制。ModelOptionsUtils.merge() 提供了灵活的选项合并机制,支持默认选项和运行时选项的合并,让配置既灵活又简单。默认配置在 application.yml,运行时可以动态调整。
观察性内置。所有实现都集成了 Micrometer,提供了完善的指标和追踪能力。这对于生产环境非常重要,可以监控模型调用次数、延迟、错误率等。
本地模型支持。Transformers 实现展示了如何在本地运行模型,这对于数据隐私要求高的场景非常有价值。数据不出本地,完全可控。
总的来说,Spring AI 的大模型集成实现既统一又灵活。统一的接口让代码简洁,灵活的实现让每个提供商都能发挥自己的优势。这种设计让 Spring AI 能够支持 20+ 种不同的模型提供商,同时保持代码的可维护性。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |