From eeb0e24013ef137bd70d73c45dbc1dd868bca64e Mon Sep 17 00:00:00 2001 From: yl-dengxs <1195279222@qq.com> Date: Fri, 9 Jan 2026 17:16:33 +0800 Subject: [PATCH 1/9] =?UTF-8?q?ollama:=E6=B7=BB=E5=8A=A0=E4=BA=86=E6=97=A5?= =?UTF-8?q?=E5=AD=90=E5=92=8C=E8=B0=83=E6=95=B4=E6=8F=90=E7=A4=BA=E8=AF=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spring-ai-chat/spring-ai-chat-ollama/pom.xml | 4 + .../ai/chat/ollama/common/FilterConfig.java | 20 ++++ .../chat/ollama/common/InterceptorConfig.java | 24 +++++ .../ai/chat/ollama/common/LogUtil.java | 49 ++++++++++ .../ollama/common/LoggingInterceptor.java | 86 +++++++++++++++++ .../common/RequestResponseLoggingFilter.java | 64 +++++++++++++ .../ai/chat/ollama/common/RequestWrapper.java | 62 ++++++++++++ .../chat/ollama/common/ResponseWrapper.java | 95 +++++++++++++++++++ .../ollama/controller/ChatController.java | 47 ++++++++- .../src/main/resources/application.properties | 2 +- 10 files changed, 451 insertions(+), 2 deletions(-) create mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/FilterConfig.java create mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/InterceptorConfig.java create mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/LogUtil.java create mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/LoggingInterceptor.java create mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/RequestResponseLoggingFilter.java create mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/RequestWrapper.java create mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/ResponseWrapper.java diff --git a/spring-ai-chat/spring-ai-chat-ollama/pom.xml b/spring-ai-chat/spring-ai-chat-ollama/pom.xml index a2bb6dc..0a7c4ea 100644 --- a/spring-ai-chat/spring-ai-chat-ollama/pom.xml +++ b/spring-ai-chat/spring-ai-chat-ollama/pom.xml @@ -15,5 +15,9 @@ org.springframework.ai spring-ai-starter-model-ollama + + org.springframework.boot + spring-boot-starter-web + \ No newline at end of file diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/FilterConfig.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/FilterConfig.java new file mode 100644 index 0000000..796943b --- /dev/null +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/FilterConfig.java @@ -0,0 +1,20 @@ +package com.glmapper.ai.chat.ollama.common; + +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class FilterConfig { + + @Bean + public FilterRegistrationBean loggingFilter() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + + registrationBean.setFilter(new RequestResponseLoggingFilter()); + registrationBean.addUrlPatterns("/api/*"); // 只拦截API请求 + registrationBean.setOrder(1); // 设置优先级 + + return registrationBean; + } +} \ No newline at end of file diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/InterceptorConfig.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/InterceptorConfig.java new file mode 100644 index 0000000..64e0f9b --- /dev/null +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/InterceptorConfig.java @@ -0,0 +1,24 @@ +package com.glmapper.ai.chat.ollama.common; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class InterceptorConfig implements WebMvcConfigurer { + + @Autowired + private LoggingInterceptor loggingInterceptor; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + // 注册日志拦截器,对所有请求进行拦截 + registry.addInterceptor(loggingInterceptor) + .addPathPatterns("/**") // 拦截所有请求 + .excludePathPatterns( // 排除不需要拦截的路径 + "/error", + "/actuator/**" + ); + } +} \ No newline at end of file diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/LogUtil.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/LogUtil.java new file mode 100644 index 0000000..35a0ce4 --- /dev/null +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/LogUtil.java @@ -0,0 +1,49 @@ +package com.glmapper.ai.chat.ollama.common; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LogUtil { + + private static final Logger log = LoggerFactory.getLogger(LogUtil.class); + private static final ObjectMapper objectMapper = new ObjectMapper(); + + /** + * 记录请求参数 + * @param methodName 方法名 + * @param params 参数 + */ + public static void logRequest(String methodName, Object[] params) { + try { + String paramsJson = params != null ? objectMapper.writeValueAsString(params) : "null"; + log.info(""" + + === Request === + Method: %s + Parameters: %s + """, methodName, paramsJson); + } catch (Exception e) { + log.error("Error logging request", e); + } + } + + /** + * 记录响应结果 + * @param methodName 方法名 + * @param result 响应结果 + */ + public static void logResponse(String methodName, Object result) { + try { + String resultJson = result != null ? objectMapper.writeValueAsString(result) : "null"; + log.info(""" + + === Response === + Method: %s + Result: %s + """, methodName, resultJson); + } catch (Exception e) { + log.error("Error logging response", e); + } + } +} \ No newline at end of file diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/LoggingInterceptor.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/LoggingInterceptor.java new file mode 100644 index 0000000..fc3f2ef --- /dev/null +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/LoggingInterceptor.java @@ -0,0 +1,86 @@ +package com.glmapper.ai.chat.ollama.common; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.lang.Nullable; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; + +@Component +public class LoggingInterceptor implements HandlerInterceptor { + + private static final Logger log = LoggerFactory.getLogger(LoggingInterceptor.class); + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + String decodedQueryString = decodeQueryString(request.getQueryString()); + log.info(""" + === Request Received === + Request URI: {} + Request Method: {} + Query String: {} + Decoded Query String: {} + Remote Address: {} + """, + request.getRequestURI(), + request.getMethod(), + request.getQueryString(), + decodedQueryString, + request.getRemoteAddr()); + + // 记录请求头信息 + request.getHeaderNames().asIterator().forEachRemaining(headerName -> + log.info("Header {}: {}", headerName, request.getHeader(headerName)) + ); + + return true; + } + + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, + @Nullable ModelAndView modelAndView) throws Exception { + log.info(""" + === Request Processed === + Response Status: {} + """, response.getStatus()); + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, + @Nullable Exception ex) throws Exception { + if (ex != null) { + log.error(""" + === Request Completed with Exception === + Request URI: {} + Response Status: {} + Exception: + """, request.getRequestURI(), response.getStatus(), ex); + } else { + log.info(""" + === Request Completed Successfully === + Request URI: {} + Response Status: {} + """, request.getRequestURI(), response.getStatus()); + } + } + + private String decodeQueryString(String queryString) { + if (queryString == null) { + return null; + } + + try { + return URLDecoder.decode(queryString, "UTF-8"); + } catch (UnsupportedEncodingException e) { + log.warn("Failed to decode query string: {}", queryString, e); + return queryString; // 如果解码失败,返回原始字符串 + } + } +} \ No newline at end of file diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/RequestResponseLoggingFilter.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/RequestResponseLoggingFilter.java new file mode 100644 index 0000000..fb39bc1 --- /dev/null +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/RequestResponseLoggingFilter.java @@ -0,0 +1,64 @@ +package com.glmapper.ai.chat.ollama.common; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpFilter; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.Arrays; + +public class RequestResponseLoggingFilter extends HttpFilter { + + private static final Logger log = LoggerFactory.getLogger(RequestResponseLoggingFilter.class); + + @Override + protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) + throws IOException, ServletException { + + log.info(""" + === Request Received === + Request URI: {} + Request Method: {} + Query String: {} + Remote Address: {} + """, + request.getRequestURI(), + request.getMethod(), + request.getQueryString(), + request.getRemoteAddr()); + + // 记录请求头信息 + request.getHeaderNames().asIterator().forEachRemaining(headerName -> + log.info("Header {}: {}", headerName, request.getHeader(headerName)) + ); + + // 包装请求和响应对象以便读取内容 + RequestWrapper requestWrapper = new RequestWrapper(request); + ResponseWrapper responseWrapper = new ResponseWrapper(response); + + try { + chain.doFilter(requestWrapper, responseWrapper); + + // 将包装的响应内容复制回原始响应 + byte[] responseToSend = responseWrapper.getDataStream(); + response.getOutputStream().write(responseToSend); + + } finally { + log.info(""" + === Request Completed === + Request URI: {} + Response Status: {} + Request Body: {} + Response Body: {} + """, + request.getRequestURI(), + response.getStatus(), + requestWrapper.getBody(), + responseWrapper.getBody()); + } + } +} \ No newline at end of file diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/RequestWrapper.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/RequestWrapper.java new file mode 100644 index 0000000..46c34e9 --- /dev/null +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/RequestWrapper.java @@ -0,0 +1,62 @@ +package com.glmapper.ai.chat.ollama.common; + +import jakarta.servlet.ReadListener; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequestWrapper; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; + +public class RequestWrapper extends HttpServletRequestWrapper { + + private final String body; + + public RequestWrapper(HttpServletRequest request) throws IOException { + super(request); + StringBuilder stringBuilder = new StringBuilder(); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()))) { + String line; + while ((line = reader.readLine()) != null) { + stringBuilder.append(line); + } + } + this.body = stringBuilder.toString(); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes()); + return new ServletInputStream() { + @Override + public boolean isFinished() { + return byteArrayInputStream.available() == 0; + } + + @Override + public boolean isReady() { + return true; + } + + @Override + public void setReadListener(ReadListener readListener) { + // Not implemented + } + + @Override + public int read() throws IOException { + return byteArrayInputStream.read(); + } + }; + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(getInputStream())); + } + + public String getBody() { + return this.body; + } +} \ No newline at end of file diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/ResponseWrapper.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/ResponseWrapper.java new file mode 100644 index 0000000..e772ffc --- /dev/null +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/common/ResponseWrapper.java @@ -0,0 +1,95 @@ +package com.glmapper.ai.chat.ollama.common; + +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.WriteListener; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponseWrapper; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; + +public class ResponseWrapper extends HttpServletResponseWrapper { + + private final ByteArrayOutputStream capture; + private ServletOutputStream output; + private PrintWriter writer; + + public ResponseWrapper(HttpServletResponse response) { + super(response); + capture = new ByteArrayOutputStream(response.getBufferSize()); + } + + @Override + public ServletOutputStream getOutputStream() { + if (writer != null) { + throw new IllegalStateException("getWriter() has already been called on this response."); + } + + if (output == null) { + output = new ServletOutputStream() { + @Override + public boolean isReady() { + return false; + } + + @Override + public void setWriteListener(WriteListener writeListener) { + + } + + @Override + public void write(int b) throws IOException { + capture.write(b); + } + + @Override + public void flush() throws IOException { + capture.flush(); + } + + @Override + public void close() throws IOException { + capture.close(); + } + }; + } + + return output; + } + + @Override + public PrintWriter getWriter() throws IOException { + if (output != null) { + throw new IllegalStateException("getOutputStream() has already been called on this response."); + } + + if (writer == null) { + writer = new PrintWriter(capture); + } + + return writer; + } + + @Override + public void flushBuffer() throws IOException { + super.flushBuffer(); + if (writer != null) { + writer.flush(); + } else if (output != null) { + output.flush(); + } + } + + public byte[] getDataStream() { + return capture.toByteArray(); + } + + public String getBody() { + try { + return capture.toString(getCharacterEncoding()); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/ChatController.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/ChatController.java index b81eccc..a9711d4 100644 --- a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/ChatController.java +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/ChatController.java @@ -6,6 +6,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; +import reactor.core.publisher.Flux; /** * @Classname ChatController @@ -28,6 +30,49 @@ public class ChatController { */ @GetMapping("/chat") public String prompt(@RequestParam String userInput) { - return this.chatClient.prompt().user(userInput).call().content(); + return this.chatClient.prompt("你是一个智能助手,请用自然语言形式回答,不要使用JSON格式或其他结构化格式") + .user("问题:" + userInput) + .call() + .content(); + } + + /** + * 流式聊天接口 + * + * @param userInput 用户输入 + * @return SseEmitter 流式响应 + */ + @GetMapping("/chat-stream") + public SseEmitter promptStream(@RequestParam String userInput) { + SseEmitter emitter = new SseEmitter(60000L); // 设置超时时间为60秒 + + try { + // 使用流式调用 + Flux response = this.chatClient.prompt("你是一个智能助手,请用自然语言形式回答,不要使用JSON格式或其他结构化格式") + .user(userInput) + .stream() + .content(); + + // 订阅响应式流并发送到SSE + response.subscribe( + token -> { + try { + emitter.send(SseEmitter.event().data(token)); + } catch (Exception e) { + emitter.completeWithError(e); + } + }, + error -> { + emitter.completeWithError(error); + }, + () -> { + emitter.complete(); + } + ); + } catch (Exception e) { + emitter.completeWithError(e); + } + + return emitter; } } diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/resources/application.properties b/spring-ai-chat/spring-ai-chat-ollama/src/main/resources/application.properties index b4b2c6b..80650b1 100644 --- a/spring-ai-chat/spring-ai-chat-ollama/src/main/resources/application.properties +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/resources/application.properties @@ -6,5 +6,5 @@ spring.profiles.active=ollama # The address of the Ollama service, which defaults to http://localhost:11434. spring.ai.ollama.base-url=http://localhost:11434 # The model name which is the one you previously downloaded via the terminal using `ollama pull` or `ollama run` -spring.ai.ollama.chat.model=deepseek-r1:1.5b +spring.ai.ollama.chat.model=glm4:9b spring.ai.ollama.chat.options.temperature=0.7 From d5c7b3fbfc808b534d06ab240d6e7fc94c890089 Mon Sep 17 00:00:00 2001 From: yl-dengxs <1195279222@qq.com> Date: Wed, 14 Jan 2026 15:53:22 +0800 Subject: [PATCH 2/9] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=BE=AE=E4=BF=A1api?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 18 ++ spring-ai-chat/spring-ai-chat-ollama/pom.xml | 29 ++ .../ai/chat/ollama/base/ContactApi.java | 151 +++++++++ .../ai/chat/ollama/base/DownloadApi.java | 68 ++++ .../ai/chat/ollama/base/FavorApi.java | 42 +++ .../ai/chat/ollama/base/GroupApi.java | 295 ++++++++++++++++++ .../ai/chat/ollama/base/LabelApi.java | 54 ++++ .../ai/chat/ollama/base/LoginApi.java | 110 +++++++ .../ai/chat/ollama/base/MessageApi.java | 206 ++++++++++++ .../ai/chat/ollama/base/PersonalApi.java | 76 +++++ .../ai/chat/ollama/util/OkhttpUtil.java | 117 +++++++ spring-ai-mcp/nacos-mcp-client/pom.xml | 10 +- spring-ai-mcp/nacos-mcp-server/pom.xml | 10 +- 13 files changed, 1176 insertions(+), 10 deletions(-) create mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/ContactApi.java create mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/DownloadApi.java create mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/FavorApi.java create mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/GroupApi.java create mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/LabelApi.java create mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/LoginApi.java create mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/MessageApi.java create mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/PersonalApi.java create mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/util/OkhttpUtil.java diff --git a/pom.xml b/pom.xml index 27e1c73..d88c8b5 100644 --- a/pom.xml +++ b/pom.xml @@ -64,6 +64,24 @@ + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + 21 + 21 + + -parameters + + + + + + spring-milestones diff --git a/spring-ai-chat/spring-ai-chat-ollama/pom.xml b/spring-ai-chat/spring-ai-chat-ollama/pom.xml index 0a7c4ea..4b6b661 100644 --- a/spring-ai-chat/spring-ai-chat-ollama/pom.xml +++ b/spring-ai-chat/spring-ai-chat-ollama/pom.xml @@ -19,5 +19,34 @@ org.springframework.boot spring-boot-starter-web + + com.alibaba.fastjson2 + fastjson2 + 2.0.25 + + + + com.squareup.okhttp3 + okhttp + 3.10.0 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + 21 + 21 + + -parameters + + + + + + \ No newline at end of file diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/ContactApi.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/ContactApi.java new file mode 100644 index 0000000..ee4b172 --- /dev/null +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/ContactApi.java @@ -0,0 +1,151 @@ +package com.glmapper.ai.chat.ollama.base; + +import com.alibaba.fastjson2.JSONObject; +import com.glmapper.ai.chat.ollama.util.OkhttpUtil; + + +import java.util.List; + +/** + * 联系人模块 + */ +public class ContactApi { + + /** + * + * @param appId + * @return + */ + public static JSONObject a(String appId){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + return OkhttpUtil.postJSON("/login/checkOnline",param); + } + + /** + * 获取通讯录列表 + * @param appId + * @return + */ + public static JSONObject fetchContactsList(String appId){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + return OkhttpUtil.postJSON("/contacts/fetchContactsList",param); + } + + /** + * 获取群/好友简要信息 + * @param appId + * @return + */ + public static JSONObject getBriefInfo(String appId, List wxids){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("wxids",wxids); + return OkhttpUtil.postJSON("/contacts/getBriefInfo",param); + } + + /** + * 获取群/好友详细信息 + * @param appId + * @return + */ + public static JSONObject getDetailInfo(String appId, List wxids){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("wxids",wxids); + return OkhttpUtil.postJSON("/contacts/getDetailInfo",param); + } + + /** + * 搜索好友 + * @param appId + * @return + */ + public static JSONObject search(String appId,String contactsInfo){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("contactsInfo",contactsInfo); + return OkhttpUtil.postJSON("/contacts/search",param); + } + + /** + * 添加联系人/同意添加好友 + * @param appId + * @return + */ + public static JSONObject search(String appId,Integer scene,Integer option,String v3, String v4,String content){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("scene",scene); + param.put("option",option); + param.put("v3",v3); + param.put("v4",v4); + param.put("content",content); + return OkhttpUtil.postJSON("/contacts/addContacts",param); + } + + /** + * 删除好友 + * @param appId + * @return + */ + public static JSONObject deleteFriend(String appId,String wxid){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("wxid",wxid); + return OkhttpUtil.postJSON("/contacts/deleteFriend",param); + } + + /** + * 设置好友仅聊天 + * @param appId + * @return + */ + public static JSONObject setFriendPermissions(String appId,String wxid,Boolean onlyChat){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("wxid",wxid); + param.put("onlyChat",onlyChat); + return OkhttpUtil.postJSON("/contacts/setFriendPermissions",param); + } + + /** + * 设置好友备注 + * @param appId + * @return + */ + public static JSONObject setFriendRemark(String appId,String wxid,String remark){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("wxid",wxid); + param.put("onlyChat",remark); + return OkhttpUtil.postJSON("/contacts/setFriendRemark",param); + } + + /** + * 获取手机通讯录 + * @param appId + * @return + */ + public static JSONObject getPhoneAddressList(String appId,List phones){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("wxid",phones); + return OkhttpUtil.postJSON("/contacts/getPhoneAddressList",param); + } + + /** + * 上传手机通讯录 + * @param appId + * @return + */ + public static JSONObject uploadPhoneAddressList(String appId,List phones,Integer opType){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("wxid",phones); + param.put("opType",opType); + return OkhttpUtil.postJSON("/contacts/uploadPhoneAddressList",param); + } + +} diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/DownloadApi.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/DownloadApi.java new file mode 100644 index 0000000..1b7bd10 --- /dev/null +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/DownloadApi.java @@ -0,0 +1,68 @@ +package com.glmapper.ai.chat.ollama.base; + +import com.alibaba.fastjson2.JSONObject; +import com.glmapper.ai.chat.ollama.util.OkhttpUtil; + + +/** + * 下载模块 + */ +public class DownloadApi { + + /** + * 下载图片 + */ + public static JSONObject downloadImage(String appId, String xml, Integer type){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("xml",xml); + param.put("type",type); + return OkhttpUtil.postJSON("/message/downloadImage",param); + } + + /** + * 下载语音 + */ + public static JSONObject downloadVoice(String appId, String xml, Long msgId){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("xml",xml); + param.put("msgId",msgId); + return OkhttpUtil.postJSON("/message/downloadVoice",param); + } + + /** + * 下载视频 + */ + public static JSONObject downloadVideo(String appId, String xml){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("xml",xml); + return OkhttpUtil.postJSON("/message/downloadVideo",param); + } + + /** + * 下载emoji + */ + public static JSONObject downloadEmojiMd5(String appId, String emojiMd5){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("emojiMd5",emojiMd5); + return OkhttpUtil.postJSON("/message/downloadEmojiMd5",param); + } + /** + * cdn下载 + */ + public static JSONObject downloadImage(String appId, String aesKey, String fileId, String type, String totalSize, String suffix){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("aesKey",aesKey); + param.put("fileId",fileId); + param.put("totalSize",totalSize); + param.put("type",type); + param.put("suffix",suffix); + return OkhttpUtil.postJSON("/message/downloadCdn",param); + } + + +} diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/FavorApi.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/FavorApi.java new file mode 100644 index 0000000..8a4f9cd --- /dev/null +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/FavorApi.java @@ -0,0 +1,42 @@ +package com.glmapper.ai.chat.ollama.base; + +import com.alibaba.fastjson2.JSONObject; +import com.glmapper.ai.chat.ollama.util.OkhttpUtil; + + +/** + * 收藏夹模块 + */ +public class FavorApi { + + /** + * 同步收藏夹 + */ + public static JSONObject sync(String appId, String syncKey) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("syncKey", syncKey); + return OkhttpUtil.postJSON("/favor/sync", param); + } + + /** + * 获取收藏夹内容 + */ + public static JSONObject getContent(String appId, Integer favId) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("favId", favId); + return OkhttpUtil.postJSON("/favor/getContent", param); + } + + /** + * 删除收藏夹 + */ + public static JSONObject delete(String appId, Integer favId) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("favId", favId); + return OkhttpUtil.postJSON("/favor/delete", param); + } + +} diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/GroupApi.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/GroupApi.java new file mode 100644 index 0000000..fb38bf9 --- /dev/null +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/GroupApi.java @@ -0,0 +1,295 @@ +package com.glmapper.ai.chat.ollama.base; + +import com.alibaba.fastjson2.JSONObject; +import com.glmapper.ai.chat.ollama.util.OkhttpUtil; + + +import java.util.List; + +/** + * 群模块 + */ +public class GroupApi { + + /** + * 创建微信群 + * @param appId + * @return + */ + public static JSONObject createChatroom(String appId, List wxids){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("wxid",wxids); + return OkhttpUtil.postJSON("/group/createChatroom",param); + } + + /** + * 修改群名称 + * @param appId + * @return + */ + public static JSONObject modifyChatroomName(String appId, String chatroomName,String chatroomId){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("chatroomName",chatroomName); + param.put("chatroomId",chatroomId); + return OkhttpUtil.postJSON("/group/modifyChatroomName",param); + } + + /** + * 修改群备注 + * @param appId + * @return + */ + public static JSONObject modifyChatroomRemark(String appId, String chatroomRemark,String chatroomId){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("chatroomRemark",chatroomRemark); + param.put("chatroomId",chatroomId); + return OkhttpUtil.postJSON("/group/modifyChatroomRemark",param); + } + + /** + * 修改我在群内的昵称 + * @param appId + * @return + */ + public static JSONObject modifyChatroomNickNameForSelf(String appId, String nickName,String chatroomId){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("nickName",nickName); + param.put("chatroomId",chatroomId); + return OkhttpUtil.postJSON("/group/modifyChatroomNickNameForSelf",param); + } + + /** + * 邀请/添加 进群 + * @param appId + * @return + */ + public static JSONObject inviteMember(String appId, List wxids,String chatroomId, String reason){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("wxids",wxids); + param.put("reason",reason); + param.put("chatroomId",chatroomId); + return OkhttpUtil.postJSON("/group/inviteMember",param); + } + + /** + * 删除群成员 + * @param appId + * @return + */ + public static JSONObject removeMember(String appId, List wxids,String chatroomId){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("wxids",wxids); + param.put("chatroomId",chatroomId); + return OkhttpUtil.postJSON("/group/removeMember",param); + } + + /** + * 退出群聊 + * @param appId + * @return + */ + public static JSONObject modifyChatroomName(String appId,String chatroomId){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("chatroomId",chatroomId); + return OkhttpUtil.postJSON("/group/quitChatroom",param); + } + + /** + * 解散群聊 + * @param appId + * @return + */ + public static JSONObject disbandChatroom(String appId,String chatroomId){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("chatroomId",chatroomId); + return OkhttpUtil.postJSON("/group/disbandChatroom",param); + } + + /** + * 获取群信息 + * @param appId + * @return + */ + public static JSONObject getChatroomInfo(String appId,String chatroomId){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("chatroomId",chatroomId); + return OkhttpUtil.postJSON("/group/getChatroomInfo",param); + } + + /** + * 获取群成员列表 + * @param appId + * @return + */ + public static JSONObject getChatroomMemberList(String appId,String chatroomId){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("chatroomId",chatroomId); + return OkhttpUtil.postJSON("/group/getChatroomMemberList",param); + } + + /** + * 获取群成员详情 + * @param appId + * @return + */ + public static JSONObject getChatroomMemberDetail(String appId,String chatroomId,List memberWxids){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("memberWxids",memberWxids); + param.put("chatroomId",chatroomId); + return OkhttpUtil.postJSON("/group/getChatroomMemberDetail",param); + } + + /** + * 获取群公告 + * @param appId + * @return + */ + public static JSONObject getChatroomAnnouncement(String appId,String chatroomId){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("chatroomId",chatroomId); + return OkhttpUtil.postJSON("/group/getChatroomAnnouncement",param); + } + + /** + * 设置群公告 + * @param appId + * @return + */ + public static JSONObject setChatroomAnnouncement(String appId,String chatroomId, String content){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("chatroomId",chatroomId); + param.put("content",content); + return OkhttpUtil.postJSON("/group/setChatroomAnnouncement",param); + } + + /** + * 同意进群 + * @param appId + * @return + */ + public static JSONObject agreeJoinRoom(String appId, String url){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("chatroomName",url); + return OkhttpUtil.postJSON("/group/agreeJoinRoom",param); + } + + /** + * 添加群成员为好友 + * @param appId + * @return + */ + public static JSONObject addGroupMemberAsFriend(String appId, String memberWxid,String chatroomId,String content){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("memberWxid",memberWxid); + param.put("content",content); + param.put("chatroomId",chatroomId); + return OkhttpUtil.postJSON("/group/addGroupMemberAsFriend",param); + } + + /** + * 获取群二维码 + * @param appId + * @return + */ + public static JSONObject getChatroomQrCode(String appId,String chatroomId){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("chatroomId",chatroomId); + return OkhttpUtil.postJSON("/group/getChatroomQrCode",param); + } + + /** + * 群保存到通讯录 + * @param appId + * @return + */ + public static JSONObject saveContractList(String appId, Integer operType,String chatroomId){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("chatroomName",operType); + param.put("chatroomId",chatroomId); + return OkhttpUtil.postJSON("/group/saveContractList",param); + } + + /** + * 管理员操作 + * @param appId + * @return + */ + public static JSONObject adminOperate(String appId,String chatroomId,List wxids,Integer operType){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("wxids",wxids); + param.put("operType",operType); + param.put("chatroomId",chatroomId); + return OkhttpUtil.postJSON("/group/adminOperate",param); + } + + /** + * 聊天置顶 + * @param appId + * @return + */ + public static JSONObject pinChat(String appId, boolean top,String chatroomId){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("top",top); + param.put("chatroomId",chatroomId); + return OkhttpUtil.postJSON("/group/pinChat",param); + } + + /** + * 设置消息免打扰 + * @param appId + * @return + */ + public static JSONObject setMsgSilence(String appId, boolean silence,String chatroomId){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("silence",silence); + param.put("chatroomId",chatroomId); + return OkhttpUtil.postJSON("/group/setMsgSilence",param); + } + + /** + * 扫码进群 + * @param appId + * @return + */ + public static JSONObject joinRoomUsingQRCode(String appId, String qrUrl){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("qrUrl",qrUrl); + return OkhttpUtil.postJSON("/group/joinRoomUsingQRCode",param); + } + + /** + * 确认进群申请 + * @param appId + * @return + */ + public static JSONObject roomAccessApplyCheckApprove(String appId, String newMsgId,String chatroomId, String msgContent){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("newMsgId",newMsgId); + param.put("msgContent",msgContent); + param.put("chatroomId",chatroomId); + return OkhttpUtil.postJSON("/group/roomAccessApplyCheckApprove",param); + } + +} diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/LabelApi.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/LabelApi.java new file mode 100644 index 0000000..449285e --- /dev/null +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/LabelApi.java @@ -0,0 +1,54 @@ +package com.glmapper.ai.chat.ollama.base; + +import com.alibaba.fastjson2.JSONObject; +import com.glmapper.ai.chat.ollama.util.OkhttpUtil; + + +import java.util.List; + +/** + * 标签模块 + */ +public class LabelApi { + + /** + * 添加标签 + */ + public static JSONObject add(String appId, String labelName) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("labelName", labelName); + return OkhttpUtil.postJSON("/label/add", param); + } + + /** + * 删除标签 + */ + public static JSONObject delete(String appId, String labelIds) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("labelIds", labelIds); + return OkhttpUtil.postJSON("/label/delete", param); + } + + /** + * 添加标签 + */ + public static JSONObject list(String appId) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + return OkhttpUtil.postJSON("/label/list", param); + } + + /** + * 添加标签 + */ + public static JSONObject modifyMemberList(String appId, String labelIds, List wxIds) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("labelIds", labelIds); + param.put("wxIds", wxIds); + return OkhttpUtil.postJSON("/label/modifyMemberList", param); + } + +} diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/LoginApi.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/LoginApi.java new file mode 100644 index 0000000..7f82fbe --- /dev/null +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/LoginApi.java @@ -0,0 +1,110 @@ +package com.glmapper.ai.chat.ollama.base; + +import com.alibaba.fastjson2.JSONObject; +import com.glmapper.ai.chat.ollama.util.OkhttpUtil; + + +/** + * 登录模块 + */ +public class LoginApi { + + + /** + * 获取tokenId 将tokenId 配置到OkhttpUtil 类中的token 属性 + * + * @return + */ + public static JSONObject getToken() { + return OkhttpUtil.postJSON("/tools/getTokenId", new JSONObject()); + } + + /** + * 设置微信消息的回调地址 + * + * @return + */ + public static JSONObject setCallback(String token,String callbackUrl) { + JSONObject param = new JSONObject(); + param.put("token",token); + param.put("callbackUrl",callbackUrl); + return OkhttpUtil.postJSON("/tools/setCallback", param); + } + + /** + * 获取登录二维码 + * + * @param appId 设备id 首次登录传空,后续登录传返回的appid + * @return + */ + public static JSONObject getQr(String appId) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + return OkhttpUtil.postJSON("/login/getLoginQrCode", param); + } + + /** + * 确认登陆 + * + * @param appId + * @param uuid 取码返回的uuid + * @param captchCode 登录验证码(跨省登录会出现此提示,使用同省代理ip能避免此问题,也能使账号更加稳定) + * @return + */ + public static JSONObject checkQr(String appId, String uuid, String captchCode) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("uuid", uuid); + param.put("captchCode", captchCode); + return OkhttpUtil.postJSON("/login/checkLogin", param); + } + + /** + * 退出微信 + * + * @param appId + * @return + */ + public static JSONObject logOut(String appId) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + return OkhttpUtil.postJSON("/login/logout", param); + } + + /** + * 弹框登录 + * + * @param appId + * @return + */ + public static JSONObject dialogLogin(String appId) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + return OkhttpUtil.postJSON("/login/dialogLogin", param); + } + + /** + * 检查是否在线 + * + * @param appId + * @return + */ + public static JSONObject checkOnline(String appId) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + return OkhttpUtil.postJSON("/login/checkOnline", param); + } + + /** + * 退出 + * + * @param appId + * @return + */ + public static JSONObject logout(String appId) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + return OkhttpUtil.postJSON("/login/logout", param); + } + +} diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/MessageApi.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/MessageApi.java new file mode 100644 index 0000000..bd20124 --- /dev/null +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/MessageApi.java @@ -0,0 +1,206 @@ +package com.glmapper.ai.chat.ollama.base; + +import com.alibaba.fastjson2.JSONObject; +import com.glmapper.ai.chat.ollama.util.OkhttpUtil; + + +/** + * 消息模块 + */ +public class MessageApi { + + /** + * 发送文字消息 + */ + public static JSONObject postText(String appId, String toWxid, String content, String ats) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("toWxid", toWxid); + param.put("content", content); + param.put("ats", ats); + return OkhttpUtil.postJSON("/message/postText", param); + } + + /** + * 发送文件消息 + */ + public static JSONObject postFile(String appId, String toWxid, String fileUrl, String fileName) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("toWxid", toWxid); + param.put("fileUrl", fileUrl); + param.put("fileName", fileName); + return OkhttpUtil.postJSON("/message/postFile", param); + } + + /** + * 发送图片消息 + */ + public static JSONObject postImage(String appId, String toWxid, String imgUrl) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("toWxid", toWxid); + param.put("imgUrl", imgUrl); + return OkhttpUtil.postJSON("/message/postImage", param); + } + + /** + * 发送语音消息 + */ + public static JSONObject postVoice(String appId, String toWxid, String voiceUrl, Integer voiceDuration) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("toWxid", toWxid); + param.put("voiceUrl", voiceUrl); + param.put("voiceDuration", voiceDuration); + return OkhttpUtil.postJSON("/message/postVoice", param); + } + + /** + * 发送视频消息 + */ + public static JSONObject postVideo(String appId, String toWxid, String videoUrl, String thumbUrl,Integer videoDuration) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("toWxid", toWxid); + param.put("videoUrl", videoUrl); + param.put("thumbUrl", thumbUrl); + param.put("videoDuration", videoDuration); + return OkhttpUtil.postJSON("/message/postVideo", param); + } + + /** + * 发送链接消息 + */ + public static JSONObject postLink(String appId, String toWxid, String title, String desc, String linkUrl, String thumbUrl) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("toWxid", toWxid); + param.put("title", title); + param.put("desc", desc); + param.put("linkUrl", linkUrl); + param.put("thumbUrl", thumbUrl); + return OkhttpUtil.postJSON("/message/postLink", param); + } + + /** + * 发送名片消息 + */ + public static JSONObject postNameCard(String appId, String toWxid, String nickName, String nameCardWxid) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("toWxid", toWxid); + param.put("nickName", nickName); + param.put("nameCardWxid", nameCardWxid); + return OkhttpUtil.postJSON("/message/postNameCard", param); + } + + /** + * 发送emoji消息 + */ + public static JSONObject postEmoji(String appId, String toWxid, String emojiMd5, String emojiSize) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("toWxid", toWxid); + param.put("emojiMd5", emojiMd5); + param.put("emojiSize", emojiSize); + return OkhttpUtil.postJSON("/message/postEmoji", param); + } + + /** + * 发送appmsg消息 + */ + public static JSONObject postAppMsg(String appId, String toWxid, String appmsg) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("toWxid", toWxid); + param.put("appmsg", appmsg); + return OkhttpUtil.postJSON("/message/postAppMsg", param); + } + + /** + * 发送小程序消息 + */ + public static JSONObject postMiniApp(String appId, String toWxid, String miniAppId, String displayName, String pagePath, String coverImgUrl, String title, String userName) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("toWxid", toWxid); + param.put("miniAppId", miniAppId); + param.put("displayName", displayName); + param.put("pagePath", pagePath); + param.put("coverImgUrl", coverImgUrl); + param.put("title", title); + param.put("userName", userName); + return OkhttpUtil.postJSON("/message/postMiniApp", param); + } + + /** + * 转发文件 + */ + public static JSONObject forwardFile(String appId, String toWxid, String xml) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("toWxid", toWxid); + param.put("xml", xml); + return OkhttpUtil.postJSON("/message/forwardFile", param); + } + + /** + * 转发图片 + */ + public static JSONObject forwardImage(String appId, String toWxid, String xml) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("toWxid", toWxid); + param.put("xml", xml); + return OkhttpUtil.postJSON("/message/forwardImage", param); + } + + /** + * 转发视频 + */ + public static JSONObject forwardVideo(String appId, String toWxid, String xml) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("toWxid", toWxid); + param.put("xml", xml); + return OkhttpUtil.postJSON("/message/forwardVideo", param); + } + + /** + * 转发链接 + */ + public static JSONObject forwardUrl(String appId, String toWxid, String xml) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("toWxid", toWxid); + param.put("xml", xml); + return OkhttpUtil.postJSON("/message/forwardUrl", param); + } + + /** + * 转发小程序 + */ + public static JSONObject forwardMiniApp(String appId, String toWxid, String xml, String coverImgUrl) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("toWxid", toWxid); + param.put("xml", xml); + param.put("coverImgUrl", coverImgUrl); + return OkhttpUtil.postJSON("/message/forwardMiniApp", param); + } + + /** + * 撤回消息 + */ + public static JSONObject revokeMsg(String appId, String toWxid, String msgId, String newMsgId,String createTime) { + JSONObject param = new JSONObject(); + param.put("appId", appId); + param.put("toWxid", toWxid); + param.put("msgId", msgId); + param.put("newMsgId", newMsgId); + param.put("createTime", createTime); + return OkhttpUtil.postJSON("/message/revokeMsg", param); + } + +} diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/PersonalApi.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/PersonalApi.java new file mode 100644 index 0000000..cade682 --- /dev/null +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/base/PersonalApi.java @@ -0,0 +1,76 @@ +package com.glmapper.ai.chat.ollama.base; + +import com.alibaba.fastjson2.JSONObject; +import com.glmapper.ai.chat.ollama.util.OkhttpUtil; + + +/** + * 个人模块 + */ +public class PersonalApi { + + /** + * 获取个人资料 + */ + public static JSONObject getProfile(String appId){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + return OkhttpUtil.postJSON("/personal/getProfile",param); + } + + + /** + * 获取自己的二维码 + */ + public static JSONObject getQrCode(String appId){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + return OkhttpUtil.postJSON("/personal/getQrCode",param); + } + + /** + * 获取设备记录 + */ + public static JSONObject getSafetyInfo(String appId){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + return OkhttpUtil.postJSON("/personal/getSafetyInfo",param); + } + + /** + * 隐私设置 + */ + public static JSONObject privacySettings(String appId,Integer option,boolean open){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("option",option); + param.put("open",open); + return OkhttpUtil.postJSON("/personal/privacySettings",param); + } + + /** + * 修改个人信息 + */ + public static JSONObject updateProfile(String appId,String city,String country,String nickName,String province,String sex,String signature){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("city",city); + param.put("country",country); + param.put("nickName",nickName); + param.put("province",province); + param.put("sex",sex); + param.put("signature",signature); + return OkhttpUtil.postJSON("/personal/updateProfile",param); + } + + /** + * 修改头像 + */ + public static JSONObject updateHeadImg(String appId,String headImgUrl){ + JSONObject param = new JSONObject(); + param.put("appId",appId); + param.put("headImgUrl",headImgUrl); + return OkhttpUtil.postJSON("/personal/updateHeadImg",param); + } + +} diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/util/OkhttpUtil.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/util/OkhttpUtil.java new file mode 100644 index 0000000..97c4e35 --- /dev/null +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/util/OkhttpUtil.java @@ -0,0 +1,117 @@ +package com.glmapper.ai.chat.ollama.util; + +import com.alibaba.fastjson2.JSONObject; +import okhttp3.*; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.io.IOException; +import java.security.SecureRandom; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +public class OkhttpUtil { + + private final static String baseUrl = "http://服务ip:2531/v2/api"; + private final static String token = ""; + + public static OkHttpClient okHttpClient() { + TrustManager[] trustManagers = buildTrustManagers(); + return new OkHttpClient.Builder() + .connectTimeout(60, TimeUnit.SECONDS) + .readTimeout(60, TimeUnit.SECONDS) + .writeTimeout(60, TimeUnit.SECONDS) + .sslSocketFactory(createSSLSocketFactory(trustManagers), (X509TrustManager) trustManagers[0]) + .hostnameVerifier((hostName, sessino) -> true) + .retryOnConnectionFailure(false)//是否开启缓存 + .build(); + } + + private static TrustManager[] buildTrustManagers() { + return new TrustManager[]{ + new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) { + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[]{}; + } + } + }; + } + + private static SSLSocketFactory createSSLSocketFactory(TrustManager[] trustAllCerts) { + SSLSocketFactory ssfFactory = null; + try { + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, trustAllCerts, new SecureRandom()); + ssfFactory = sc.getSocketFactory(); + } catch (Exception e) { + e.printStackTrace(); + } + return ssfFactory; + } + + public static JSONObject postJSON(String route,JSONObject param){ + Map header = new HashMap<>(); + if(token != null){ + header.put("X-GEWE-TOKEN",token); + } + try { + if(baseUrl == null || "".equals(baseUrl)){ + throw new RuntimeException("baseUrl 未配置"); + } + String res = json(baseUrl + route, header, param.toJSONString(), okHttpClient()); + System.out.println(res); + JSONObject jsonObject = JSONObject.parse(res); + if(jsonObject.getInteger("ret") == 200){ + return jsonObject; + }else{ + throw new RuntimeException(res); + } + } catch (Exception e) { + System.out.println("url="+baseUrl + route); + throw new RuntimeException(e); + } + } + + private static String json(String url, Map header, String json, OkHttpClient client) throws IOException { + // 创建一个请求 Builder + Request.Builder builder = new Request.Builder(); + // 创建一个 request + Request request = builder.url(url).build(); + + // 创建一个 Headers.Builder + Headers.Builder headerBuilder = request.headers().newBuilder(); + + // 装载请求头参数 + Iterator> headerIterator = header.entrySet().iterator(); + headerIterator.forEachRemaining(e -> { + headerBuilder.add(e.getKey(), (String) e.getValue()); + }); + headerBuilder.add("Content-Type", "application/json"); + + // application/octet-stream + RequestBody requestBody = FormBody.create(MediaType.parse("application/json"), json); + + // 设置自定义的 builder + builder.headers(headerBuilder.build()).post(requestBody); + + try (Response execute = client.newCall(builder.build()).execute()) { + return execute.body().string(); + } + } + +} diff --git a/spring-ai-mcp/nacos-mcp-client/pom.xml b/spring-ai-mcp/nacos-mcp-client/pom.xml index 45c84c6..1f369f8 100644 --- a/spring-ai-mcp/nacos-mcp-client/pom.xml +++ b/spring-ai-mcp/nacos-mcp-client/pom.xml @@ -14,11 +14,11 @@ - - com.alibaba.cloud.ai - spring-ai-alibaba-starter-nacos-mcp-client - 1.0.0.3-SNAPSHOT - + + + + + org.springframework.ai diff --git a/spring-ai-mcp/nacos-mcp-server/pom.xml b/spring-ai-mcp/nacos-mcp-server/pom.xml index 3bac2bb..59d1578 100644 --- a/spring-ai-mcp/nacos-mcp-server/pom.xml +++ b/spring-ai-mcp/nacos-mcp-server/pom.xml @@ -19,11 +19,11 @@ spring-ai-starter-mcp-server-webmvc - - com.alibaba.cloud.ai - spring-ai-alibaba-starter-nacos-mcp-server - 1.0.0.3-SNAPSHOT - + + + + + From a3cd223a58195970112130cee5898e32f2079bb3 Mon Sep 17 00:00:00 2001 From: yl-dengxs <1195279222@qq.com> Date: Wed, 14 Jan 2026 17:57:21 +0800 Subject: [PATCH 3/9] =?UTF-8?q?=E5=85=A8=E5=B1=80=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=E8=AF=8D=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/chat/ollama/configs/OllamaChatClientConfigs.java | 3 ++- .../glmapper/ai/chat/ollama/controller/ChatController.java | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/configs/OllamaChatClientConfigs.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/configs/OllamaChatClientConfigs.java index adfe950..5bdcb35 100644 --- a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/configs/OllamaChatClientConfigs.java +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/configs/OllamaChatClientConfigs.java @@ -25,7 +25,8 @@ public class OllamaChatClientConfigs { @Bean public ChatClient chatClient(OllamaChatModel chatModel) { return ChatClient.builder(chatModel) - .defaultSystem("You are a friendly chat bot that answers question with json always") +// .defaultSystem("You are a friendly chat bot that answers question with json always") + .defaultSystem("你是一个智能助手,请用自然语言形式回答") .build(); } } \ No newline at end of file diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/ChatController.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/ChatController.java index a9711d4..4eaf2f7 100644 --- a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/ChatController.java +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/ChatController.java @@ -30,8 +30,8 @@ public class ChatController { */ @GetMapping("/chat") public String prompt(@RequestParam String userInput) { - return this.chatClient.prompt("你是一个智能助手,请用自然语言形式回答,不要使用JSON格式或其他结构化格式") - .user("问题:" + userInput) + return this.chatClient.prompt() + .user( userInput) .call() .content(); } @@ -48,7 +48,7 @@ public SseEmitter promptStream(@RequestParam String userInput) { try { // 使用流式调用 - Flux response = this.chatClient.prompt("你是一个智能助手,请用自然语言形式回答,不要使用JSON格式或其他结构化格式") + Flux response = this.chatClient.prompt() .user(userInput) .stream() .content(); From b055f8b7e8137202ac19ae2c33bbb096ccfedf78 Mon Sep 17 00:00:00 2001 From: yl-dengxs <1195279222@qq.com> Date: Wed, 14 Jan 2026 17:58:07 +0800 Subject: [PATCH 4/9] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=E8=AE=B0?= =?UTF-8?q?=E5=BF=86=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/schema-mysql.sql | 9 ++- spring-ai-chat/spring-ai-chat-ollama/pom.xml | 9 +++ .../ollama/controller/ChatController.java | 18 +++++ .../ollama/service/ChatMemoryService.java | 71 +++++++++++++++++++ .../src/main/resources/application.properties | 10 --- .../src/main/resources/schema-mysql.sql | 9 +++ 6 files changed, 111 insertions(+), 15 deletions(-) create mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/service/ChatMemoryService.java delete mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/resources/application.properties create mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/resources/schema-mysql.sql diff --git a/spring-ai-chat-memory/spring-ai-chat-memory-jdbc/src/main/resources/schema-mysql.sql b/spring-ai-chat-memory/spring-ai-chat-memory-jdbc/src/main/resources/schema-mysql.sql index 6a0ef87..f503ea8 100644 --- a/spring-ai-chat-memory/spring-ai-chat-memory-jdbc/src/main/resources/schema-mysql.sql +++ b/spring-ai-chat-memory/spring-ai-chat-memory-jdbc/src/main/resources/schema-mysql.sql @@ -1,10 +1,9 @@ CREATE TABLE IF NOT EXISTS SPRING_AI_CHAT_MEMORY ( - conversation_id VARCHAR(36) NOT NULL, + conversation_id VARCHAR(36) NOT NULL, content TEXT NOT NULL, type VARCHAR(10) NOT NULL, - `timestamp` TIMESTAMP NOT NULL, + `timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT TYPE_CHECK CHECK (type IN ('USER', 'ASSISTANT', 'SYSTEM', 'TOOL')) -); + ); -CREATE INDEX IF NOT EXISTS SPRING_AI_CHAT_MEMORY_CONVERSATION_ID_TIMESTAMP_IDX -ON SPRING_AI_CHAT_MEMORY(conversation_id, `timestamp`); \ No newline at end of file +CREATE INDEX SPRING_AI_CHAT_MEMORY_CONVERSATION_ID_TIMESTAMP_IDX ON SPRING_AI_CHAT_MEMORY(conversation_id, `timestamp`); \ No newline at end of file diff --git a/spring-ai-chat/spring-ai-chat-ollama/pom.xml b/spring-ai-chat/spring-ai-chat-ollama/pom.xml index 4b6b661..74261c8 100644 --- a/spring-ai-chat/spring-ai-chat-ollama/pom.xml +++ b/spring-ai-chat/spring-ai-chat-ollama/pom.xml @@ -30,6 +30,15 @@ okhttp 3.10.0 + + org.springframework.ai + spring-ai-starter-model-chat-memory-repository-jdbc + + + mysql + mysql-connector-java + 8.0.33 + diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/ChatController.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/ChatController.java index 4eaf2f7..9c89b21 100644 --- a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/ChatController.java +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/ChatController.java @@ -1,5 +1,6 @@ package com.glmapper.ai.chat.ollama.controller; +import com.glmapper.ai.chat.ollama.service.ChatMemoryService; import org.springframework.ai.chat.client.ChatClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; @@ -21,6 +22,8 @@ public class ChatController { @Autowired private ChatClient chatClient; + @Autowired + private ChatMemoryService chatMemoryService; /** * 普通的聊天接口 @@ -36,6 +39,21 @@ public String prompt(@RequestParam String userInput) { .content(); } + /** + * 普通的聊天接口 + * + * @param userInput 用户输入 + * @return 返回内容 + */ + @GetMapping("/chat-memory") + public String prompt(@RequestParam String userInput,String conversationId) { + return chatMemoryService.call(userInput,conversationId); +// return this.chatClient.prompt("你是一个智能助手,请用自然语言形式回答,不要使用JSON格式或其他结构化格式") +// .user("问题:" + userInput) +// .call() +// .content(); + } + /** * 流式聊天接口 * diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/service/ChatMemoryService.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/service/ChatMemoryService.java new file mode 100644 index 0000000..1c25b7d --- /dev/null +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/service/ChatMemoryService.java @@ -0,0 +1,71 @@ +package com.glmapper.ai.chat.ollama.service; + +import jakarta.annotation.PostConstruct; +import org.springframework.ai.chat.memory.ChatMemory; +import org.springframework.ai.chat.memory.MessageWindowChatMemory; +import org.springframework.ai.chat.memory.repository.jdbc.JdbcChatMemoryRepository; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.chat.model.ChatModel; +import org.springframework.ai.chat.model.ChatResponse; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @Classname StorageService + * @Description StorageService + * @Date 2025/5/29 09:29 + * @Created by glmapper + */ +@Service +public class ChatMemoryService { + + @Autowired + private ChatModel chatModel; + + @Autowired + private JdbcChatMemoryRepository chatMemoryRepository; + + private ChatMemory chatMemory; + + @PostConstruct + public void init() { + this.chatMemory = MessageWindowChatMemory.builder() + .chatMemoryRepository(chatMemoryRepository) + .maxMessages(20) + .build(); + } + + public String call(String message, String conversationId) { + UserMessage userMessage = new UserMessage(message); + this.chatMemory.add(conversationId, userMessage); + List messages = chatMemory.get(conversationId); + ChatResponse response = chatModel.call(new Prompt(messages)); + chatMemory.add(conversationId, response.getResult().getOutput()); + return response.getResult().getOutput().getText(); + } + + /** + * 模拟一个对话场景,用户先介绍自己的名字,然后询问 AI 自己的名字 + *

+ * 这里使用的方式是 Memory in Chat Model + * + * @param message 用户输入的消息 + * @param conversationId 对话 ID + * @return AI 的回答 + */ + public void chat(String message, String conversationId) { + // First interaction + call("My name is James Bond", conversationId); + // Second interaction + call("What is my name?", conversationId); + } + + + public ChatMemory getChatMemory() { + return chatMemory; + } +} diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/resources/application.properties b/spring-ai-chat/spring-ai-chat-ollama/src/main/resources/application.properties deleted file mode 100644 index 80650b1..0000000 --- a/spring-ai-chat/spring-ai-chat-ollama/src/main/resources/application.properties +++ /dev/null @@ -1,10 +0,0 @@ -spring.application.name=spring-ai-chat-ollama -server.port=8081 -spring.profiles.active=ollama - -# Ollama configuration for Spring AI Chat -# The address of the Ollama service, which defaults to http://localhost:11434. -spring.ai.ollama.base-url=http://localhost:11434 -# The model name which is the one you previously downloaded via the terminal using `ollama pull` or `ollama run` -spring.ai.ollama.chat.model=glm4:9b -spring.ai.ollama.chat.options.temperature=0.7 diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/resources/schema-mysql.sql b/spring-ai-chat/spring-ai-chat-ollama/src/main/resources/schema-mysql.sql new file mode 100644 index 0000000..f503ea8 --- /dev/null +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/resources/schema-mysql.sql @@ -0,0 +1,9 @@ +CREATE TABLE IF NOT EXISTS SPRING_AI_CHAT_MEMORY ( + conversation_id VARCHAR(36) NOT NULL, + content TEXT NOT NULL, + type VARCHAR(10) NOT NULL, + `timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT TYPE_CHECK CHECK (type IN ('USER', 'ASSISTANT', 'SYSTEM', 'TOOL')) + ); + +CREATE INDEX SPRING_AI_CHAT_MEMORY_CONVERSATION_ID_TIMESTAMP_IDX ON SPRING_AI_CHAT_MEMORY(conversation_id, `timestamp`); \ No newline at end of file From 7098e39d2cb1d6a9050b00005da2bd62de5375aa Mon Sep 17 00:00:00 2001 From: yl-dengxs <1195279222@qq.com> Date: Sun, 21 Jun 2026 11:34:50 +0800 Subject: [PATCH 5/9] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=E8=AE=B0?= =?UTF-8?q?=E5=BF=86=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ollama/controller/WxBotController.java | 22 +++++++++++++++ .../src/main/resources/application.yml | 28 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/WxBotController.java create mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/resources/application.yml diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/WxBotController.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/WxBotController.java new file mode 100644 index 0000000..d253a96 --- /dev/null +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/WxBotController.java @@ -0,0 +1,22 @@ +package com.glmapper.ai.chat.ollama.controller; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +/** + * @description: + * @author:dxs + * @date:2026/1/15 09:11 + */ +@Slf4j +@RestController +@RequestMapping("/wxbot") +public class WxBotController { + @PostMapping("/callBack") + public String callBack(@RequestBody Map msg) { + log.info("接收到微信消息:{}", msg); + return "success"; + } +} diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/resources/application.yml b/spring-ai-chat/spring-ai-chat-ollama/src/main/resources/application.yml new file mode 100644 index 0000000..83bcc11 --- /dev/null +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/resources/application.yml @@ -0,0 +1,28 @@ +spring: + application: + name: spring-ai-chat-ollama + profiles: + active: ollama + datasource: + url: jdbc:mysql://localhost:3306/wxbot?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC + username: root + password: 12345678 + driver-class-name: com.mysql.cj.jdbc.Driver + ai: + ollama: + base-url: http://localhost:11434 + chat: + model: glm4:9b + options: + temperature: 0.7 + chat: + memory: + repository: + jdbc: + initialize-schema: always + schema: classpath:schema-@@platform@@.sql + platform: mysql + +server: + port: 8081 + From 8f9227b45d101ac12a7a2862e7e23482beebf459 Mon Sep 17 00:00:00 2001 From: yl-dengxs <1195279222@qq.com> Date: Sun, 21 Jun 2026 11:43:02 +0800 Subject: [PATCH 6/9] =?UTF-8?q?Revert=20"=E6=B7=BB=E5=8A=A0=E4=BA=86?= =?UTF-8?q?=E8=AE=B0=E5=BF=86=E6=A8=A1=E5=9D=97"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 7098e39d2cb1d6a9050b00005da2bd62de5375aa. --- .../ollama/controller/WxBotController.java | 22 --------------- .../src/main/resources/application.yml | 28 ------------------- 2 files changed, 50 deletions(-) delete mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/WxBotController.java delete mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/resources/application.yml diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/WxBotController.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/WxBotController.java deleted file mode 100644 index d253a96..0000000 --- a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/WxBotController.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.glmapper.ai.chat.ollama.controller; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.web.bind.annotation.*; - -import java.util.Map; - -/** - * @description: - * @author:dxs - * @date:2026/1/15 09:11 - */ -@Slf4j -@RestController -@RequestMapping("/wxbot") -public class WxBotController { - @PostMapping("/callBack") - public String callBack(@RequestBody Map msg) { - log.info("接收到微信消息:{}", msg); - return "success"; - } -} diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/resources/application.yml b/spring-ai-chat/spring-ai-chat-ollama/src/main/resources/application.yml deleted file mode 100644 index 83bcc11..0000000 --- a/spring-ai-chat/spring-ai-chat-ollama/src/main/resources/application.yml +++ /dev/null @@ -1,28 +0,0 @@ -spring: - application: - name: spring-ai-chat-ollama - profiles: - active: ollama - datasource: - url: jdbc:mysql://localhost:3306/wxbot?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC - username: root - password: 12345678 - driver-class-name: com.mysql.cj.jdbc.Driver - ai: - ollama: - base-url: http://localhost:11434 - chat: - model: glm4:9b - options: - temperature: 0.7 - chat: - memory: - repository: - jdbc: - initialize-schema: always - schema: classpath:schema-@@platform@@.sql - platform: mysql - -server: - port: 8081 - From 470cf59091eb4bb19c578376f74d8d367a497abc Mon Sep 17 00:00:00 2001 From: yl-dengxs <1195279222@qq.com> Date: Sun, 21 Jun 2026 12:02:23 +0800 Subject: [PATCH 7/9] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=E8=AE=B0?= =?UTF-8?q?=E5=BF=86=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/glmapper/ai/chat/ollama/controller/ChatController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/ChatController.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/ChatController.java index 9c89b21..22fe632 100644 --- a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/ChatController.java +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/controller/ChatController.java @@ -14,7 +14,7 @@ * @Classname ChatController * @Description ollama ChatController * @Date 2025/6/6 08:26 - * @Created by Gepeng18 + * @Created by Gepeng18111 */ @RestController @RequestMapping("/api/ollama") From 5d784e3bc864fee37c62592c2a437f6c725bb7c4 Mon Sep 17 00:00:00 2001 From: yl-dengxs <1195279222@qq.com> Date: Sun, 21 Jun 2026 12:09:25 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E6=B7=BB=E5=8A=A0claude.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CLAUDE.md | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..634cdaa --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,71 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +Spring AI Summary 是基于 Spring AI 框架的模块化示例工程集合,用于学习 Spring AI 核心功能。包含聊天、向量数据库、RAG、MCP、Agent 等多个功能模块的示例代码。 + +## 技术栈 + +- **Java**: 21 +- **Spring Boot**: 3.3.6 +- **Spring AI**: 1.0.0 +- **构建工具**: Maven 3.6+ (推荐使用 mvnd 加速) +- **Lombok**: 用于简化 POJO 代码 + +## 常用命令 + +```bash +# 编译整个项目 +mvn clean compile -DskipTests + +# 编译单个模块 (如 spring-ai-chat-deepseek) +mvn clean compile -DskipTests -pl spring-ai-chat/spring-ai-chat-deepseek + +# 运行测试 +mvn test -pl + +# 打包 +mvn clean package -DskipTests +``` + +## 模块结构 + +``` +spring-ai-summary/ +├── spring-ai-chat/ # 聊天示例 (DeepSeek, Doubao, OpenAI, Qwen, Ollama, 多模型) +├── spring-ai-vector/ # 向量数据库 (MariaDB, Redis, Milvus) +├── spring-ai-rag/ # RAG 检索增强生成 +├── spring-ai-mcp/ # MCP 协议 (客户端/服务端 + Nacos 集成) +├── spring-ai-evaluation/ # 模型评估 +├── spring-ai-chat-memory/ # 对话记忆 (JDBC, 本地存储) +├── spring-ai-tool-calling/ # 工具调用 +├── spring-ai-agent/ # Agent 模式 (工作流、评估优化、编排) +└── spring-ai-observability/ # 可观测性 (指标、链路追踪) +``` + +## 配置说明 + +每个子模块在 `src/main/resources/` 下有独立的配置文件 (application.properties 或 application.yml)。API 密钥通过环境变量注入: + +```properties +spring.ai.deepseek.api-key=${spring.ai.deepseek.api-key} +spring.ai.openai.api-key=${OPENAI_API_KEY} +``` + +敏感配置文件 (如 `application-deepseek.properties`) 已被 `.gitignore` 排除。 + +## 运行示例 + +1. 配置对应模块的 API 密钥环境变量 +2. 运行模块的 Application 主类 (如 `DsChatApplication`) +3. 默认端口在各模块配置文件中定义 (通常 8080-8082) +4. 通过 Actuator 端点监控: `http://localhost:/actuator` + +## 学习路径建议 + +1. `spring-ai-chat` - 聊天应用开发 (必选起点) +2. `spring-ai-tool-calling` - 工具调用能力 +3. `spring-ai-vector` - 向量数据库集成 +4. `spring-ai-mcp` / `spring-ai-rag` / `spring-ai-agent` - 高级应用模式 \ No newline at end of file From 43a53554bd10895b1f87610ff1be846e2cc4ffa8 Mon Sep 17 00:00:00 2001 From: yl-dengxs <1195279222@qq.com> Date: Sun, 21 Jun 2026 12:26:34 +0800 Subject: [PATCH 9/9] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/chat/ollama/util/TestUtils.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/util/TestUtils.java diff --git a/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/util/TestUtils.java b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/util/TestUtils.java new file mode 100644 index 0000000..9146504 --- /dev/null +++ b/spring-ai-chat/spring-ai-chat-ollama/src/main/java/com/glmapper/ai/chat/ollama/util/TestUtils.java @@ -0,0 +1,18 @@ +package com.glmapper.ai.chat.ollama.util; + +/** + * @description: + * @author:dxs + * @date:2026/6/21 12:24 + * + */ +public class TestUtils { + // 编写一个性能很差的方法 + public static void slowMethod() { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +}