From 2889245d651bf2e866168c371ceedfceee06291e Mon Sep 17 00:00:00 2001
From: LuanY77 <2307984361@qq.com>
Date: Fri, 18 Jul 2025 22:33:12 +0800
Subject: [PATCH] =?UTF-8?q?Test:=20=E6=B7=BB=E5=8A=A0=20Ollama=20=E6=A8=A1?=
=?UTF-8?q?=E5=9E=8B=E5=AE=9E=E7=8E=B0=E5=92=8C=E6=B5=8B=E8=AF=95=E4=BB=A3?=
=?UTF-8?q?=E7=A0=81(=E5=88=9D=E6=AD=A5=E6=A1=86=E6=9E=B6)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ai/interact/transport/Transport.java | 1 +
.../liteflow-ai-model-ollama/pom.xml | 15 ++
.../ollama/constants/OllamaConstant.java | 14 ++
.../interact/OllamaProtocolTransformer.java | 41 ++++++
.../ollama/model/chat/OllamaChatConfig.java | 59 ++++++++
.../ollama/model/chat/OllamaChatModel.java | 52 +++++++
liteflow-ai/liteflow-ai-test/pom.xml | 11 ++
.../ai/model/ollama/ModelConfiguration.java | 42 ++++++
.../ai/model/ollama/ModelFactoryTest.java | 129 ++++++++++++++++++
9 files changed, 364 insertions(+)
create mode 100644 liteflow-ai/liteflow-ai-model/liteflow-ai-model-ollama/src/main/java/com/yomahub/liteflow/ai/model/ollama/constants/OllamaConstant.java
create mode 100644 liteflow-ai/liteflow-ai-model/liteflow-ai-model-ollama/src/main/java/com/yomahub/liteflow/ai/model/ollama/interact/OllamaProtocolTransformer.java
create mode 100644 liteflow-ai/liteflow-ai-model/liteflow-ai-model-ollama/src/main/java/com/yomahub/liteflow/ai/model/ollama/model/chat/OllamaChatConfig.java
create mode 100644 liteflow-ai/liteflow-ai-model/liteflow-ai-model-ollama/src/main/java/com/yomahub/liteflow/ai/model/ollama/model/chat/OllamaChatModel.java
create mode 100644 liteflow-ai/liteflow-ai-test/src/test/java/com/yomahub/liteflow/ai/model/ollama/ModelConfiguration.java
create mode 100644 liteflow-ai/liteflow-ai-test/src/test/java/com/yomahub/liteflow/ai/model/ollama/ModelFactoryTest.java
diff --git a/liteflow-ai/liteflow-ai-core/src/main/java/com/yomahub/liteflow/ai/interact/transport/Transport.java b/liteflow-ai/liteflow-ai-core/src/main/java/com/yomahub/liteflow/ai/interact/transport/Transport.java
index 21d43cbad..c15b4f03b 100644
--- a/liteflow-ai/liteflow-ai-core/src/main/java/com/yomahub/liteflow/ai/interact/transport/Transport.java
+++ b/liteflow-ai/liteflow-ai-core/src/main/java/com/yomahub/liteflow/ai/interact/transport/Transport.java
@@ -47,6 +47,7 @@ public interface Transport {
default String buildRequestBody(ChatConfig config, ChatRequest request) {
return config.toRequestBody()
.merge(request.toRequestBody())
+ .put("prompt", "Why sky is blue?")
.toJsonString();
}
}
diff --git a/liteflow-ai/liteflow-ai-model/liteflow-ai-model-ollama/pom.xml b/liteflow-ai/liteflow-ai-model/liteflow-ai-model-ollama/pom.xml
index 698ffb6f7..aec4b9315 100644
--- a/liteflow-ai/liteflow-ai-model/liteflow-ai-model-ollama/pom.xml
+++ b/liteflow-ai/liteflow-ai-model/liteflow-ai-model-ollama/pom.xml
@@ -18,6 +18,21 @@
liteflow-ai-core
${revision}
+
+
+ org.springframework.boot
+ spring-boot-autoconfigure
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+
\ No newline at end of file
diff --git a/liteflow-ai/liteflow-ai-model/liteflow-ai-model-ollama/src/main/java/com/yomahub/liteflow/ai/model/ollama/constants/OllamaConstant.java b/liteflow-ai/liteflow-ai-model/liteflow-ai-model-ollama/src/main/java/com/yomahub/liteflow/ai/model/ollama/constants/OllamaConstant.java
new file mode 100644
index 000000000..00306fd4c
--- /dev/null
+++ b/liteflow-ai/liteflow-ai-model/liteflow-ai-model-ollama/src/main/java/com/yomahub/liteflow/ai/model/ollama/constants/OllamaConstant.java
@@ -0,0 +1,14 @@
+package com.yomahub.liteflow.ai.model.ollama.constants;
+
+/**
+ * TODO
+ *
+ * @author 苍镜月
+ * @since TODO
+ */
+
+public interface OllamaConstant {
+
+ String PROVIDER_NAME = "ollama";
+
+}
diff --git a/liteflow-ai/liteflow-ai-model/liteflow-ai-model-ollama/src/main/java/com/yomahub/liteflow/ai/model/ollama/interact/OllamaProtocolTransformer.java b/liteflow-ai/liteflow-ai-model/liteflow-ai-model-ollama/src/main/java/com/yomahub/liteflow/ai/model/ollama/interact/OllamaProtocolTransformer.java
new file mode 100644
index 000000000..6b17c26e3
--- /dev/null
+++ b/liteflow-ai/liteflow-ai-model/liteflow-ai-model-ollama/src/main/java/com/yomahub/liteflow/ai/model/ollama/interact/OllamaProtocolTransformer.java
@@ -0,0 +1,41 @@
+package com.yomahub.liteflow.ai.model.ollama.interact;
+
+import com.yomahub.liteflow.ai.interact.pipeline.ChatContext;
+import com.yomahub.liteflow.ai.interact.protocol.ProtocolTransformer;
+import com.yomahub.liteflow.ai.interact.protocol.ProtocolTransformerRegistrar;
+import com.yomahub.liteflow.ai.interact.protocol.StreamingProtocolChunk;
+import com.yomahub.liteflow.ai.model.chat.entity.ChatResponse;
+import com.yomahub.liteflow.ai.model.chat.message.AssistantMessage;
+
+import static com.yomahub.liteflow.ai.model.ollama.constants.OllamaConstant.PROVIDER_NAME;
+
+/**
+ * TODO
+ *
+ * @author 苍镜月
+ * @since TODO
+ */
+
+public class OllamaProtocolTransformer extends ProtocolTransformerRegistrar implements ProtocolTransformer {
+
+ @Override
+ public StreamingProtocolChunk transformStreamingChunk(String streamChunk, ChatContext context) {
+ return null;
+ }
+
+ @Override
+ public ChatResponse transformStreamingResponse(ChatContext context) {
+ return null;
+ }
+
+ @Override
+ public ChatResponse transformBlockingResponse(String blockingResponse, ChatContext context) {
+ AssistantMessage message = new AssistantMessage(blockingResponse);
+ return new ChatResponse(message, context.getChatId(), true);
+ }
+
+ @Override
+ protected String getProviderName() {
+ return PROVIDER_NAME;
+ }
+}
diff --git a/liteflow-ai/liteflow-ai-model/liteflow-ai-model-ollama/src/main/java/com/yomahub/liteflow/ai/model/ollama/model/chat/OllamaChatConfig.java b/liteflow-ai/liteflow-ai-model/liteflow-ai-model-ollama/src/main/java/com/yomahub/liteflow/ai/model/ollama/model/chat/OllamaChatConfig.java
new file mode 100644
index 000000000..f3421c5c1
--- /dev/null
+++ b/liteflow-ai/liteflow-ai-model/liteflow-ai-model-ollama/src/main/java/com/yomahub/liteflow/ai/model/ollama/model/chat/OllamaChatConfig.java
@@ -0,0 +1,59 @@
+package com.yomahub.liteflow.ai.model.ollama.model.chat;
+
+import com.yomahub.liteflow.ai.interact.transport.TransportType;
+import com.yomahub.liteflow.ai.model.chat.entity.ChatConfig;
+
+import java.time.Duration;
+import java.util.Map;
+
+/**
+ * TODO
+ *
+ * @author 苍镜月
+ * @since TODO
+ */
+
+public class OllamaChatConfig extends ChatConfig {
+
+ public OllamaChatConfig() {
+ super();
+ }
+
+ public OllamaChatConfig(
+ String apiUrl,
+ String endPoint,
+ String apiKey,
+ String provider,
+ String model,
+ Duration timeout,
+ Map headersConfig,
+ boolean autoToolCallEnabled,
+ boolean streaming,
+ TransportType transportType
+ ) {
+ super(apiUrl, endPoint, apiKey, provider, model, timeout,
+ headersConfig, autoToolCallEnabled, streaming, transportType);
+ }
+
+ public OllamaChatConfig(Builder builder) {
+ super(builder);
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder extends ChatConfig.Builder {
+
+ @Override
+ protected Builder self() {
+ return this;
+ }
+
+ @Override
+ public OllamaChatConfig build() {
+ checkRequiredFields();
+ return new OllamaChatConfig(this);
+ }
+ }
+}
diff --git a/liteflow-ai/liteflow-ai-model/liteflow-ai-model-ollama/src/main/java/com/yomahub/liteflow/ai/model/ollama/model/chat/OllamaChatModel.java b/liteflow-ai/liteflow-ai-model/liteflow-ai-model-ollama/src/main/java/com/yomahub/liteflow/ai/model/ollama/model/chat/OllamaChatModel.java
new file mode 100644
index 000000000..5a9b47159
--- /dev/null
+++ b/liteflow-ai/liteflow-ai-model/liteflow-ai-model-ollama/src/main/java/com/yomahub/liteflow/ai/model/ollama/model/chat/OllamaChatModel.java
@@ -0,0 +1,52 @@
+package com.yomahub.liteflow.ai.model.ollama.model.chat;
+
+import com.yomahub.liteflow.ai.interact.InteractClient;
+import com.yomahub.liteflow.ai.interact.LlmInteractClient;
+import com.yomahub.liteflow.ai.model.chat.ChatModel;
+import com.yomahub.liteflow.ai.model.chat.entity.ChatRequest;
+import com.yomahub.liteflow.ai.model.chat.entity.ChatResponse;
+import com.yomahub.liteflow.ai.model.runtime.LiteFlowAIModel;
+
+import java.util.concurrent.CompletableFuture;
+
+import static com.yomahub.liteflow.ai.model.ollama.constants.OllamaConstant.PROVIDER_NAME;
+import static com.yomahub.liteflow.ai.model.runtime.ModelType.CHAT_MODEL;
+
+/**
+ * TODO
+ *
+ * @author 苍镜月
+ * @since TODO
+ */
+
+@LiteFlowAIModel(PROVIDER_NAME + CHAT_MODEL)
+public class OllamaChatModel implements ChatModel {
+
+ private final OllamaChatConfig config;
+ private final InteractClient interactClient;
+
+ public OllamaChatModel(OllamaChatConfig config) {
+ this.config = config;
+ this.interactClient = new LlmInteractClient();
+ }
+
+ @Override
+ public ChatResponse chat(ChatRequest request) {
+ return interactClient.chat(config, request);
+ }
+
+ @Override
+ public CompletableFuture chatAsync(ChatRequest request) {
+ return null;
+ }
+
+ @Override
+ public void stream(ChatRequest request) {
+
+ }
+
+ @Override
+ public OllamaChatConfig getModelConfig() {
+ return config;
+ }
+}
diff --git a/liteflow-ai/liteflow-ai-test/pom.xml b/liteflow-ai/liteflow-ai-test/pom.xml
index b89b48fc4..2cd300e29 100644
--- a/liteflow-ai/liteflow-ai-test/pom.xml
+++ b/liteflow-ai/liteflow-ai-test/pom.xml
@@ -18,6 +18,17 @@
liteflow-ai-core
${revision}
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+
+
+
+ com.yomahub
+ liteflow-ai-model-ollama
+ ${revision}
+
\ No newline at end of file
diff --git a/liteflow-ai/liteflow-ai-test/src/test/java/com/yomahub/liteflow/ai/model/ollama/ModelConfiguration.java b/liteflow-ai/liteflow-ai-test/src/test/java/com/yomahub/liteflow/ai/model/ollama/ModelConfiguration.java
new file mode 100644
index 000000000..a490e5c4e
--- /dev/null
+++ b/liteflow-ai/liteflow-ai-test/src/test/java/com/yomahub/liteflow/ai/model/ollama/ModelConfiguration.java
@@ -0,0 +1,42 @@
+package com.yomahub.liteflow.ai.model.ollama;
+
+import com.yomahub.liteflow.ai.interact.transport.TransportType;
+import com.yomahub.liteflow.ai.model.ollama.constants.OllamaConstant;
+import com.yomahub.liteflow.ai.model.ollama.interact.OllamaProtocolTransformer;
+import com.yomahub.liteflow.ai.model.ollama.model.chat.OllamaChatConfig;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * TODO
+ *
+ * @author 苍镜月
+ * @since TODO
+ */
+
+@Configuration
+public class ModelConfiguration {
+
+ @Bean
+ public OllamaChatConfig ollamaChatConfig() {
+ return OllamaChatConfig
+ .builder()
+ .apiUrl("http://localhost:11434/")
+ .endPoint("/api/generate")
+ .provider(OllamaConstant.PROVIDER_NAME)
+ .model("qwen3:32b")
+ .streaming(false)
+ .transportType(TransportType.HTTP)
+ .build();
+ }
+//
+// @Bean
+// public OllamaChatModel ollamaChatModel(OllamaChatConfig config) {
+// return new OllamaChatModel(config);
+// }
+
+ @Bean
+ public OllamaProtocolTransformer ollamaProtocolTransformer() {
+ return new OllamaProtocolTransformer();
+ }
+}
diff --git a/liteflow-ai/liteflow-ai-test/src/test/java/com/yomahub/liteflow/ai/model/ollama/ModelFactoryTest.java b/liteflow-ai/liteflow-ai-test/src/test/java/com/yomahub/liteflow/ai/model/ollama/ModelFactoryTest.java
new file mode 100644
index 000000000..bc2618dfe
--- /dev/null
+++ b/liteflow-ai/liteflow-ai-test/src/test/java/com/yomahub/liteflow/ai/model/ollama/ModelFactoryTest.java
@@ -0,0 +1,129 @@
+package com.yomahub.liteflow.ai.model.ollama;
+
+import com.yomahub.liteflow.ai.interact.protocol.ProtocolTransformer;
+import com.yomahub.liteflow.ai.interact.protocol.ProtocolTransformerFactory;
+import com.yomahub.liteflow.ai.model.chat.ChatModel;
+import com.yomahub.liteflow.ai.model.chat.entity.ChatOptions;
+import com.yomahub.liteflow.ai.model.chat.entity.ChatRequest;
+import com.yomahub.liteflow.ai.model.chat.entity.ChatResponse;
+import com.yomahub.liteflow.ai.model.chat.message.AssistantMessage;
+import com.yomahub.liteflow.ai.model.chat.message.Message;
+import com.yomahub.liteflow.ai.model.chat.message.MessageType;
+import com.yomahub.liteflow.ai.model.ollama.constants.OllamaConstant;
+import com.yomahub.liteflow.ai.model.ollama.model.chat.OllamaChatConfig;
+import com.yomahub.liteflow.ai.model.ollama.model.chat.OllamaChatModel;
+import com.yomahub.liteflow.ai.model.runtime.ModelRuntimeFactory;
+import com.yomahub.liteflow.ai.model.runtime.ModelRuntimeRegistrar;
+import com.yomahub.liteflow.ai.util.SpringUtil;
+import com.yomahub.liteflow.log.LFLog;
+import com.yomahub.liteflow.log.LFLoggerManager;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import javax.annotation.Resource;
+import java.util.*;
+
+/**
+ * TODO
+ *
+ * @author 苍镜月
+ * @since TODO
+ */
+
+@SpringBootTest(classes = {
+ ModelFactoryTest.class,
+ ModelConfiguration.class,
+ OllamaChatModel.class,
+ ModelRuntimeRegistrar.class,
+ SpringUtil.class,
+})
+public class ModelFactoryTest {
+
+ private static final LFLog LOG = LFLoggerManager.getLogger(ModelFactoryTest.class);
+
+ @Resource
+ private OllamaChatConfig ollamaChatConfig;
+
+ @Test
+ public void test() {
+
+ List lst = new ArrayList<>();
+ lst.add(new Message() {
+ @Override
+ public MessageType getMessageType() {
+ return MessageType.USER;
+ }
+
+ @Override
+ public String getContent() {
+ return "Why sky is blue?";
+ }
+
+ @Override
+ public Map getMetaData() {
+ return new HashMap<>();
+ }
+ });
+
+ ChatRequest request = ChatRequest.builder()
+ .messages(lst)
+ .options(ChatOptions.DEFAULT)
+ .onStart(context -> LOG.info("chat start"))
+ .onClose(context -> LOG.info("chat close"))
+ .onCompletion(((response, context) -> {
+ LOG.info("chat completion: \n{}", response.getMessage().getContent());
+ AssistantMessage modifiedMessage = new AssistantMessage(
+ response.getMessage().getContent() + " \n(modified by onCompletion)"
+ );
+ response.setMessage(modifiedMessage);
+ return response;
+ }))
+ .build();
+
+ // 自动注册 Model
+ Set supportedProviders = ModelRuntimeFactory.getSupportedProviders();
+ LOG.info("{}", supportedProviders);
+
+ // 自动注册 转换器
+ ProtocolTransformer transformer = ProtocolTransformerFactory.getTransformer(OllamaConstant.PROVIDER_NAME);
+ LOG.info("{}", transformer);
+
+ // 请求体构建
+ LOG.info("{}",
+ request.toRequestBody()
+ .merge(ollamaChatConfig.toRequestBody())
+ );
+
+ System.out.println("=========================================");
+
+ // 请求
+ ChatModel chatModel = ModelRuntimeFactory.createChatRuntime(OllamaConstant.PROVIDER_NAME, ollamaChatConfig);
+ ChatResponse response = chatModel.chat(request);
+ }
+
+ /*
+ 2025-07-18 22:28:40.752 INFO 36312 --- [ main] c.y.l.ai.model.ollama.ModelFactoryTest : [ollama_chat]
+ 2025-07-18 22:28:40.752 INFO 36312 --- [ main] c.y.l.ai.model.ollama.ModelFactoryTest : com.yomahub.liteflow.ai.model.ollama.interact.OllamaProtocolTransformer@a62c7cd
+ 2025-07-18 22:28:40.752 INFO 36312 --- [ main] c.y.l.ai.model.ollama.ModelFactoryTest : {
+ "messages":[
+ {
+ "content":"Why sky is blue?",
+ "messageType":"USER",
+ "metaData":{}
+ }
+ ],
+ "options.temperature":0.8,
+ "options.top_p":0.9,
+ "options.top_k":50.0,
+ "think":false,
+ "model":"qwen3:32b",
+ "stream":false
+ }
+ =========================================
+ 2025-07-18 22:28:40.817 INFO 36312 --- [onPool-worker-1] c.y.l.ai.model.ollama.ModelFactoryTest : chat start
+ 2025-07-18 22:29:17.241 INFO 36312 --- [onPool-worker-1] com.yomahub.liteflow.ai.util.HttpUtil : 正在关闭 OkHttp 客户端。
+ 2025-07-18 22:29:17.241 INFO 36312 --- [onPool-worker-1] com.yomahub.liteflow.ai.util.HttpUtil : OkHttp 客户端已成功关闭。
+ 2025-07-18 22:29:17.242 INFO 36312 --- [onPool-worker-1] c.y.l.ai.model.ollama.ModelFactoryTest : chat completion:
+ "{\"model\":\"qwen3:32b\",\"created_at\":\"2025-07-18T14:29:17.227484Z\",\"response\":\"The sky appears blue due to a phenomenon called **Rayleigh scattering**, which is related to how sunlight interacts with the Earth's atmosphere.\\n\\n### Here's how it works:\\n\\n1. **Sunlight is made of many colors**: Sunlight appears white, but it's actually composed of a spectrum of colors, each with a different wavelength. These colors range from violet and blue (shorter wavelengths) to yellow, orange, and red (longer wavelengths).\\n\\n2. **Earth's atmosphere scatters light**: When sunlight enters Earth's atmosphere, it collides with molecules and small particles in the air. These collisions cause the light to scatter in all directions.\\n\\n3. **Shorter wavelengths scatter more**: Blue and violet light have shorter wavelengths and are scattered much more efficiently than the longer wavelengths like red and yellow. This is due to the physics of how light interacts with the air molecules.\\n\\n4. **Why not violet?**: Although violet light is scattered even more than blue, our eyes are more sensitive to blue light, and the sun emits more blue light than violet. Also, some of the violet is absorbed by the upper atmosphere. So we perceive the sky as **blue**.\\n\\n5. **Sunset colors**: During sunrise or sunset, the sun is lower on the horizon, and the light has to pass through more of the atmosphere. This causes more scattering of the shorter blue and green wavelengths, allowing the longer red and orange wavelengths to dominate, which is why the sky appears red or orange at those times.\\n\\n### In short:\\nThe sky looks blue because the Earth's atmosphere scatters the shorter blue wavelengths of sunlight more than the other colors, and our eyes are most sensitive to blue.\\n\\nLet me know if you'd like a visual or analogy to help explain it further!\",\"done\":true,\"done_reason\":\"stop\",\"context\":[151644,872,198,10234,12884,374,6303,30,608,2152,5854,766,151645,198,151644,77091,198,151667,271,151668,271,785,12884,7952,6303,4152,311,264,24844,2598,3070,29187,62969,71816,97219,892,374,5435,311,1246,39020,83161,448,279,9237,594,16566,382,14374,5692,594,1246,432,4278,1447,16,13,3070,30092,4145,374,1865,315,1657,7987,95518,8059,4145,7952,4158,11,714,432,594,3520,23415,315,264,19745,315,7987,11,1817,448,264,2155,45306,13,4220,7987,2088,504,79736,323,6303,320,8676,261,92859,8,311,13753,11,18575,11,323,2518,320,4825,261,92859,3593,17,13,3070,43824,594,16566,1136,10175,3100,95518,3197,39020,28833,9237,594,16566,11,432,4530,3341,448,34615,323,2613,18730,304,279,3720,13,4220,47353,5240,279,3100,311,44477,304,678,17961,382,18,13,3070,12472,261,92859,44477,803,95518,8697,323,79736,3100,614,23327,92859,323,525,36967,1753,803,29720,1091,279,5021,92859,1075,2518,323,13753,13,1096,374,4152,311,279,21321,315,1246,3100,83161,448,279,3720,34615,382,19,13,3070,10234,537,79736,30,95518,10328,79736,3100,374,36967,1496,803,1091,6303,11,1039,6414,525,803,16216,311,6303,3100,11,323,279,7015,72780,803,6303,3100,1091,79736,13,7281,11,1045,315,279,79736,374,41001,553,279,8416,16566,13,2055,582,44393,279,12884,438,3070,12203,334,382,20,13,3070,30092,746,7987,95518,11954,63819,476,42984,11,279,7015,374,4722,389,279,34074,11,323,279,3100,702,311,1494,1526,803,315,279,16566,13,1096,11137,803,71816,315,279,23327,6303,323,6176,92859,11,10693,279,5021,2518,323,18575,92859,311,40736,11,892,374,3170,279,12884,7952,2518,476,18575,518,1846,3039,382,14374,758,2805,510,785,12884,5868,6303,1576,279,9237,594,16566,1136,10175,279,23327,6303,92859,315,39020,803,1091,279,1008,7987,11,323,1039,6414,525,1429,16216,311,6303,382,10061,752,1414,421,498,4172,1075,264,9124,476,55103,311,1492,10339,432,4623,0],\"total_duration\":36303248917,\"load_duration\":40503917,\"prompt_eval_count\":21,\"prompt_eval_duration\":1824295292,\"eval_count\":358,\"eval_duration\":34437921250}"
+ */
+}