diff --git a/src/main/java/cn/van/business/service/MarketingImageService.java b/src/main/java/cn/van/business/service/MarketingImageService.java index 8c19375..aea6c75 100644 --- a/src/main/java/cn/van/business/service/MarketingImageService.java +++ b/src/main/java/cn/van/business/service/MarketingImageService.java @@ -2,7 +2,7 @@ package cn.van.business.service; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; -import cn.van.business.util.ds.DeepSeekClientUtil; +import cn.van.business.util.ds.OllamaClientUtil; import lombok.extern.slf4j.Slf4j; import net.coobird.thumbnailator.Thumbnails; import org.springframework.beans.factory.annotation.Autowired; @@ -29,7 +29,7 @@ import java.util.Map; public class MarketingImageService { @Autowired - private DeepSeekClientUtil deepSeekClientUtil; + private OllamaClientUtil ollamaClientUtil; // 输出图片尺寸 private static final int OUTPUT_WIDTH = 1080; @@ -191,7 +191,7 @@ public class MarketingImageService { fullProductName ); - String extracted = deepSeekClientUtil.getDeepSeekResponse(prompt); + String extracted = ollamaClientUtil.getResponse(prompt); if (StrUtil.isNotBlank(extracted)) { // 清理可能的换行和多余空格 extracted = extracted.trim().replaceAll("\\s+", ""); diff --git a/src/main/java/cn/van/business/service/SocialMediaService.java b/src/main/java/cn/van/business/service/SocialMediaService.java index 6eafcb4..b6f59ef 100644 --- a/src/main/java/cn/van/business/service/SocialMediaService.java +++ b/src/main/java/cn/van/business/service/SocialMediaService.java @@ -1,7 +1,7 @@ package cn.van.business.service; import cn.hutool.core.util.StrUtil; -import cn.van.business.util.ds.DeepSeekClientUtil; +import cn.van.business.util.ds.OllamaClientUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; @@ -23,7 +23,7 @@ import java.util.Map; public class SocialMediaService { @Autowired - private DeepSeekClientUtil deepSeekClientUtil; + private OllamaClientUtil ollamaClientUtil; @Autowired private MarketingImageService marketingImageService; @@ -102,7 +102,7 @@ public class SocialMediaService { String promptTemplate = getPromptTemplate("keywords", DEFAULT_KEYWORDS_PROMPT); String prompt = String.format(promptTemplate, productName); - String response = deepSeekClientUtil.getDeepSeekResponse(prompt); + String response = ollamaClientUtil.getResponse(prompt); if (StrUtil.isNotBlank(response)) { // 解析关键词 @@ -191,7 +191,7 @@ public class SocialMediaService { String prompt = String.format(promptTemplate, productName, priceInfo.toString(), keywordsInfo); - String content = deepSeekClientUtil.getDeepSeekResponse(prompt.toString()); + String content = ollamaClientUtil.getResponse(prompt.toString()); if (StrUtil.isNotBlank(content)) { result.put("success", true); diff --git a/src/main/java/cn/van/business/util/ds/OllamaClientUtil.java b/src/main/java/cn/van/business/util/ds/OllamaClientUtil.java new file mode 100644 index 0000000..b0963c8 --- /dev/null +++ b/src/main/java/cn/van/business/util/ds/OllamaClientUtil.java @@ -0,0 +1,84 @@ +package cn.van.business.util.ds; + +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import cn.hutool.http.Method; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * Ollama 大模型接口调用工具。 + * 地址默认:192.168.8.34:11434,模型默认:qwen3.5:9b + */ +@Component +public class OllamaClientUtil { + private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(OllamaClientUtil.class); + private static final ObjectMapper objectMapper = new ObjectMapper(); + + @Value("${jarvis.ollama.base-url:http://192.168.8.34:11434}") + private String ollamaBaseUrl; + + @Value("${jarvis.ollama.model:qwen3.5:9b}") + private String ollamaModel; + + /** + * 调用 Ollama /api/chat 并返回助手回复的文本内容 + * + * @param inputText 用户输入的文本 + * @return 模型回复的文本内容 + */ + public String getResponse(String inputText) throws IOException { + if (inputText == null || inputText.trim().isEmpty()) { + throw new IllegalArgumentException("输入文本不能为空"); + } + if (inputText.length() > 10000) { + throw new IllegalArgumentException("输入文本过长"); + } + + String url = ollamaBaseUrl.replaceAll("/$", "") + "/api/chat"; + Map requestBody = new HashMap<>(); + requestBody.put("model", ollamaModel); + requestBody.put("messages", new Object[]{ + Map.of("role", "user", "content", inputText) + }); + requestBody.put("stream", false); + + String jsonBody = objectMapper.writeValueAsString(requestBody); + + HttpRequest request = HttpRequest.of(url) + .method(Method.POST) + .header("Content-Type", "application/json") + .header("Accept", "application/json") + .body(jsonBody) + .timeout(60000); + + logger.info("请求 Ollama API: URL={}, model={}", url, ollamaModel); + + HttpResponse response = request.execute(); + + if (response.getStatus() != 200) { + logger.error("Ollama API 调用失败!状态码={}, 响应={}", response.getStatus(), response.body()); + throw new IOException("API 调用失败,HTTP 状态码: " + response.getStatus()); + } + + JsonNode root = objectMapper.readTree(response.body()); + JsonNode message = root.path("message"); + if (!message.isMissingNode()) { + JsonNode content = message.path("content"); + if (!content.isMissingNode()) { + return content.asText(); + } + } + JsonNode responseText = root.path("response"); + if (!responseText.isMissingNode()) { + return responseText.asText(); + } + throw new IOException("Ollama 返回数据格式异常,未找到回复内容"); + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 152450d..7876d1c 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -63,6 +63,10 @@ jarvis: host: 192.168.8.88 rocketmq: name-server: 192.168.8.88:9876 + # Ollama 大模型接口(原 DS 调用已切换为此) + ollama: + base-url: http://192.168.8.34:11434 + model: qwen3.5:9b rocketmq: name-server: ${jarvis.server.rocketmq.name-server:192.168.8.88:9876} # RocketMQ Name Server 地址 producer: