feat(chat): 优化提示词,时间参数直接放在提示词中
This commit is contained in:
@@ -16,11 +16,6 @@
|
|||||||
<groupId>com.lanyuanxiaoyao</groupId>
|
<groupId>com.lanyuanxiaoyao</groupId>
|
||||||
<artifactId>service-ai-core</artifactId>
|
<artifactId>service-ai-core</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.ai</groupId>
|
|
||||||
<artifactId>spring-ai-starter-model-openai</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.ai</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-starter-model-deepseek</artifactId>
|
<artifactId>spring-ai-starter-model-deepseek</artifactId>
|
||||||
|
|||||||
@@ -3,9 +3,10 @@ package com.lanyuanxiaoyao.service.ai.chat.controller;
|
|||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.lanyuanxiaoyao.service.ai.chat.entity.MessageVO;
|
import com.lanyuanxiaoyao.service.ai.chat.entity.MessageVO;
|
||||||
import com.lanyuanxiaoyao.service.ai.chat.tools.DatetimeTools;
|
|
||||||
import com.lanyuanxiaoyao.service.forest.service.KnowledgeService;
|
import com.lanyuanxiaoyao.service.forest.service.KnowledgeService;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import org.eclipse.collections.api.list.ImmutableList;
|
import org.eclipse.collections.api.list.ImmutableList;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -35,6 +36,7 @@ import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
|||||||
@RequestMapping("chat")
|
@RequestMapping("chat")
|
||||||
public class ChatController {
|
public class ChatController {
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ChatController.class);
|
private static final Logger logger = LoggerFactory.getLogger(ChatController.class);
|
||||||
|
private final static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
private static final String ROLE_ASSISTANT = "assistant";
|
private static final String ROLE_ASSISTANT = "assistant";
|
||||||
private static final String ROLE_USER = "user";
|
private static final String ROLE_USER = "user";
|
||||||
|
|
||||||
@@ -48,26 +50,29 @@ public class ChatController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ChatClient.ChatClientRequestSpec buildRequest(Long knowledgeId, ImmutableList<MessageVO> messages) {
|
private ChatClient.ChatClientRequestSpec buildRequest(Long knowledgeId, ImmutableList<MessageVO> messages) {
|
||||||
var systemPromptBuilder = new StringBuilder();
|
var builder = StrUtil.builder()
|
||||||
systemPromptBuilder.append("""
|
.append(StrUtil.format("""
|
||||||
你是一名专业的AI运维助手,负责“Hudi数据同步服务平台”的运维工作;
|
你是一名专业的AI运维助手,负责“Hudi数据同步服务平台”的运维工作;
|
||||||
你将会友好地帮助用户解答关于该平台运维工作的问题,你会尽可能通过各种方式获取知识和数据来解答;
|
你将会友好地帮助用户解答关于该平台运维工作的问题,你会尽可能通过各种方式获取知识和数据来解答;
|
||||||
对于无法通过已有知识回答的问题,你会提示用户你无法解答该问题,而不是虚构不存在的数据或答案;
|
对于无法通过已有知识回答的问题,你会提示用户你无法解答该问题,而不是虚构不存在的数据或答案;
|
||||||
对于与该平台无关的问题,你会委婉地拒绝用户,并提示无法回答;
|
对于与该平台无关的问题,你会委婉地拒绝用户,并提示无法回答;
|
||||||
你将始终在中文语境下进行对话。
|
你将始终在中文语境下进行对话。
|
||||||
""");
|
当前时间为:{}
|
||||||
|
|
||||||
|
""", LocalDateTime.now().format(formatter)));
|
||||||
if (ObjectUtil.isNotNull(knowledgeId)) {
|
if (ObjectUtil.isNotNull(knowledgeId)) {
|
||||||
var vo = messages.select(message -> StrUtil.equals(message.getRole(), "user")).getLastOptional().orElseThrow();
|
var vo = messages.select(message -> StrUtil.equals(message.getRole(), "user")).getLastOptional().orElseThrow();
|
||||||
var documents = knowledgeService.query(knowledgeId, vo.getContent());
|
var documents = knowledgeService.query(knowledgeId, vo.getContent(), 0.5);
|
||||||
logger.info("Knowledge id:{}, content:{}", knowledgeId, vo.getContent());
|
|
||||||
if (ObjectUtil.isNotEmpty(documents)) {
|
if (ObjectUtil.isNotEmpty(documents)) {
|
||||||
systemPromptBuilder.append("以下是与用户问题有关的外部知识,优先利用该知识回答用户的提问:\n");
|
builder.append(StrUtil.format("""
|
||||||
systemPromptBuilder.append(documents.makeString("\n"));
|
以下是与用户问题有关的外部知识,优先利用该知识回答用户的提问:
|
||||||
|
{}
|
||||||
|
|
||||||
|
""", documents.makeString("\n")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return chatClient.prompt()
|
return chatClient.prompt()
|
||||||
.system(systemPromptBuilder.toString())
|
.system(builder.toString())
|
||||||
.tools(new DatetimeTools())
|
|
||||||
.messages(
|
.messages(
|
||||||
messages
|
messages
|
||||||
.collect(message -> StrUtil.equals(message.getRole(), ROLE_ASSISTANT)
|
.collect(message -> StrUtil.equals(message.getRole(), ROLE_ASSISTANT)
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
package com.lanyuanxiaoyao.service.ai.chat.tools;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.time.format.DateTimeFormatter;
|
|
||||||
import org.springframework.ai.tool.annotation.Tool;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author lanyuanxiaoyao
|
|
||||||
* @version 20250516
|
|
||||||
*/
|
|
||||||
public class DatetimeTools {
|
|
||||||
private final static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
||||||
|
|
||||||
@Tool(description = "获取当前日期和时间")
|
|
||||||
public String getCurrentDateTime() {
|
|
||||||
return LocalDateTime.now().format(formatter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
package com.lanyuanxiaoyao.service.ai.chat;
|
|
||||||
|
|
||||||
import org.springframework.ai.chat.client.ChatClient;
|
|
||||||
import org.springframework.ai.openai.OpenAiChatModel;
|
|
||||||
import org.springframework.ai.openai.OpenAiChatOptions;
|
|
||||||
import org.springframework.ai.openai.api.OpenAiApi;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author lanyuanxiaoyao
|
|
||||||
* @version 20250514
|
|
||||||
*/
|
|
||||||
public class TestChat {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
ChatClient client = ChatClient.builder(
|
|
||||||
OpenAiChatModel.builder()
|
|
||||||
.openAiApi(
|
|
||||||
OpenAiApi.builder()
|
|
||||||
.baseUrl("http://132.121.206.65:10086")
|
|
||||||
.apiKey("*XMySqV%>hR&v>>g*NwCs3tpQ5FVMFEF2VHVTj<MYQd$&@$sY7CgqNyea4giJi4")
|
|
||||||
.build()
|
|
||||||
)
|
|
||||||
.defaultOptions(
|
|
||||||
OpenAiChatOptions.builder()
|
|
||||||
.model("Qwen3-1.7")
|
|
||||||
.build()
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
)
|
|
||||||
.build();
|
|
||||||
String content = client.prompt()
|
|
||||||
.user("你好")
|
|
||||||
.call()
|
|
||||||
.content();
|
|
||||||
System.out.println(content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
package com.lanyuanxiaoyao.service.ai.chat;
|
||||||
|
|
||||||
|
import java.net.http.HttpClient;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import org.springframework.ai.chat.client.ChatClient;
|
||||||
|
import org.springframework.ai.deepseek.DeepSeekChatModel;
|
||||||
|
import org.springframework.ai.deepseek.DeepSeekChatOptions;
|
||||||
|
import org.springframework.ai.deepseek.api.DeepSeekApi;
|
||||||
|
import org.springframework.ai.tool.ToolCallback;
|
||||||
|
import org.springframework.ai.tool.definition.ToolDefinition;
|
||||||
|
import org.springframework.http.client.JdkClientHttpRequestFactory;
|
||||||
|
import org.springframework.http.client.reactive.JdkClientHttpConnector;
|
||||||
|
import org.springframework.web.client.RestClient;
|
||||||
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
|
import reactor.core.Disposable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lanyuanxiaoyao
|
||||||
|
* @version 20250514
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("NullableProblems")
|
||||||
|
public class TestSpringAIToolChat {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
ChatClient client = ChatClient.builder(
|
||||||
|
DeepSeekChatModel.builder()
|
||||||
|
.deepSeekApi(
|
||||||
|
DeepSeekApi.builder()
|
||||||
|
.baseUrl("http://132.121.206.65:10086/v1")
|
||||||
|
.apiKey("*XMySqV%>hR&v>>g*NwCs3tpQ5FVMFEF2VHVTj<MYQd$&@$sY7CgqNyea4giJi4")
|
||||||
|
.restClientBuilder(restClientBuilder())
|
||||||
|
.webClientBuilder(webClientBuilder())
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.defaultOptions(
|
||||||
|
DeepSeekChatOptions.builder()
|
||||||
|
.model("Qwen3-1.7-vllm")
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
ToolCallback datetimeTool = new ToolCallback() {
|
||||||
|
@Override
|
||||||
|
public ToolDefinition getToolDefinition() {
|
||||||
|
return ToolDefinition.builder()
|
||||||
|
.name("getCurrentTime")
|
||||||
|
.description("获取当前日期和时间")
|
||||||
|
// language=JSON
|
||||||
|
.inputSchema("""
|
||||||
|
{"type": null}
|
||||||
|
""")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String call(String toolInput) {
|
||||||
|
return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Disposable disposable = client.prompt()
|
||||||
|
.user("当前时间?")
|
||||||
|
.toolCallbacks(datetimeTool)
|
||||||
|
.stream()
|
||||||
|
.content()
|
||||||
|
.subscribe(System.out::println);
|
||||||
|
while (!disposable.isDisposed()) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HttpClient httpClient() {
|
||||||
|
return HttpClient.newBuilder()
|
||||||
|
.version(HttpClient.Version.HTTP_1_1)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RestClient.Builder restClientBuilder() {
|
||||||
|
return RestClient.builder()
|
||||||
|
.requestFactory(new JdkClientHttpRequestFactory(httpClient()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WebClient.Builder webClientBuilder() {
|
||||||
|
return WebClient.builder()
|
||||||
|
.clientConnector(new JdkClientHttpConnector(httpClient()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,5 +18,8 @@ public interface KnowledgeService {
|
|||||||
ImmutableList<String> query(@Query("id") Long id, @Body String text);
|
ImmutableList<String> query(@Query("id") Long id, @Body String text);
|
||||||
|
|
||||||
@Post(value = "/query", contentType = "plain/text")
|
@Post(value = "/query", contentType = "plain/text")
|
||||||
ImmutableList<String> query(@Query("id") Long id, @Query("limit") Integer limit, @Query("threshold") Double threshold, @Body String text);
|
ImmutableList<String> query(@Query("id") Long id, @Body String text, @Query("threshold") Double threshold);
|
||||||
|
|
||||||
|
@Post(value = "/query", contentType = "plain/text")
|
||||||
|
ImmutableList<String> query(@Query("id") Long id, @Body String text, @Query("limit") Integer limit, @Query("threshold") Double threshold);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user