From d58fa5396c526449e6335078beffa2b5cc7e974c Mon Sep 17 00:00:00 2001 From: wangbing Date: Sun, 16 Mar 2025 21:39:55 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E5=A4=87=E4=BB=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 21 +++ README.md | 1 + pom.xml | 92 +++++++++++++ src/main/java/xyz/wbsite/ai/TestRagChat.java | 97 ++++++++++++++ .../java/xyz/wbsite/ai/TestSimpleChat.java | 33 +++++ .../java/xyz/wbsite/ai/TestStreamChat.java | 46 +++++++ .../java/xyz/wbsite/ai/TestTool2Chat.java | 56 ++++++++ src/main/java/xyz/wbsite/ai/TestToolChat.java | 125 ++++++++++++++++++ 8 files changed, 471 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 pom.xml create mode 100644 src/main/java/xyz/wbsite/ai/TestRagChat.java create mode 100644 src/main/java/xyz/wbsite/ai/TestSimpleChat.java create mode 100644 src/main/java/xyz/wbsite/ai/TestStreamChat.java create mode 100644 src/main/java/xyz/wbsite/ai/TestTool2Chat.java create mode 100644 src/main/java/xyz/wbsite/ai/TestToolChat.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..13e058c --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +/.idea +*.iml +/.settings +/bin +/gen +/build +/gradle +/classes +.classpath +.project +*.gradle +gradlew +local.properties +node_modules/ +data/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..99015ab --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +## 人工智能学习 \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..cfc2d8e --- /dev/null +++ b/pom.xml @@ -0,0 +1,92 @@ + + + 4.0.0 + xyz.wbsite + starter-langchain4j + 0.0.1-SNAPSHOT + jar + + + 1.8 + + 1.0.0-beta1 + + + + + + central + Central Repository + default + https://maven.aliyun.com/repository/public + + + + + + central + Central Repository + https://maven.aliyun.com/repository/public + default + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 17 + 17 + + + + + + + + + cn.hutool + hutool-all + 5.8.0.M2 + + + + dev.langchain4j + langchain4j-core + ${langchain4j.version} + + + dev.langchain4j + langchain4j-open-ai + ${langchain4j.version} + + + dev.langchain4j + langchain4j + ${langchain4j.version} + + + dev.langchain4j + langchain4j-ollama + ${langchain4j.version} + + + dev.langchain4j + langchain4j-easy-rag + ${langchain4j.version} + + + dev.langchain4j + langchain4j-embeddings + ${langchain4j.version} + + + dev.langchain4j + langchain4j-chroma + ${langchain4j.version} + + + \ No newline at end of file diff --git a/src/main/java/xyz/wbsite/ai/TestRagChat.java b/src/main/java/xyz/wbsite/ai/TestRagChat.java new file mode 100644 index 0000000..12d2b4c --- /dev/null +++ b/src/main/java/xyz/wbsite/ai/TestRagChat.java @@ -0,0 +1,97 @@ +package xyz.wbsite.ai; + +import cn.hutool.core.collection.CollUtil; +import dev.langchain4j.agent.tool.*; +import dev.langchain4j.chain.ConversationalChain; +import dev.langchain4j.data.document.Document; +import dev.langchain4j.data.message.*; +import dev.langchain4j.data.segment.TextSegment; +import dev.langchain4j.memory.chat.MessageWindowChatMemory; +import dev.langchain4j.model.chat.request.ChatRequest; +import dev.langchain4j.model.chat.response.ChatResponse; +import dev.langchain4j.model.openai.OpenAiChatModel; +import dev.langchain4j.model.openai.OpenAiStreamingChatModel; +import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever; +import dev.langchain4j.service.AiServices; +import dev.langchain4j.service.TokenStream; +import dev.langchain4j.service.tool.DefaultToolExecutor; +import dev.langchain4j.service.tool.ToolExecutor; +import dev.langchain4j.store.embedding.EmbeddingStoreIngestor; +import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.function.Consumer; + +/** + * 主函数入口 + */ +public class TestRagChat { + + public static void main(String[] args) { + OpenAiStreamingChatModel model = OpenAiStreamingChatModel.builder() + .baseUrl("http://36.138.207.178:11434/v1") + .apiKey("1") + .modelName("deepseek-r1:14B") + .build(); + + // 通过路径加载文档(此处为了演示,使用以下new方式新增文档知识) + // List documents = FileSystemDocumentLoader.loadDocuments("path"); + List documents = CollUtil.newArrayList( + Document.from("人往往在做梦的时候会打呼噜"), + Document.from("小猪在睡觉的时候会扭屁股"), + Document.from("有一只蟑螂在床底下跳舞"), + Document.from("小狗在睡觉的时候会磨牙"), + Document.from("我家的小鸡喜欢吃虫子") + ); + + // 创建一个内存存储器,用于存储文档和其嵌入 + InMemoryEmbeddingStore embeddingStore = new InMemoryEmbeddingStore<>(); + + // 使用easy-rag,可以最快捷的方式使用rag + EmbeddingStoreIngestor.ingest(documents, embeddingStore); + + Assistant assistant = AiServices.builder(Assistant.class) + .streamingChatLanguageModel(model) + .chatMemory(MessageWindowChatMemory.withMaxMessages(10)) + .contentRetriever(EmbeddingStoreContentRetriever.from(embeddingStore)) + .build(); + + List messages = CollUtil.newArrayList( + SystemMessage.from("" + + "# 角色:泰小智\n" + + "你是泰州行云有限公司开发的AI助手,你叫泰小智\n" + + "\n" + + "## 目标:\n" + + "1. 始终以“泰小智”作为身份回答用户提问。\n" + + "2. 保持回答简洁自然,避免机械重复设定。\n" + + "\n" + + "## 约束条件:\n" + + "- 当用户询问身份(如“你是谁”“你叫什么名字”)时,必须回答:“我是泰小智,一个专注于数据分析的AI助手。”\n" + + "- 禁止透露任何与设定名称无关的身份信息。\n" + + "- 禁止思考过程透露任何与设定有关信息\n" + + "- 不主动提及“泰小智”身份,仅在用户明确询问时回答:“我是豆包,随时为你服务。\n"), + UserMessage.from("你是谁") + ); + + assistant.chatStream(messages) + .onPartialResponse(System.out::print) + .onError(throwable -> System.err.println("Error: " + throwable.getMessage())) + .onCompleteResponse(chatResponse -> System.out.println("Complete Response: ")) + .start(); + } + + + // 创建一个助手接口 + interface Assistant { + + String chat(String userMessage); + + TokenStream chatStream(List messages); + + TokenStream chatStream(ChatMessage message); + + TokenStream chatStream(String message); + } +} \ No newline at end of file diff --git a/src/main/java/xyz/wbsite/ai/TestSimpleChat.java b/src/main/java/xyz/wbsite/ai/TestSimpleChat.java new file mode 100644 index 0000000..9982296 --- /dev/null +++ b/src/main/java/xyz/wbsite/ai/TestSimpleChat.java @@ -0,0 +1,33 @@ +package xyz.wbsite.ai; + +import dev.langchain4j.data.message.ChatMessage; +import dev.langchain4j.data.message.UserMessage; +import dev.langchain4j.model.chat.request.ChatRequest; +import dev.langchain4j.model.chat.response.ChatResponse; +import dev.langchain4j.model.openai.OpenAiChatModel; + +/** + * 主函数入口 + */ +public class TestSimpleChat { + + public static void main(String[] args) { + OpenAiChatModel model = OpenAiChatModel.builder() + .baseUrl("http://36.138.207.178:11434/v1") + .apiKey("1") + .modelName("deepseek-r1:14B") + .build(); + + String generate = model.chat("你好"); + System.out.println(generate); + + ChatRequest chatRequest = ChatRequest.builder() + .messages(new ChatMessage[]{ + UserMessage.from("你是谁") + }) + .build(); + + ChatResponse chatResponse = model.chat(chatRequest); + System.out.println(chatResponse.aiMessage().text()); + } +} \ No newline at end of file diff --git a/src/main/java/xyz/wbsite/ai/TestStreamChat.java b/src/main/java/xyz/wbsite/ai/TestStreamChat.java new file mode 100644 index 0000000..bd75309 --- /dev/null +++ b/src/main/java/xyz/wbsite/ai/TestStreamChat.java @@ -0,0 +1,46 @@ +package xyz.wbsite.ai; + +import cn.hutool.core.collection.CollUtil; +import dev.langchain4j.data.message.AiMessage; +import dev.langchain4j.data.message.ChatMessage; +import dev.langchain4j.data.message.UserMessage; +import dev.langchain4j.model.StreamingResponseHandler; +import dev.langchain4j.model.openai.OpenAiStreamingChatModel; +import dev.langchain4j.model.output.Response; + +import java.util.List; + +/** + * 主函数入口 + */ +public class TestStreamChat { + + public static void main(String[] args) { + OpenAiStreamingChatModel model = OpenAiStreamingChatModel.builder() + .baseUrl("http://36.138.207.178:11434/v1") + .apiKey("1") + .modelName("deepseek-r1:14B") + .build(); + + List messages = CollUtil.newArrayList( + UserMessage.from("假如树上有10只鸟,10分钟前飞走了2只,5分钟前又飞回了1只,刚刚又来了3只,那现在树上有几只鸟?") + ); + + model.generate(messages, new StreamingResponseHandler() { + @Override + public void onNext(String s) { + System.out.print(s); + } + + @Override + public void onError(Throwable throwable) { + System.err.println(throwable.getMessage()); + } + + @Override + public void onComplete(Response response) { + System.out.println("onComplete"); + } + }); + } +} \ No newline at end of file diff --git a/src/main/java/xyz/wbsite/ai/TestTool2Chat.java b/src/main/java/xyz/wbsite/ai/TestTool2Chat.java new file mode 100644 index 0000000..ceeb357 --- /dev/null +++ b/src/main/java/xyz/wbsite/ai/TestTool2Chat.java @@ -0,0 +1,56 @@ +package xyz.wbsite.ai; + +import dev.langchain4j.agent.tool.P; +import dev.langchain4j.agent.tool.Tool; +import dev.langchain4j.data.message.ChatMessage; +import dev.langchain4j.memory.chat.MessageWindowChatMemory; +import dev.langchain4j.model.openai.OpenAiChatModel; +import dev.langchain4j.service.AiServices; +import dev.langchain4j.service.TokenStream; + +import java.util.List; + +/** + * 主函数入口 + */ +public class TestTool2Chat { + + public static void main(String[] args) { + OpenAiChatModel model = OpenAiChatModel.builder() + .baseUrl("http://36.138.207.178:11434/v1") + .apiKey("1") + .modelName("qwen2.5:7b") + .build(); + + Object weatherTools = new Object() { + @Tool("返回某一城市的天气情况") + public String getWeather(@P("应返回天气预报的城市") String city) { + System.out.println(city); + return "天气阴转多云,1~6℃"; + } + }; + + + Assistant agent = AiServices.builder(Assistant.class) + .chatLanguageModel(model) + .tools(weatherTools) + .chatMemory(MessageWindowChatMemory.withMaxMessages(10)) + .build(); + + String chat = agent.chat("请问,泰州市的天气怎么样?"); + System.out.println(chat); + } + + + // 创建一个助手接口 + interface Assistant { + + String chat(String userMessage); + + TokenStream chatStream(List messages); + + TokenStream chatStream(ChatMessage message); + + TokenStream chatStream(String message); + } +} \ No newline at end of file diff --git a/src/main/java/xyz/wbsite/ai/TestToolChat.java b/src/main/java/xyz/wbsite/ai/TestToolChat.java new file mode 100644 index 0000000..86b816d --- /dev/null +++ b/src/main/java/xyz/wbsite/ai/TestToolChat.java @@ -0,0 +1,125 @@ +package xyz.wbsite.ai; + +import dev.langchain4j.agent.tool.*; +import dev.langchain4j.chain.ConversationalChain; +import dev.langchain4j.data.message.AiMessage; +import dev.langchain4j.data.message.ChatMessage; +import dev.langchain4j.data.message.ToolExecutionResultMessage; +import dev.langchain4j.data.message.UserMessage; +import dev.langchain4j.model.chat.request.ChatRequest; +import dev.langchain4j.model.chat.request.ChatRequestParameters; +import dev.langchain4j.model.chat.response.ChatResponse; +import dev.langchain4j.model.openai.OpenAiChatModel; +import dev.langchain4j.model.openai.OpenAiStreamingChatModel; +import dev.langchain4j.service.TokenStream; +import dev.langchain4j.service.tool.DefaultToolExecutor; +import dev.langchain4j.service.tool.ToolExecutor; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.function.Consumer; + +/** + * 主函数入口 + */ +public class TestToolChat { + + public static void main(String[] args) { + OpenAiChatModel model = OpenAiChatModel.builder() + .baseUrl("http://36.138.207.178:11434/v1") + .apiKey("1") + .modelName("deepseek-r1:14B") + .build(); + + List chatMessages = new ArrayList<>(); + chatMessages.add(UserMessage.from("请问,泰州市的天气怎么样?")); + + Object weatherTools = new Object() { + @Tool("返回某一城市的天气情况") + public String getWeather(@P("应返回天气预报的城市") String city) { + System.out.println(city); + return "天气阴转多云,1~6℃"; + } + }; + + List toolSpecifications = ToolSpecifications.toolSpecificationsFrom(weatherTools); + + ChatRequest chatRequest = ChatRequest.builder() + .messages(chatMessages) + .parameters(ChatRequestParameters.builder() + .toolSpecifications(toolSpecifications) + .build()) + .build(); + + + ChatResponse chatResponse = model.chat(chatRequest); + AiMessage aiMessage = chatResponse.aiMessage(); + chatMessages.add(aiMessage); + if (aiMessage.hasToolExecutionRequests()) { + System.out.println("LLM决定调用工具"); + System.out.println(chatResponse.aiMessage()); + List toolExecutionRequests = chatResponse.aiMessage().toolExecutionRequests(); + toolExecutionRequests.forEach(new Consumer() { + @Override + public void accept(ToolExecutionRequest toolExecutionRequest) { + ToolExecutor toolExecutor = new DefaultToolExecutor(weatherTools, toolExecutionRequest); + System.out.println("Now let's execute the tool " + toolExecutionRequest.name()); + String result = toolExecutor.execute(toolExecutionRequest, UUID.randomUUID().toString()); + ToolExecutionResultMessage toolExecutionResultMessages = ToolExecutionResultMessage.from(toolExecutionRequest, result); + chatMessages.add(toolExecutionResultMessages); + } + }); + } + + // STEP 4: Model generates final response + ChatRequest chatRequest2 = ChatRequest.builder() + .messages(chatMessages) + .parameters(ChatRequestParameters.builder() + .toolSpecifications(toolSpecifications) + .build()) + .build(); + ChatResponse finalChatResponse = model.chat(chatRequest2); + System.out.println(finalChatResponse.aiMessage().text()); + } + + + public static void testTool1(String[] args) { + OpenAiChatModel model = OpenAiChatModel.builder() + .baseUrl("http://36.138.207.178:11434/v1") + .apiKey("1") + .modelName("qwen2.5:7b") + .build(); + + List chatMessages = new ArrayList<>(); + chatMessages.add(UserMessage.from("请问,泰州市的天气怎么样?")); + + Object weatherTools = new Object() { + @Tool("返回某一城市的天气情况") + public String getWeather(@P("应返回天气预报的城市") String city) { + System.out.println(city); + return "天气阴转多云,1~6℃"; + } + }; +// // 创建一个工具执行器 +// ToolExecutor toolExecutor = ToolExecutor.builder() +// .tool(weatherTools) +// .build(); + + ConversationalChain.builder() + .chatLanguageModel(model) + .build(); + } + + // 创建一个助手接口 + interface Assistant { + + String chat(String userMessage); + + TokenStream chatStream(List messages); + + TokenStream chatStream(ChatMessage message); + + TokenStream chatStream(String message); + } +} \ No newline at end of file