ChatModels
ChatModelAPI
Spring AI Chat Model API被设计成一个简单而便携的界面,用于与各种AI模型进行交互,允许开发人员以最少的代码更改在不同模型之间切换。这种设计符合Spring的模块化和可互换性理念。
此外,在用于输入封装的Prompt和用于输出处理的ChatResponse等配套类的帮助下,聊天模型API将通信与人工智能模型统一。它管理请求准备和响应解析的复杂性,提供直接和简化的API交互。
ChatModel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public interface ChatModel extends Model<Prompt, ChatResponse>, StreamingChatModel { default String call(String message) { Prompt prompt = new Prompt(new UserMessage(message)); Generation generation = this.call(prompt).getResult(); return generation != null ? generation.getOutput().getText() : ""; }
default String call(Message... messages) { Prompt prompt = new Prompt(Arrays.asList(messages)); Generation generation = this.call(prompt).getResult(); return generation != null ? generation.getOutput().getText() : ""; }
ChatResponse call(Prompt prompt);
default ChatOptions getDefaultOptions() { return ChatOptions.builder().build(); }
default Flux<ChatResponse> stream(Prompt prompt) { throw new UnsupportedOperationException("streaming is not supported"); } }
|
Prompt
封装了消息对象和可选模型请求选项的列表
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class Prompt implements ModelRequest<List<Message>> {
private final List<Message> messages;
private ChatOptions modelOptions;
@Override public ChatOptions getOptions() {...}
@Override public List<Message> getInstructions() {...}
}
|
Message
1 2 3 4 5 6 7 8 9 10 11
| public interface Content {
String getText();
Map<String, Object> getMetadata(); }
public interface Message extends Content {
MessageType getMessageType(); }
|
1 2 3 4 5 6
| public enum MessageType { USER("user"), ASSISTANT("assistant"), SYSTEM("system"), TOOL("tool"); }
|

Chat Options
用于定义一些可以传递给AI模型的可移植选项
允许在启动时设置默认配置,同时还提供了在每个请求的基础上覆盖这些设置
1 2 3 4 5 6 7 8 9 10 11 12 13
| public interface ChatOptions extends ModelOptions {
String getModel(); Float getFrequencyPenalty(); Integer getMaxTokens(); Float getPresencePenalty(); List<String> getStopSequences(); Float getTemperature(); Integer getTopK(); Float getTopP(); ChatOptions copy();
}
|

OllamaChatOptions 参数解释
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 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
| public class OllamaChatOptions implements ToolCallingChatOptions { private static final List<String> NON_SUPPORTED_FIELDS = List.of("model", "format", "keep_alive", "truncate");
@JsonProperty("numa") private Boolean useNUMA;
@JsonProperty("num_ctx") private Integer numCtx;
@JsonProperty("num_batch") private Integer numBatch;
@JsonProperty("num_gpu") private Integer numGPU;
@JsonProperty("main_gpu") private Integer mainGPU;
@JsonProperty("low_vram") private Boolean lowVRAM;
@JsonProperty("f16_kv") private Boolean f16KV;
@JsonProperty("logits_all") private Boolean logitsAll;
@JsonProperty("vocab_only") private Boolean vocabOnly;
@JsonProperty("use_mmap") private Boolean useMMap;
@JsonProperty("use_mlock") private Boolean useMLock;
@JsonProperty("num_thread") private Integer numThread;
@JsonProperty("num_keep") private Integer numKeep;
@JsonProperty("seed") private Integer seed;
@JsonProperty("num_predict") private Integer numPredict;
@JsonProperty("top_k") private Integer topK;
@JsonProperty("top_p") private Double topP;
@JsonProperty("min_p") private Double minP;
@JsonProperty("tfs_z") private Float tfsZ;
@JsonProperty("typical_p") private Float typicalP;
@JsonProperty("repeat_last_n") private Integer repeatLastN;
@JsonProperty("temperature") private Double temperature;
@JsonProperty("repeat_penalty") private Double repeatPenalty;
@JsonProperty("presence_penalty") private Double presencePenalty;
@JsonProperty("frequency_penalty") private Double frequencyPenalty;
@JsonProperty("mirostat") private Integer mirostat;
@JsonProperty("mirostat_tau") private Float mirostatTau;
@JsonProperty("mirostat_eta") private Float mirostatEta;
@JsonProperty("penalize_newline") private Boolean penalizeNewline;
@JsonProperty("stop") private List<String> stop;
@JsonProperty("model") private String model;
@JsonProperty("format") private Object format;
@JsonProperty("keep_alive") private String keepAlive;
@JsonProperty("truncate") private Boolean truncate;
@JsonProperty("think") private ThinkOption thinkOption;
@JsonIgnore private Boolean internalToolExecutionEnabled;
@JsonIgnore private List<ToolCallback> toolCallbacks;
@JsonIgnore private Set<String> toolNames;
@JsonIgnore private Map<String, Object> toolContext; }
|
ChatResponse
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class ChatResponse implements ModelResponse<Generation> {
private final ChatResponseMetadata chatResponseMetadata; private final List<Generation> generations;
@Override public ChatResponseMetadata getMetadata() {...}
@Override public List<Generation> getResults() {...}
}
|
AssistantMessage 也继承至Message ,messageType = MessageType.ASSISTANT
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Generation implements ModelResult<AssistantMessage> {
private final AssistantMessage assistantMessage; private ChatGenerationMetadata chatGenerationMetadata;
@Override public AssistantMessage getOutput() {...}
@Override public ChatGenerationMetadata getMetadata() {...}
}
|
Demo
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
| @SpringBootTest(classes = Application.class) public class ChatModelTest {
@Test public void test(@Autowired OllamaChatModel ollamaChatModel) { String called = ollamaChatModel.call("你是谁"); System.out.println(called); }
@Test public void test2(@Autowired OllamaChatModel ollamaChatModel) { Flux<String> res = ollamaChatModel.stream("写一篇1000字作文"); res.toIterable().forEach(System.out::println); }
@Test public void testMultimodality(@Autowired OllamaChatModel ollamaChatModel) { var imageResource = new ClassPathResource("2.png");
OllamaChatOptions ollamaOptions = OllamaChatOptions.builder() .model("gemma3:4b") .build();
Media media = new Media(MimeTypeUtils.IMAGE_PNG, imageResource);
ChatResponse response = ollamaChatModel.call( new Prompt( UserMessage.builder().media(media) .text(""" 描述这幅图的内容 """).build(), ollamaOptions ) );
System.out.println(response.getResult().getOutput().getText()); } }
|