diff --git a/src/main/java/cn/bugstack/xfg/frame/config/Retrofit2Config.java b/src/main/java/cn/bugstack/xfg/frame/config/Retrofit2Config.java index d612756cd1f6a86857edb3cf66bcdd38c38c8c57..b6c0cf37c75cd1099b0a4d9722d5fb1bf22f4ac8 100644 --- a/src/main/java/cn/bugstack/xfg/frame/config/Retrofit2Config.java +++ b/src/main/java/cn/bugstack/xfg/frame/config/Retrofit2Config.java @@ -3,48 +3,64 @@ package cn.bugstack.xfg.frame.config; import cn.bugstack.xfg.frame.service.IKnowledgeCenterService; import lombok.extern.slf4j.Slf4j; import okhttp3.OkHttpClient; +import okhttp3.Request; import okhttp3.logging.HttpLoggingInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import retrofit2.Retrofit; import retrofit2.converter.jackson.JacksonConverterFactory; +import javax.annotation.Resource; import java.util.concurrent.TimeUnit; @Slf4j @Configuration public class Retrofit2Config { - private static final String BASE_URL = "https://demo.ragflow.io/"; + + @Resource + private RagflowProperties ragflowProperties; + + @Resource + private AuthInterceptor authInterceptor; @Bean public Retrofit retrofit() { - // 创建日志拦截器 - HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() { - @Override - public void log(String message) { - // 使用 SLF4J 记录日志,便于与 Spring Boot 日志系统集成 - log.info("Retrofit: {}", message); - } - }); - - // 设置日志级别 - loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); - // 创建 OkHttpClient 并添加拦截器 - OkHttpClient okHttpClient = new OkHttpClient.Builder() - .addInterceptor(loggingInterceptor) - .connectTimeout(30, TimeUnit.SECONDS) - .readTimeout(30, TimeUnit.SECONDS) - .writeTimeout(30, TimeUnit.SECONDS) - .build(); return new Retrofit.Builder() - .baseUrl(BASE_URL) - .client(okHttpClient) + .baseUrl(ragflowProperties.getApi().getBaseUrl()) + .client(createOkHttpClient()) .addConverterFactory(JacksonConverterFactory.create()).build(); } + private OkHttpClient createOkHttpClient() { + // 创建日志拦截器 + HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); + loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); + + // 创建请求头拦截器 + okhttp3.Interceptor headerInterceptor = chain -> { + okhttp3.Request originalRequest = chain.request(); + + // 添加公共请求头 + okhttp3.Request newRequest = originalRequest.newBuilder() + .addHeader("Content-Type", "application/json") + .addHeader("Authorization", "Bearer ragflow-IzZjQ5Y2ZhYWNkZjExZjA5MTA4MDI0Mm") // 认证token + .build(); + + return chain.proceed(newRequest); + }; + + return new OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS) // 连接超时 + .readTimeout(30, TimeUnit.SECONDS) // 读取超时 + .writeTimeout(30, TimeUnit.SECONDS) // 写入超时 + .addInterceptor(headerInterceptor) // 添加请求头拦截器 + .addInterceptor(loggingInterceptor) // 添加日志拦截器 + .build(); + } + @Bean public IKnowledgeCenterService knowledgeCenterService() { return retrofit().create(IKnowledgeCenterService.class); diff --git a/src/main/java/cn/bugstack/xfg/frame/controller/UserController.java b/src/main/java/cn/bugstack/xfg/frame/controller/UserController.java index 4904cbcc6ae533dbaa789535dc0a077689f0d086..c96a6719a51d3b62bd8c7d5f0b25260d23cbd86a 100644 --- a/src/main/java/cn/bugstack/xfg/frame/controller/UserController.java +++ b/src/main/java/cn/bugstack/xfg/frame/controller/UserController.java @@ -1,11 +1,17 @@ package cn.bugstack.xfg.frame.controller; +import cn.bugstack.xfg.frame.common.AssistantType; import cn.bugstack.xfg.frame.common.Result; +import cn.bugstack.xfg.frame.domain.req.CreateChatReq; +import cn.bugstack.xfg.frame.domain.req.CreateSessionReq; import cn.bugstack.xfg.frame.domain.req.KeySensorCompletionReq; +import cn.bugstack.xfg.frame.domain.res.ChatIdRes; import cn.bugstack.xfg.frame.domain.res.CompletionRes; +import cn.bugstack.xfg.frame.domain.res.SessionRes; import cn.bugstack.xfg.frame.domain.res.UserRes; import cn.bugstack.xfg.frame.domain.vo.UserVO; import cn.bugstack.xfg.frame.service.IKnowledgeCenterService; +import cn.bugstack.xfg.frame.service.IPromptService; import cn.bugstack.xfg.frame.service.IUserService; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestMapping; @@ -44,13 +50,49 @@ public class UserController { @RequestMapping("/queryAI") public String queryAI() throws IOException { // todo 构建ai (提示词) + // 根据这里的key 拿到提示词位置 + AssistantType generalAssistant= AssistantType.fromConfigKey("general"); + + // 获取这个type 对应的提示词 + String sysPrompt = IPromptService.loadPromptFromFile(generalAssistant); + + // 3. 构建 PromptConfig + CreateChatReq.PromptConfig promptConfig = CreateChatReq.PromptConfig.builder() + .prompt(sysPrompt) + .build(); + + // 5. 构建创建聊天请求 + CreateChatReq createChatReq = CreateChatReq.builder() + .name(generalAssistant.getDescription() + " - " + System.currentTimeMillis()) + .promptConfig(promptConfig) + .build(); + + Call chat = knowledgeCenterService.createChat(createChatReq); + ChatIdRes chatIdRes = chat.execute().body(); + log.info("chatIdRes: {}", chatIdRes); + + // ======================== + log.info("开始创建session"); + + CreateSessionReq newSession = CreateSessionReq.builder().name("new session").build(); + + Call session = knowledgeCenterService.createSession( + chatIdRes.getId(), + newSession + ); + SessionRes sessionRes = session.execute().body(); + log.info("sessionRes: {}", sessionRes); + log.info("sessionId: {}", sessionRes.getData().getId()); + log.info("=======》成功拿到session"); + + // todo 根据上一步拿到的aichat id 创建一个session // 构建请求参数 KeySensorCompletionReq.KeySensorCompletionReqBuilder reqBuilder = KeySensorCompletionReq.builder() - .question("请给我一个5个字") + .question("hello") .style("normal"); - Call call = knowledgeCenterService.getCompletions("Bearer ragflow-djN2QwZjc0YTNlNzExZjBiYjBlNDIwMT", reqBuilder.build(), "56a8f80aa85911f08a8a42010a8e0005"); + Call call = knowledgeCenterService.getCompletions(reqBuilder.build(), sessionRes.getData().getId()); CompletionRes completionRes = call.execute().body(); log.info("completionRes: {}", completionRes); return "test"; diff --git a/src/main/java/cn/bugstack/xfg/frame/service/IKnowledgeCenterService.java b/src/main/java/cn/bugstack/xfg/frame/service/IKnowledgeCenterService.java index fab2bc043f31694c40391d05efc7b893317fee54..5e8443b88e9c31a5aab681c2ac4df6284f83dee9 100644 --- a/src/main/java/cn/bugstack/xfg/frame/service/IKnowledgeCenterService.java +++ b/src/main/java/cn/bugstack/xfg/frame/service/IKnowledgeCenterService.java @@ -1,23 +1,49 @@ package cn.bugstack.xfg.frame.service; +import cn.bugstack.xfg.frame.domain.req.CreateChatReq; +import cn.bugstack.xfg.frame.domain.req.CreateSessionReq; import cn.bugstack.xfg.frame.domain.req.KeySensorCompletionReq; +import cn.bugstack.xfg.frame.domain.res.ChatIdRes; import cn.bugstack.xfg.frame.domain.res.CompletionRes; +import cn.bugstack.xfg.frame.domain.res.SessionRes; import retrofit2.Call; import retrofit2.http.*; public interface IKnowledgeCenterService { + /** + * 创建聊天助手 + * + * @param req 创建聊天请求参数 + * @return 聊天 ID 响应 + */ + @POST("api/v1/chats") + Call createChat( + @Body CreateChatReq req + ); + + /** + * 创建会话 + * + * @param chatId 聊天助手 ID + * @param req 创建会话请求参数 + * @return 会话响应 + */ + @POST("api/v1/chats/{chat_id}/sessions") + Call createSession( + @Path("chat_id") String chatId, + @Body CreateSessionReq req + ); /** * 对接 completion 接口 * - * @param authorization 认证头信息 * @param req 请求参数对象 + * @param chat_id 聊天 ID * @return 响应结果 */ @POST("api/v1/chats/{chat_id}/completions") Call getCompletions( - @Header("Authorization") String authorization, @Body KeySensorCompletionReq req, @Path("chat_id") String chat_id ); diff --git a/src/main/java/cn/bugstack/xfg/frame/service/IPromptService.java b/src/main/java/cn/bugstack/xfg/frame/service/IPromptService.java index 2e2310ec2293bf1f98a995dfc539e9d408d25c14..122bffc604f63bce3d0c79c70d2f50fe32efcc79 100644 --- a/src/main/java/cn/bugstack/xfg/frame/service/IPromptService.java +++ b/src/main/java/cn/bugstack/xfg/frame/service/IPromptService.java @@ -1,7 +1,15 @@ package cn.bugstack.xfg.frame.service; +import cn.bugstack.xfg.frame.common.AssistantType; +import cn.bugstack.xfg.frame.config.RagflowProperties; import cn.bugstack.xfg.frame.domain.req.KSReq; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.io.ClassPathResource; +import org.springframework.util.StreamUtils; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -13,6 +21,7 @@ import java.util.stream.Collectors; * @Description xx类 * @Date 2025/10/18 */ +@Slf4j public class IPromptService { private String buildBatchPrompt(List ksReqs){ StringBuilder batchPrompt = new StringBuilder(); @@ -66,4 +75,27 @@ public class IPromptService { , otherContextIdStr ); } + + + /** + * 从文件加载 prompt 内容 + * @param assistantType 助手类型 + * @return prompt 内容 + */ + public static String loadPromptFromFile(AssistantType assistantType) { + try { + String promptFilePath = assistantType.getPromptFilePath(); + ClassPathResource resource = new ClassPathResource(promptFilePath); + try (InputStream inputStream = resource.getInputStream()) { + String content = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8); + log.info("成功加载 {} 助手的 prompt 模板,文件路径: {}", assistantType.getDescription(), promptFilePath); + return content; + } + } catch (IOException e) { + log.error("加载 {} 助手的 prompt 模板失败: {}", assistantType.getDescription(), e.getMessage()); + throw new RuntimeException("加载 prompt 模板失败", e); + } + } + + } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 0e5468f61c32645de746d1fe2a395a785dfbf971..0eb11b6aa375fed1969459aec66bc907db950515 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -10,4 +10,24 @@ spring: mybatis: mapper-locations: classpath:/mybatis/mapper/*.xml - config-location: classpath:/mybatis/config/mybatis-config.xml \ No newline at end of file + config-location: classpath:/mybatis/config/mybatis-config.xml + +# RagFlow 配置 +ragflow: + api: + base-url: http://47.107.166.69/ + api-key: ragflow-IzZjQ5Y2ZhYWNkZjExZjA5MTA4MDI0Mm + prompts: + general: + file: prompts/general-assistant.txt + opener: "Hi! I'm your general assistant. What can I help you with today?" + empty-response: "Sorry! No relevant content was found in the knowledge base!" + technical: + file: prompts/technical-assistant.txt + opener: "Hello! I'm your technical assistant. What technical question can I help you solve?" + empty-response: "Sorry! No relevant technical information was found in the knowledge base!" + customer-service: + file: prompts/customer-service.txt + opener: "Hello! Welcome to our customer service. How may I assist you today?" + empty-response: "Sorry! I couldn't find relevant information to help with your inquiry. Please contact our support team for further assistance." + \ No newline at end of file diff --git a/target/classes/application.yml b/target/classes/application.yml index 0e5468f61c32645de746d1fe2a395a785dfbf971..0eb11b6aa375fed1969459aec66bc907db950515 100644 --- a/target/classes/application.yml +++ b/target/classes/application.yml @@ -10,4 +10,24 @@ spring: mybatis: mapper-locations: classpath:/mybatis/mapper/*.xml - config-location: classpath:/mybatis/config/mybatis-config.xml \ No newline at end of file + config-location: classpath:/mybatis/config/mybatis-config.xml + +# RagFlow 配置 +ragflow: + api: + base-url: http://47.107.166.69/ + api-key: ragflow-IzZjQ5Y2ZhYWNkZjExZjA5MTA4MDI0Mm + prompts: + general: + file: prompts/general-assistant.txt + opener: "Hi! I'm your general assistant. What can I help you with today?" + empty-response: "Sorry! No relevant content was found in the knowledge base!" + technical: + file: prompts/technical-assistant.txt + opener: "Hello! I'm your technical assistant. What technical question can I help you solve?" + empty-response: "Sorry! No relevant technical information was found in the knowledge base!" + customer-service: + file: prompts/customer-service.txt + opener: "Hello! Welcome to our customer service. How may I assist you today?" + empty-response: "Sorry! I couldn't find relevant information to help with your inquiry. Please contact our support team for further assistance." + \ No newline at end of file