From 21b60a0216843eef51ba434e0eb732ef665cb9aa Mon Sep 17 00:00:00 2001 From: liyongde <1419499670@qq.com> Date: Sat, 7 Jun 2025 22:32:41 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20ollama=E6=B5=81=E5=BC=8F=E5=BA=94?= =?UTF-8?q?=E7=AD=94=E6=8E=A5=E5=8F=A3=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/uiDesigner.xml | 124 ++++++++++++++++++ .../java/com/storm/dev/api/IAiService.java | 26 ++++ .../{ => com/storm/dev/api}/package-info.java | 3 +- ai-rag-app/pom.xml | 28 ++-- .../main/java/com/storm/dev/Application.java | 18 +++ .../com/storm/dev/config/OllamaConfig.java | 27 ++++ .../storm/dev/config/RedisClientConfig.java | 42 ++++++ .../config/RedisClientConfigProperties.java | 37 ++++++ .../main/java/com/storm/dev/package-info.java | 6 + .../src/main/resources/application-dev.yml | 27 ++++ .../src/main/resources/application-prod.yml | 7 + .../src/main/resources/application-test.yml | 7 + ai-rag-app/src/main/resources/application.yml | 5 + .../src/main/resources/logback-spring.xml | 113 ++++++++++++++++ ai-rag-trigger/pom.xml | 24 ++-- .../dev/trigger/http/OllamaController.java | 41 ++++++ .../com/storm/dev/trigger/package-info.java | 6 + 17 files changed, 515 insertions(+), 26 deletions(-) create mode 100644 .idea/uiDesigner.xml create mode 100644 ai-rag-api/src/main/java/com/storm/dev/api/IAiService.java rename ai-rag-api/src/main/java/{ => com/storm/dev/api}/package-info.java (60%) create mode 100644 ai-rag-app/src/main/java/com/storm/dev/Application.java create mode 100644 ai-rag-app/src/main/java/com/storm/dev/config/OllamaConfig.java create mode 100644 ai-rag-app/src/main/java/com/storm/dev/config/RedisClientConfig.java create mode 100644 ai-rag-app/src/main/java/com/storm/dev/config/RedisClientConfigProperties.java create mode 100644 ai-rag-app/src/main/java/com/storm/dev/package-info.java create mode 100644 ai-rag-app/src/main/resources/application-dev.yml create mode 100644 ai-rag-app/src/main/resources/application-prod.yml create mode 100644 ai-rag-app/src/main/resources/application-test.yml create mode 100644 ai-rag-app/src/main/resources/application.yml create mode 100644 ai-rag-app/src/main/resources/logback-spring.xml create mode 100644 ai-rag-trigger/src/main/java/com/storm/dev/trigger/http/OllamaController.java create mode 100644 ai-rag-trigger/src/main/java/com/storm/dev/trigger/package-info.java diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ai-rag-api/src/main/java/com/storm/dev/api/IAiService.java b/ai-rag-api/src/main/java/com/storm/dev/api/IAiService.java new file mode 100644 index 0000000..021606b --- /dev/null +++ b/ai-rag-api/src/main/java/com/storm/dev/api/IAiService.java @@ -0,0 +1,26 @@ +package com.storm.dev.api; + +import org.springframework.ai.chat.ChatResponse; +import reactor.core.publisher.Flux; + +/** + * @author: lyd + * @date: 2025/6/7 22:12 + */ +public interface IAiService { + /** + * 非流式生成 + * @param model 模型 + * @param message 信息 + * @return + */ + ChatResponse generate(String model, String message); + + /** + * 流式生成 + * @param model 模型 + * @param message 信息 + * @return + */ + Flux generateStream(String model, String message); +} diff --git a/ai-rag-api/src/main/java/package-info.java b/ai-rag-api/src/main/java/com/storm/dev/api/package-info.java similarity index 60% rename from ai-rag-api/src/main/java/package-info.java rename to ai-rag-api/src/main/java/com/storm/dev/api/package-info.java index dd64099..942087a 100644 --- a/ai-rag-api/src/main/java/package-info.java +++ b/ai-rag-api/src/main/java/com/storm/dev/api/package-info.java @@ -1,4 +1,5 @@ /** * @author: lyd * @date: 2025/6/7 19:12 - */ \ No newline at end of file + */ +package com.storm.dev.api; \ No newline at end of file diff --git a/ai-rag-app/pom.xml b/ai-rag-app/pom.xml index 5f10ecf..62aa8b5 100644 --- a/ai-rag-app/pom.xml +++ b/ai-rag-app/pom.xml @@ -24,21 +24,23 @@ test - - org.springframework.ai - spring-ai-openai-spring-boot-starter - + + + + - - org.springframework.ai - spring-ai-tika-document-reader - + + + + - - org.springframework.ai - spring-ai-pgvector-store-spring-boot-starter - + + + + + + org.springframework.ai spring-ai-ollama @@ -122,7 +124,7 @@ org.springframework.boot spring-boot-maven-plugin - + com.storm.dev.Application JAR diff --git a/ai-rag-app/src/main/java/com/storm/dev/Application.java b/ai-rag-app/src/main/java/com/storm/dev/Application.java new file mode 100644 index 0000000..55c3069 --- /dev/null +++ b/ai-rag-app/src/main/java/com/storm/dev/Application.java @@ -0,0 +1,18 @@ +package com.storm.dev; + +import org.springframework.beans.factory.annotation.Configurable; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * 会扫描com.storm.dev的包 + */ +@SpringBootApplication +@Configurable +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class); + } + +} diff --git a/ai-rag-app/src/main/java/com/storm/dev/config/OllamaConfig.java b/ai-rag-app/src/main/java/com/storm/dev/config/OllamaConfig.java new file mode 100644 index 0000000..53299a2 --- /dev/null +++ b/ai-rag-app/src/main/java/com/storm/dev/config/OllamaConfig.java @@ -0,0 +1,27 @@ +package com.storm.dev.config; + +import org.springframework.ai.ollama.OllamaChatClient; +import org.springframework.ai.ollama.api.OllamaApi; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 注入OllamaApi、OllamaChatClient对象 + * @author: lyd + * @date: 2025/6/7 22:28 + */ +@Configuration +public class OllamaConfig { + + @Bean + public OllamaApi ollamaApi(@Value("${spring.ai.ollama.base-url}") String baseUrl) { + return new OllamaApi(baseUrl); + } + + @Bean + public OllamaChatClient ollamaChatClient(OllamaApi ollamaApi) { + return new OllamaChatClient(ollamaApi); + } + +} \ No newline at end of file diff --git a/ai-rag-app/src/main/java/com/storm/dev/config/RedisClientConfig.java b/ai-rag-app/src/main/java/com/storm/dev/config/RedisClientConfig.java new file mode 100644 index 0000000..0d57fef --- /dev/null +++ b/ai-rag-app/src/main/java/com/storm/dev/config/RedisClientConfig.java @@ -0,0 +1,42 @@ +package com.storm.dev.config; + +import org.redisson.Redisson; +import org.redisson.api.RedissonClient; +import org.redisson.codec.JsonJacksonCodec; +import org.redisson.config.Config; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Redis 客户端,使用 Redisson Redisson + * + */ +@Configuration +@EnableConfigurationProperties(RedisClientConfigProperties.class) +public class RedisClientConfig { + + @Bean("redissonClient") + public RedissonClient redissonClient(ConfigurableApplicationContext applicationContext, RedisClientConfigProperties properties) { + Config config = new Config(); + // 根据需要可以设定编解码器;https://github.com/redisson/redisson/wiki/4.-%E6%95%B0%E6%8D%AE%E5%BA%8F%E5%88%97%E5%8C%96 + config.setCodec(JsonJacksonCodec.INSTANCE); + + config.useSingleServer() + .setAddress("redis://" + properties.getHost() + ":" + properties.getPort()) +// .setPassword(properties.getPassword()) + .setConnectionPoolSize(properties.getPoolSize()) + .setConnectionMinimumIdleSize(properties.getMinIdleSize()) + .setIdleConnectionTimeout(properties.getIdleTimeout()) + .setConnectTimeout(properties.getConnectTimeout()) + .setRetryAttempts(properties.getRetryAttempts()) + .setRetryInterval(properties.getRetryInterval()) + .setPingConnectionInterval(properties.getPingInterval()) + .setKeepAlive(properties.isKeepAlive()) + ; + + return Redisson.create(config); + } + +} diff --git a/ai-rag-app/src/main/java/com/storm/dev/config/RedisClientConfigProperties.java b/ai-rag-app/src/main/java/com/storm/dev/config/RedisClientConfigProperties.java new file mode 100644 index 0000000..0dde870 --- /dev/null +++ b/ai-rag-app/src/main/java/com/storm/dev/config/RedisClientConfigProperties.java @@ -0,0 +1,37 @@ +package com.storm.dev.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * @author Fuzhengwei bugstack.cn @小傅哥 + * Redis 连接配置 redisson-spring-boot-starter + */ +@Data +@ConfigurationProperties(prefix = "redis.sdk.config", ignoreInvalidFields = true) +public class RedisClientConfigProperties { + + /** host:ip */ + private String host; + /** 端口 */ + private int port; + /** 账密 */ + private String password; + /** 设置连接池的大小,默认为64 */ + private int poolSize = 64; + /** 设置连接池的最小空闲连接数,默认为10 */ + private int minIdleSize = 10; + /** 设置连接的最大空闲时间(单位:毫秒),超过该时间的空闲连接将被关闭,默认为10000 */ + private int idleTimeout = 10000; + /** 设置连接超时时间(单位:毫秒),默认为10000 */ + private int connectTimeout = 10000; + /** 设置连接重试次数,默认为3 */ + private int retryAttempts = 3; + /** 设置连接重试的间隔时间(单位:毫秒),默认为1000 */ + private int retryInterval = 1000; + /** 设置定期检查连接是否可用的时间间隔(单位:毫秒),默认为0,表示不进行定期检查 */ + private int pingInterval = 0; + /** 设置是否保持长连接,默认为true */ + private boolean keepAlive = true; + +} diff --git a/ai-rag-app/src/main/java/com/storm/dev/package-info.java b/ai-rag-app/src/main/java/com/storm/dev/package-info.java new file mode 100644 index 0000000..ed0404c --- /dev/null +++ b/ai-rag-app/src/main/java/com/storm/dev/package-info.java @@ -0,0 +1,6 @@ +/** + * 启动模块 + * @author: lyd + * @date: 2025/6/7 22:04 + */ +package com.storm.dev; \ No newline at end of file diff --git a/ai-rag-app/src/main/resources/application-dev.yml b/ai-rag-app/src/main/resources/application-dev.yml new file mode 100644 index 0000000..cc8f7f5 --- /dev/null +++ b/ai-rag-app/src/main/resources/application-dev.yml @@ -0,0 +1,27 @@ +server: + port: 8090 + +spring: + ai: + ollama: + base-url: http://117.72.202.142:11434 + +# Redis +redis: + sdk: + config: + host: 117.72.202.142 + port: 16379 + pool-size: 10 + min-idle-size: 5 + idle-timeout: 30000 + connect-timeout: 5000 + retry-attempts: 3 + retry-interval: 1000 + ping-interval: 60000 + keep-alive: true + +logging: + level: + root: info + config: classpath:logback-spring.xml diff --git a/ai-rag-app/src/main/resources/application-prod.yml b/ai-rag-app/src/main/resources/application-prod.yml new file mode 100644 index 0000000..7d19cad --- /dev/null +++ b/ai-rag-app/src/main/resources/application-prod.yml @@ -0,0 +1,7 @@ +server: + port: 8090 + +logging: + level: + root: info + config: classpath:logback-spring.xml diff --git a/ai-rag-app/src/main/resources/application-test.yml b/ai-rag-app/src/main/resources/application-test.yml new file mode 100644 index 0000000..7d19cad --- /dev/null +++ b/ai-rag-app/src/main/resources/application-test.yml @@ -0,0 +1,7 @@ +server: + port: 8090 + +logging: + level: + root: info + config: classpath:logback-spring.xml diff --git a/ai-rag-app/src/main/resources/application.yml b/ai-rag-app/src/main/resources/application.yml new file mode 100644 index 0000000..f5dfac6 --- /dev/null +++ b/ai-rag-app/src/main/resources/application.yml @@ -0,0 +1,5 @@ +spring: + application: + name: ai-rag-knowledge + profiles: + active: dev diff --git a/ai-rag-app/src/main/resources/logback-spring.xml b/ai-rag-app/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..f71e2ea --- /dev/null +++ b/ai-rag-app/src/main/resources/logback-spring.xml @@ -0,0 +1,113 @@ + + + + + logback + + + + + + + + + + + + info + + + %d{yy-MM-dd.HH:mm:ss.SSS} [%-16t] %-5p %-22c{0}%X{ServiceId} -%X{trace-id} %m%n + UTF-8 + + + + + + + + ./data/log/log_info.log + + + %d{yy-MM-dd.HH:mm:ss.SSS} [%-16t] %-5p %-22c{0}%X{ServiceId} -%X{trace-id} %m%n + UTF-8 + + + + + ./data/log/log-info-%d{yyyy-MM-dd}.%i.log + + 100MB + + + 15 + 10GB + + + + + + + ./data/log/log_error.log + + + %d{yy-MM-dd.HH:mm:ss.SSS} [%-16t] %-5p %-22c{0}%X{ServiceId} -%X{trace-id} %m%n + UTF-8 + + + + ./data/log/log-error-%d{yyyy-MM-dd}.%i.log + + 100MB + + + 7 + 5GB + + + + WARN + + + + + + + 0 + + 8192 + + true + + false + + + + + + 0 + + 1024 + + true + + false + + + + + + + + + + + + + + + + + diff --git a/ai-rag-trigger/pom.xml b/ai-rag-trigger/pom.xml index 3abc8f7..2dc9d7f 100644 --- a/ai-rag-trigger/pom.xml +++ b/ai-rag-trigger/pom.xml @@ -23,18 +23,18 @@ spring-boot-starter-web - - org.springframework.ai - spring-ai-openai-spring-boot-starter - - - org.springframework.ai - spring-ai-tika-document-reader - - - org.springframework.ai - spring-ai-pgvector-store - + + + + + + + + + + + + org.springframework.ai spring-ai-ollama diff --git a/ai-rag-trigger/src/main/java/com/storm/dev/trigger/http/OllamaController.java b/ai-rag-trigger/src/main/java/com/storm/dev/trigger/http/OllamaController.java new file mode 100644 index 0000000..b6a34c2 --- /dev/null +++ b/ai-rag-trigger/src/main/java/com/storm/dev/trigger/http/OllamaController.java @@ -0,0 +1,41 @@ +package com.storm.dev.trigger.http; + +import com.storm.dev.api.IAiService; +import jakarta.annotation.Resource; +import org.springframework.ai.chat.ChatResponse; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.ollama.OllamaChatClient; +import org.springframework.ai.ollama.api.OllamaOptions; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Flux; + +/** + * @author: lyd + * @date: 2025/6/7 22:18 + */ +@RestController() +@CrossOrigin("*") +@RequestMapping("/api/v1/ollama/") +public class OllamaController implements IAiService { + + @Resource + private OllamaChatClient chatClient; + + /** + * http://localhost:8090/api/v1/ollama/generate?model=deepseek-r1:1.5b&message=1+1 + */ + @GetMapping("generate") + @Override + public ChatResponse generate(@RequestParam String model, @RequestParam String message) { + return chatClient.call(new Prompt(message, OllamaOptions.create().withModel(model))); + } + + /** + * http://localhost:8090/api/v1/ollama/generate_stream?model=deepseek-r1:1.5b&message=hi + */ + @GetMapping("generate_stream") + @Override + public Flux generateStream(@RequestParam String model, @RequestParam String message) { + return chatClient.stream(new Prompt(message, OllamaOptions.create().withModel(model))); + } +} diff --git a/ai-rag-trigger/src/main/java/com/storm/dev/trigger/package-info.java b/ai-rag-trigger/src/main/java/com/storm/dev/trigger/package-info.java new file mode 100644 index 0000000..d89b4a9 --- /dev/null +++ b/ai-rag-trigger/src/main/java/com/storm/dev/trigger/package-info.java @@ -0,0 +1,6 @@ +/** + * 触发器 + * @author: lyd + * @date: 2025/6/7 22:17 + */ +package com.storm.dev.trigger; \ No newline at end of file