commit 0d15e2078071161dcd70c864a6d3fe21f30a5eb2
Author: userpu <565599455@qq.com>
Date: Wed Dec 17 19:47:14 2025 +0800
Initial commit
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5ff6309
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..7d05e99
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,10 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# 依赖于环境的 Maven 主目录路径
+/mavenHomeManager.xml
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml
new file mode 100644
index 0000000..3508924
--- /dev/null
+++ b/.idea/dataSources.xml
@@ -0,0 +1,17 @@
+
+
+
+
+ mysql.8
+ true
+ com.mysql.cj.jdbc.Driver
+ jdbc:mysql://localhost:3306/langchain4j
+
+
+
+
+
+ $ProjectFileDir$
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..eb5644e
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..82dbec8
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/langchain4j-ai-helloworld/pom.xml b/langchain4j-ai-helloworld/pom.xml
new file mode 100644
index 0000000..82ee066
--- /dev/null
+++ b/langchain4j-ai-helloworld/pom.xml
@@ -0,0 +1,46 @@
+
+
+ 4.0.0
+
+ com.iwe3
+ langchain4j-ai-java
+ 1.0-SNAPSHOT
+
+
+ langchain4j-ai-helloworld
+ jar
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ dev.langchain4j
+ langchain4j-open-ai
+
+
+ dev.langchain4j
+ langchain4j
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
\ No newline at end of file
diff --git a/langchain4j-ai-helloworld/src/main/java/com/iwe3/langchain4j/HelloworldApplication.java b/langchain4j-ai-helloworld/src/main/java/com/iwe3/langchain4j/HelloworldApplication.java
new file mode 100644
index 0000000..2d2fb57
--- /dev/null
+++ b/langchain4j-ai-helloworld/src/main/java/com/iwe3/langchain4j/HelloworldApplication.java
@@ -0,0 +1,12 @@
+package com.iwe3.langchain4j;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class HelloworldApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(HelloworldApplication.class,args);
+ }
+}
diff --git a/langchain4j-ai-helloworld/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java b/langchain4j-ai-helloworld/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
new file mode 100644
index 0000000..f2fcc21
--- /dev/null
+++ b/langchain4j-ai-helloworld/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
@@ -0,0 +1,19 @@
+package com.iwe3.langchain4j.config;
+
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.openai.OpenAiChatModel;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class LLMConfig {
+ @Bean
+ public ChatModel chatModelQwen(){
+ return OpenAiChatModel.builder()
+ .apiKey(System.getenv("DASH_SCOPE_API_KEY"))
+ .modelName("qwen-plus")
+ .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
+ .build();
+ }
+
+}
diff --git a/langchain4j-ai-helloworld/src/main/java/com/iwe3/langchain4j/controller/LangChain4JController.java b/langchain4j-ai-helloworld/src/main/java/com/iwe3/langchain4j/controller/LangChain4JController.java
new file mode 100644
index 0000000..c1259a6
--- /dev/null
+++ b/langchain4j-ai-helloworld/src/main/java/com/iwe3/langchain4j/controller/LangChain4JController.java
@@ -0,0 +1,26 @@
+package com.iwe3.langchain4j.controller;
+
+import dev.langchain4j.model.chat.ChatModel;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@Slf4j
+public class LangChain4JController
+{
+ // http://localhost:9001/langchain4j/hello?question=如何学习LangChain4J
+
+ @Resource
+ private ChatModel chatModel;
+
+ @GetMapping(value = "/langchain4j/hello")
+ public String hello(@RequestParam(value = "question",defaultValue = "你是谁") String question)
+ {
+ var result = chatModel.chat(question);
+ System.out.println("通过langchain4j调用模型返回结果:\n"+result);
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/langchain4j-ai-helloworld/src/main/resources/application.yml b/langchain4j-ai-helloworld/src/main/resources/application.yml
new file mode 100644
index 0000000..08e8cce
--- /dev/null
+++ b/langchain4j-ai-helloworld/src/main/resources/application.yml
@@ -0,0 +1,5 @@
+server:
+ port: 9001
+spring:
+ application:
+ name: langchain4j-ai-helloworld
\ No newline at end of file
diff --git a/langchain4j-ai-image/pom.xml b/langchain4j-ai-image/pom.xml
new file mode 100644
index 0000000..87f72fe
--- /dev/null
+++ b/langchain4j-ai-image/pom.xml
@@ -0,0 +1,49 @@
+
+
+ 4.0.0
+
+ com.iwe3
+ langchain4j-ai-java
+ 1.0-SNAPSHOT
+
+
+ langchain4j-ai-image
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ dev.langchain4j
+ langchain4j-community-dashscope-spring-boot-starter
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ dev.langchain4j
+ langchain4j-open-ai-spring-boot-starter
+ 1.9.1-beta17
+
+
+
+ dev.langchain4j
+ langchain4j-spring-boot-starter
+ 1.9.1-beta17
+
+
+
\ No newline at end of file
diff --git a/langchain4j-ai-image/src/main/java/com/iwe3/langchain4j/ImageApplication.java b/langchain4j-ai-image/src/main/java/com/iwe3/langchain4j/ImageApplication.java
new file mode 100644
index 0000000..7aa5cb4
--- /dev/null
+++ b/langchain4j-ai-image/src/main/java/com/iwe3/langchain4j/ImageApplication.java
@@ -0,0 +1,13 @@
+package com.iwe3.langchain4j;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class ImageApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ImageApplication.class,args);
+ }
+
+}
diff --git a/langchain4j-ai-image/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java b/langchain4j-ai-image/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
new file mode 100644
index 0000000..0de0cdf
--- /dev/null
+++ b/langchain4j-ai-image/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
@@ -0,0 +1,34 @@
+package com.iwe3.langchain4j.config;
+
+import dev.langchain4j.community.model.dashscope.WanxImageModel;
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.openai.OpenAiChatModel;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class LLMConfig
+{
+ @Bean
+ public ChatModel ImageModel() {
+ return OpenAiChatModel.builder()
+ .apiKey(System.getenv("DASH_SCOPE_API_KEY"))
+ //qwen-vl-max 是一个多模态大模型,支持图片和文本的结合输入,适用于视觉-语言任务。
+ .modelName("qwen-vl-max")
+ .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
+ .build();
+ }
+
+ /**
+ * @Description: 测试通义万象来实现图片生成,
+ * 知识出处,https://help.aliyun.com/zh/model-studio/text-to-image
+ */
+ @Bean
+ public WanxImageModel wanxImageModel()
+ {
+ return WanxImageModel.builder()
+ .apiKey(System.getenv("DASH_SCOPE_API_KEY"))
+ .modelName("wanx2.1-t2i-turbo") //图片生成 https://help.aliyun.com/zh/model-studio/text-to-image
+ .build();
+ }
+}
diff --git a/langchain4j-ai-image/src/main/java/com/iwe3/langchain4j/controller/ImageModelController.java b/langchain4j-ai-image/src/main/java/com/iwe3/langchain4j/controller/ImageModelController.java
new file mode 100644
index 0000000..cbd8c03
--- /dev/null
+++ b/langchain4j-ai-image/src/main/java/com/iwe3/langchain4j/controller/ImageModelController.java
@@ -0,0 +1,62 @@
+package com.iwe3.langchain4j.controller;
+
+import dev.langchain4j.data.message.ImageContent;
+import dev.langchain4j.data.message.TextContent;
+import dev.langchain4j.data.message.UserMessage;
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.chat.response.ChatResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.io.Resource;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.io.IOException;
+import java.util.Base64;
+
+@RestController
+@Slf4j
+public class ImageModelController
+{
+ @Autowired
+ private ChatModel ImageModel;
+
+ @Value("classpath:static/imgs/1.png")
+ private Resource resource;//import org.springframework.core.io.Resource;
+
+ /**
+ * @Description:
+ * 通过Base64编码将图片转化为字符串
+ * 结合ImageContent和TextContent形成UserMessage一起发送到模型进行处理。
+ *
+ *测试地址:http://localhost:9005/lc4j/image/call
+ */
+ @GetMapping(value = "/lc4j/image/call")
+ public String readImageContent() throws IOException
+ {
+ String result = null;
+
+ //第一步,图片转码:通过Base64编码将图片转化为字符串
+ byte[] byteArray = resource.getContentAsByteArray();
+ String base64Data = Base64.getEncoder().encodeToString(byteArray);
+
+ //第二步,提示词指定:结合ImageContent和TextContent一起发送到模型进行处理。
+ UserMessage userMessage = UserMessage.from(
+ TextContent.from("她是谁?"),
+ ImageContent.from(base64Data, "image/jpg")
+ );
+ //第三步,API调用:使用OpenAiChatModel来构建请求,并通过chat()方法调用模型。
+ //请求内容包括文本提示和图片,模型会根据输入返回分析结果。
+ ChatResponse chatResponse = ImageModel.chat(userMessage);
+
+ //第四步,解析与输出:从ChatResponse中获取AI大模型的回复,打印出处理后的结果。
+ result = chatResponse.aiMessage().text();
+
+ //后台打印
+ System.out.println(result);
+
+ //返回前台
+ return result;
+ }
+}
diff --git a/langchain4j-ai-image/src/main/java/com/iwe3/langchain4j/controller/WanxImageModelController.java b/langchain4j-ai-image/src/main/java/com/iwe3/langchain4j/controller/WanxImageModelController.java
new file mode 100644
index 0000000..03512cc
--- /dev/null
+++ b/langchain4j-ai-image/src/main/java/com/iwe3/langchain4j/controller/WanxImageModelController.java
@@ -0,0 +1,71 @@
+package com.iwe3.langchain4j.controller;
+
+import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesis;
+import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesisParam;
+import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesisResult;
+import com.alibaba.dashscope.exception.ApiException;
+import com.alibaba.dashscope.exception.NoApiKeyException;
+import com.alibaba.dashscope.utils.JsonUtils;
+import dev.langchain4j.community.model.dashscope.WanxImageModel;
+import dev.langchain4j.data.image.Image;
+import dev.langchain4j.model.output.Response;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.io.IOException;
+
+
+@RestController
+@Slf4j
+public class WanxImageModelController
+{
+ @Autowired
+ private WanxImageModel wanxImageModel;
+
+ // http://localhost:9005/lc4j/image/create
+ @GetMapping(value = "/lc4j/image/create")
+ public String createImageContent() throws IOException
+ {
+ System.out.println(wanxImageModel);
+ var imageResponse = wanxImageModel.generate("美女");
+ System.out.println(imageResponse.content().url());
+ return imageResponse.content().url().toString();
+
+ }
+
+ // http://localhost:9005/lc4j/image/create2
+ @GetMapping(value = "/lc4j/image/create2")
+ public String createImageContent2() throws IOException
+ {
+
+ var prompt = "近景镜头,18岁的中国女孩,古代服饰,圆脸,正面看着镜头," +
+ "民族优雅的服装,商业摄影,室外,电影级光照,半身特写,精致的淡妆,锐利的边缘。";
+ var param =
+ ImageSynthesisParam.builder()
+ .apiKey(System.getenv("DASH_SCOPE_API_KEY"))
+ .model(ImageSynthesis.Models.WANX_V1)
+ .prompt(prompt)
+ .style("")
+ .n(1)
+ .size("1024*1024")
+ .build();
+
+ var imageSynthesis = new ImageSynthesis();
+ ImageSynthesisResult result = null;
+
+ try {
+ System.out.println("---sync call, please wait a moment----");
+
+ result = imageSynthesis.call(param);
+ } catch (ApiException | NoApiKeyException e){
+ throw new RuntimeException(e.getMessage());
+ }
+
+
+ System.out.println(JsonUtils.toJson(result));
+
+ return JsonUtils.toJson(result);
+ }
+}
diff --git a/langchain4j-ai-image/src/main/resources/application.yml b/langchain4j-ai-image/src/main/resources/application.yml
new file mode 100644
index 0000000..fe4ccc6
--- /dev/null
+++ b/langchain4j-ai-image/src/main/resources/application.yml
@@ -0,0 +1,5 @@
+server:
+ port: 9005
+spring:
+ application:
+ name: langchain4j-ai-image
\ No newline at end of file
diff --git a/langchain4j-ai-image/src/main/resources/static/imgs/1.png b/langchain4j-ai-image/src/main/resources/static/imgs/1.png
new file mode 100644
index 0000000..d3472d7
Binary files /dev/null and b/langchain4j-ai-image/src/main/resources/static/imgs/1.png differ
diff --git a/langchain4j-ai-image/src/main/resources/static/imgs/2.png b/langchain4j-ai-image/src/main/resources/static/imgs/2.png
new file mode 100644
index 0000000..7598a5b
Binary files /dev/null and b/langchain4j-ai-image/src/main/resources/static/imgs/2.png differ
diff --git a/langchain4j-ai-low-high-api/pom.xml b/langchain4j-ai-low-high-api/pom.xml
new file mode 100644
index 0000000..9d79456
--- /dev/null
+++ b/langchain4j-ai-low-high-api/pom.xml
@@ -0,0 +1,42 @@
+
+
+ 4.0.0
+
+ com.iwe3
+ langchain4j-ai-java
+ 1.0-SNAPSHOT
+
+
+ langchain4j-ai-low-high-api
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ dev.langchain4j
+ langchain4j-open-ai-spring-boot-starter
+ 1.9.1-beta17
+
+
+
+ dev.langchain4j
+ langchain4j-spring-boot-starter
+ 1.9.1-beta17
+
+
+
\ No newline at end of file
diff --git a/langchain4j-ai-low-high-api/src/main/java/com/iwe3/langchain4j/LowHighApplication.java b/langchain4j-ai-low-high-api/src/main/java/com/iwe3/langchain4j/LowHighApplication.java
new file mode 100644
index 0000000..3ab76b3
--- /dev/null
+++ b/langchain4j-ai-low-high-api/src/main/java/com/iwe3/langchain4j/LowHighApplication.java
@@ -0,0 +1,12 @@
+package com.iwe3.langchain4j;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class LowHighApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(LowHighApplication.class,args);
+ }
+}
diff --git a/langchain4j-ai-low-high-api/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java b/langchain4j-ai-low-high-api/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
new file mode 100644
index 0000000..b9e868b
--- /dev/null
+++ b/langchain4j-ai-low-high-api/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
@@ -0,0 +1,37 @@
+package com.iwe3.langchain4j.config;
+
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.openai.OpenAiChatModel;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class LLMConfig {
+
+ @Bean(name = "qwen")
+ public ChatModel chatModelQwen(){
+ /*大模型3件套:apikey ,model-name,base-url */
+ return OpenAiChatModel.builder()
+ .apiKey(System.getenv("DASH_SCOPE_API_KEY"))
+ .modelName("qwen-plus")
+ .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
+ .build();
+ }
+
+ /**
+ * @Description:
+ * 知识出处,https://api-docs.deepseek.com/zh-cn/
+ */
+ @Bean(name = "deepseek")
+ public ChatModel chatModelDeepSeek()
+ {
+ return
+ OpenAiChatModel.builder()
+ .apiKey(System.getenv("DEEP_SEEK_API_KEY"))
+ .modelName("deepseek-chat")
+ //.modelName("deepseek-reasoner")
+ .baseUrl("https://api.deepseek.com/v1")
+ .build();
+ }
+
+}
diff --git a/langchain4j-ai-low-high-api/src/main/java/com/iwe3/langchain4j/controller/HighLevelController.java b/langchain4j-ai-low-high-api/src/main/java/com/iwe3/langchain4j/controller/HighLevelController.java
new file mode 100644
index 0000000..482815f
--- /dev/null
+++ b/langchain4j-ai-low-high-api/src/main/java/com/iwe3/langchain4j/controller/HighLevelController.java
@@ -0,0 +1,21 @@
+package com.iwe3.langchain4j.controller;
+
+import com.iwe3.langchain4j.service.ChatAssistant;
+import jakarta.annotation.Resource;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class HighLevelController {
+
+ @Resource
+ private ChatAssistant chatAssistant;
+
+ // http://localhost:9003/lc4j/boot/declarative?prompt=我是谁
+ @GetMapping(value = "/lc4j/boot/declarative")
+ public String declarative(@RequestParam(value = "prompt", defaultValue = "你是谁") String prompt)
+ {
+ return chatAssistant.chat(prompt);
+ }
+}
diff --git a/langchain4j-ai-low-high-api/src/main/java/com/iwe3/langchain4j/controller/LowLevelController.java b/langchain4j-ai-low-high-api/src/main/java/com/iwe3/langchain4j/controller/LowLevelController.java
new file mode 100644
index 0000000..3176975
--- /dev/null
+++ b/langchain4j-ai-low-high-api/src/main/java/com/iwe3/langchain4j/controller/LowLevelController.java
@@ -0,0 +1,41 @@
+package com.iwe3.langchain4j.controller;
+
+import dev.langchain4j.data.message.UserMessage;
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.chat.response.ChatResponse;
+import dev.langchain4j.model.output.TokenUsage;
+import jakarta.annotation.Resource;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class LowLevelController {
+
+ @Resource(name = "qwen")
+ private ChatModel chatModel;
+
+ // http://localhost:9003/lc4j/lowapi/api01?prompt=我是谁
+ @GetMapping(value = "/lc4j/lowapi/api01")
+ public String api01(@RequestParam(value = "prompt", defaultValue = "你是谁") String prompt)
+ {
+ return chatModel.chat(prompt);
+ }
+
+ // http://localhost:9003/lc4j/lowapi/api02?prompt=我是谁
+ @GetMapping(value = "/lc4j/lowapi/api02")
+ public String api02(@RequestParam(value = "prompt", defaultValue = "你是谁") String prompt)
+ {
+ ChatResponse chatResponse = chatModel.chat(UserMessage.from(prompt));
+
+ String result = chatResponse.aiMessage().text();
+ System.out.println("通过调用大模型返回结果:"+result);
+
+ // Token 用量计算的底层api
+ TokenUsage tokenUsage = chatResponse.tokenUsage();
+ System.out.println("本次调用消耗的token:"+tokenUsage);
+ result = result +"\t\n"+tokenUsage;
+
+ return result;
+ }
+}
diff --git a/langchain4j-ai-low-high-api/src/main/java/com/iwe3/langchain4j/service/ChatAssistant.java b/langchain4j-ai-low-high-api/src/main/java/com/iwe3/langchain4j/service/ChatAssistant.java
new file mode 100644
index 0000000..5fdd791
--- /dev/null
+++ b/langchain4j-ai-low-high-api/src/main/java/com/iwe3/langchain4j/service/ChatAssistant.java
@@ -0,0 +1,14 @@
+package com.iwe3.langchain4j.service;
+
+import dev.langchain4j.service.spring.AiService;
+import dev.langchain4j.service.spring.AiServiceWiringMode;
+
+/**
+ * 知识出处:
+ * https://docs.langchain4j.dev/tutorials/spring-boot-integration/#spring-boot-starter-for-declarative-ai-services
+ */
+@AiService(wiringMode = AiServiceWiringMode.EXPLICIT
+,chatModel = "qwen")
+public interface ChatAssistant {
+ String chat(String prompt);
+}
diff --git a/langchain4j-ai-low-high-api/src/main/resources/application.yml b/langchain4j-ai-low-high-api/src/main/resources/application.yml
new file mode 100644
index 0000000..1eae114
--- /dev/null
+++ b/langchain4j-ai-low-high-api/src/main/resources/application.yml
@@ -0,0 +1,5 @@
+server:
+ port: 9003
+spring:
+ application:
+ name: langchain4j-ai-low-level
\ No newline at end of file
diff --git a/langchain4j-ai-memory/pom.xml b/langchain4j-ai-memory/pom.xml
new file mode 100644
index 0000000..4fa026a
--- /dev/null
+++ b/langchain4j-ai-memory/pom.xml
@@ -0,0 +1,52 @@
+
+
+ 4.0.0
+
+ com.iwe3
+ langchain4j-ai-java
+ 1.0-SNAPSHOT
+
+
+ langchain4j-ai-memory
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ dev.langchain4j
+ langchain4j-reactor
+ 1.9.1-beta17
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ dev.langchain4j
+ langchain4j-open-ai-spring-boot-starter
+ 1.9.1-beta17
+
+
+
+ dev.langchain4j
+ langchain4j-spring-boot-starter
+ 1.9.1-beta17
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+
+
+
\ No newline at end of file
diff --git a/langchain4j-ai-memory/src/main/java/com/iwe3/langchain4j/MemoryApplication.java b/langchain4j-ai-memory/src/main/java/com/iwe3/langchain4j/MemoryApplication.java
new file mode 100644
index 0000000..775a0a8
--- /dev/null
+++ b/langchain4j-ai-memory/src/main/java/com/iwe3/langchain4j/MemoryApplication.java
@@ -0,0 +1,12 @@
+package com.iwe3.langchain4j;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class MemoryApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(MemoryApplication.class,args);
+ }
+}
diff --git a/langchain4j-ai-memory/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java b/langchain4j-ai-memory/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
new file mode 100644
index 0000000..c1f56fc
--- /dev/null
+++ b/langchain4j-ai-memory/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
@@ -0,0 +1,23 @@
+package com.iwe3.langchain4j.config;
+
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.openai.OpenAiChatModel;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class LLMConfig {
+
+ /**
+ * @Description: 普通对话接口 ChatModel
+ */
+ @Bean(name = "qwen")
+ public ChatModel chatModelQwen()
+ {
+ return OpenAiChatModel.builder()
+ .apiKey(System.getenv("DASH_SCOPE_API_KEY"))
+ .modelName("qwen-plus")
+ .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
+ .build();
+ }
+}
diff --git a/langchain4j-ai-memory/src/main/java/com/iwe3/langchain4j/config/MemoryChatAssistantConfig.java b/langchain4j-ai-memory/src/main/java/com/iwe3/langchain4j/config/MemoryChatAssistantConfig.java
new file mode 100644
index 0000000..c82f520
--- /dev/null
+++ b/langchain4j-ai-memory/src/main/java/com/iwe3/langchain4j/config/MemoryChatAssistantConfig.java
@@ -0,0 +1,19 @@
+package com.iwe3.langchain4j.config;
+
+import dev.langchain4j.memory.ChatMemory;
+import dev.langchain4j.memory.chat.MessageWindowChatMemory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class MemoryChatAssistantConfig {
+
+
+
+ //@Bean -> 向IOC容器中注入 chatMemory 的实例
+ @Bean
+ ChatMemory windowChatMemory() {
+ // 设置聊天记忆记录的message数量
+ return MessageWindowChatMemory.withMaxMessages(10);
+ }
+}
diff --git a/langchain4j-ai-memory/src/main/java/com/iwe3/langchain4j/config/SeparateChatAssistantConfig.java b/langchain4j-ai-memory/src/main/java/com/iwe3/langchain4j/config/SeparateChatAssistantConfig.java
new file mode 100644
index 0000000..91a05e9
--- /dev/null
+++ b/langchain4j-ai-memory/src/main/java/com/iwe3/langchain4j/config/SeparateChatAssistantConfig.java
@@ -0,0 +1,26 @@
+package com.iwe3.langchain4j.config;
+
+import dev.langchain4j.memory.chat.ChatMemoryProvider;
+import dev.langchain4j.memory.chat.MessageWindowChatMemory;
+import dev.langchain4j.store.memory.chat.InMemoryChatMemoryStore;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class SeparateChatAssistantConfig {
+
+ /**
+ * 聊天记忆提供器
+ * 配置:采用memoryId来完成隔离
+ * @return
+ */
+ @Bean
+ ChatMemoryProvider chatMemoryProvider() {
+ return memoryId -> MessageWindowChatMemory.builder()
+ .id(memoryId)
+ .maxMessages(10).chatMemoryStore(new InMemoryChatMemoryStore())
+ .build();
+ //如果未来想自定义 -> 则自己写一个类实现 ChatMemoryStore
+ }
+
+}
diff --git a/langchain4j-ai-memory/src/main/java/com/iwe3/langchain4j/service/ChatAssistant.java b/langchain4j-ai-memory/src/main/java/com/iwe3/langchain4j/service/ChatAssistant.java
new file mode 100644
index 0000000..72d4d45
--- /dev/null
+++ b/langchain4j-ai-memory/src/main/java/com/iwe3/langchain4j/service/ChatAssistant.java
@@ -0,0 +1,20 @@
+package com.iwe3.langchain4j.service;
+
+import dev.langchain4j.service.spring.AiService;
+import dev.langchain4j.service.spring.AiServiceWiringMode;
+
+/**
+ * 知识出处:
+ * https://docs.langchain4j.dev/tutorials/spring-boot-integration/#spring-boot-starter-for-declarative-ai-services
+ * chatMemory = "chatMemory" 则表示:使用ChatMemory来完成聊天记忆
+ */
+@AiService(wiringMode = AiServiceWiringMode.EXPLICIT
+,chatModel = "qwen",chatMemory = "windowChatMemory")
+public interface ChatAssistant {
+ /**
+ * 普通聊天
+ * @param prompt
+ * @return
+ */
+ String chat(String prompt);
+}
diff --git a/langchain4j-ai-memory/src/main/java/com/iwe3/langchain4j/service/SeparateChatAssistant.java b/langchain4j-ai-memory/src/main/java/com/iwe3/langchain4j/service/SeparateChatAssistant.java
new file mode 100644
index 0000000..ff4222d
--- /dev/null
+++ b/langchain4j-ai-memory/src/main/java/com/iwe3/langchain4j/service/SeparateChatAssistant.java
@@ -0,0 +1,22 @@
+package com.iwe3.langchain4j.service;
+
+import dev.langchain4j.service.MemoryId;
+import dev.langchain4j.service.UserMessage;
+import dev.langchain4j.service.spring.AiService;
+import dev.langchain4j.service.spring.AiServiceWiringMode;
+
+@AiService(
+ wiringMode = AiServiceWiringMode.EXPLICIT,
+ chatModel = "qwen",
+ chatMemoryProvider = "chatMemoryProvider"
+)
+public interface SeparateChatAssistant {
+
+ /**
+ * 分离聊天记录
+ * @param memoryId 聊天id
+ * @param userMessage 用户消息
+ * @return
+ */
+ String chat(@MemoryId int memoryId, @UserMessage String userMessage);
+}
diff --git a/langchain4j-ai-memory/src/main/resources/application.yml b/langchain4j-ai-memory/src/main/resources/application.yml
new file mode 100644
index 0000000..a71688f
--- /dev/null
+++ b/langchain4j-ai-memory/src/main/resources/application.yml
@@ -0,0 +1,10 @@
+server:
+ port: 9007
+ servlet:
+ encoding:
+ charset: utf-8
+ enabled: true
+ force: true # 设置响应的字符编码,避免流式返回输出乱码
+spring:
+ application:
+ name: langchain4j-ai-memory
\ No newline at end of file
diff --git a/langchain4j-ai-memory/src/test/java/com/iwe3/langchain4j/MemoryApplicationTest.java b/langchain4j-ai-memory/src/test/java/com/iwe3/langchain4j/MemoryApplicationTest.java
new file mode 100644
index 0000000..56417c4
--- /dev/null
+++ b/langchain4j-ai-memory/src/test/java/com/iwe3/langchain4j/MemoryApplicationTest.java
@@ -0,0 +1,51 @@
+package com.iwe3.langchain4j;
+
+import com.iwe3.langchain4j.service.ChatAssistant;
+import dev.langchain4j.data.message.UserMessage;
+import dev.langchain4j.model.chat.ChatModel;
+import jakarta.annotation.Resource;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class MemoryApplicationTest {
+
+ @Resource(name="qwen")
+ private ChatModel chatModel;
+
+ @Test
+ public void testLowerLevel(){
+
+ // 第一轮对话
+ var um01 = UserMessage.userMessage("我是蒲哥");
+ var res01 = chatModel.chat(um01);
+ var am01 = res01.aiMessage();
+ // 输出大语言模型的回复
+ System.out.println(am01.text());
+
+ // 第二轮对话
+ var um02 = UserMessage.userMessage("你知道我是谁吗");
+ //将第一轮对话记录,也一起发给 LLM
+ var res02 = chatModel.chat(um02);
+
+ var am02 = res02.aiMessage();
+ // 输出大语言模型的回复
+ System.out.println(am02.text());
+ }
+
+
+
+ @Autowired
+ private ChatAssistant chatAssistant;
+ @Test
+ public void testHighLevel(){
+ var res = chatAssistant.chat("我是蒲哥");
+ System.out.println("res = " + res);
+ res = chatAssistant.chat("我是谁?");
+ System.out.println("res = " + res);
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/langchain4j-ai-memory/src/test/java/com/iwe3/langchain4j/SeparateChatTest.java b/langchain4j-ai-memory/src/test/java/com/iwe3/langchain4j/SeparateChatTest.java
new file mode 100644
index 0000000..497b126
--- /dev/null
+++ b/langchain4j-ai-memory/src/test/java/com/iwe3/langchain4j/SeparateChatTest.java
@@ -0,0 +1,30 @@
+package com.iwe3.langchain4j;
+
+import com.iwe3.langchain4j.service.SeparateChatAssistant;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+public class SeparateChatTest {
+
+ @Autowired
+ private SeparateChatAssistant separateChatAssistant;
+
+ @Test
+ public void testSeparateChatMemory() {
+ // 用户1的对话
+ var res = separateChatAssistant.chat(1, "我是蒲哥");
+ System.out.println(res);
+ res = separateChatAssistant.chat(1, "你知道我是谁吗");
+ System.out.println(res);
+
+ // 用户2的对话
+ var res02 = separateChatAssistant.chat(2, "我是小明");
+ System.out.println(res02);
+ res02 = separateChatAssistant.chat(2, "我叫什么名字");
+ System.out.println(res02);
+ }
+
+
+}
diff --git a/langchain4j-ai-model-params/pom.xml b/langchain4j-ai-model-params/pom.xml
new file mode 100644
index 0000000..b308542
--- /dev/null
+++ b/langchain4j-ai-model-params/pom.xml
@@ -0,0 +1,51 @@
+
+
+ 4.0.0
+
+ com.iwe3
+ langchain4j-ai-java
+ 1.0-SNAPSHOT
+
+
+ langchain4j-ai-model-params
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+ ch.qos.logback
+ logback-classic
+
+
+ cn.hutool
+ hutool-all
+ 5.8.39
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ dev.langchain4j
+ langchain4j-open-ai-spring-boot-starter
+ 1.9.1-beta17
+
+
+
+ dev.langchain4j
+ langchain4j-spring-boot-starter
+ 1.9.1-beta17
+
+
+
\ No newline at end of file
diff --git a/langchain4j-ai-model-params/src/main/java/com/iwe3/langchain4j/ModelParamsApplication.java b/langchain4j-ai-model-params/src/main/java/com/iwe3/langchain4j/ModelParamsApplication.java
new file mode 100644
index 0000000..002fdb0
--- /dev/null
+++ b/langchain4j-ai-model-params/src/main/java/com/iwe3/langchain4j/ModelParamsApplication.java
@@ -0,0 +1,12 @@
+package com.iwe3.langchain4j;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class ModelParamsApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ModelParamsApplication.class,args);
+ }
+}
diff --git a/langchain4j-ai-model-params/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java b/langchain4j-ai-model-params/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
new file mode 100644
index 0000000..7093646
--- /dev/null
+++ b/langchain4j-ai-model-params/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
@@ -0,0 +1,45 @@
+package com.iwe3.langchain4j.config;
+
+import com.iwe3.langchain4j.listener.UserpuChatModelListener;
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.openai.OpenAiChatModel;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.time.Duration;
+import java.util.List;
+
+@Configuration
+public class LLMConfig {
+
+ @Bean(name = "qwen")
+ public ChatModel chatModelQwen(){
+ /*模型3件套:apikey - modelName - baseUrl */
+ return OpenAiChatModel.builder()
+ .apiKey(System.getenv("DASH_SCOPE_API_KEY"))
+ .modelName("qwen-plus")
+ .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
+ .logRequests(true)
+ .logResponses(true)
+ .listeners(List.of(new UserpuChatModelListener()))
+ .maxRetries(3)
+ .timeout(Duration.ofSeconds(5))
+ .build();
+ }
+
+ /**
+ * @Description:
+ * 知识出处,https://api-docs.deepseek.com/zh-cn/
+ */
+ @Bean(name = "deepseek")
+ public ChatModel chatModelDeepSeek(){
+ return
+ OpenAiChatModel.builder()
+ .apiKey(System.getenv("DEEP_SEEK_API_KEY"))
+ .modelName("deepseek-chat")
+ //.modelName("deepseek-reasoner")
+ .baseUrl("https://api.deepseek.com/v1")
+ .build();
+ }
+
+}
diff --git a/langchain4j-ai-model-params/src/main/java/com/iwe3/langchain4j/controller/ModelParameterController.java b/langchain4j-ai-model-params/src/main/java/com/iwe3/langchain4j/controller/ModelParameterController.java
new file mode 100644
index 0000000..8bd455d
--- /dev/null
+++ b/langchain4j-ai-model-params/src/main/java/com/iwe3/langchain4j/controller/ModelParameterController.java
@@ -0,0 +1,27 @@
+package com.iwe3.langchain4j.controller;
+
+import dev.langchain4j.model.chat.ChatModel;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@Slf4j
+public class ModelParameterController
+{
+ @Resource(name = "qwen")
+ private ChatModel chatModelQwen;
+
+ // http://localhost:9004/lc4j/modelparam/config?prompt=我是谁
+ @GetMapping(value = "/lc4j/modelparam/config")
+ public String config(@RequestParam(value = "prompt", defaultValue = "你是谁") String prompt)
+ {
+ var result = chatModelQwen.chat(prompt);
+
+ System.out.println("通过langchain4j调用模型返回结果:"+result);
+
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/langchain4j-ai-model-params/src/main/java/com/iwe3/langchain4j/listener/UserpuChatModelListener.java b/langchain4j-ai-model-params/src/main/java/com/iwe3/langchain4j/listener/UserpuChatModelListener.java
new file mode 100644
index 0000000..0e5d24a
--- /dev/null
+++ b/langchain4j-ai-model-params/src/main/java/com/iwe3/langchain4j/listener/UserpuChatModelListener.java
@@ -0,0 +1,36 @@
+package com.iwe3.langchain4j.listener;
+
+import cn.hutool.core.util.IdUtil;
+import dev.langchain4j.model.chat.listener.ChatModelErrorContext;
+import dev.langchain4j.model.chat.listener.ChatModelListener;
+import dev.langchain4j.model.chat.listener.ChatModelRequestContext;
+import dev.langchain4j.model.chat.listener.ChatModelResponseContext;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class UserpuChatModelListener implements ChatModelListener
+{
+ @Override
+ public void onRequest(ChatModelRequestContext requestContext)
+ {
+
+ // onRequest配置的k:v键值对,在onResponse阶段可以获得,上下文传递参数好用
+ String uuidValue = IdUtil.simpleUUID();
+ requestContext.attributes().put("TraceID",uuidValue);
+ log.info("请求参数requestContext:{}", requestContext+"\t"+uuidValue);
+ }
+
+ @Override
+ public void onResponse(ChatModelResponseContext responseContext)
+ {
+ Object object = responseContext.attributes().get("TraceID");
+
+ log.info("返回结果responseContext:{}", object);
+ }
+
+ @Override
+ public void onError(ChatModelErrorContext errorContext)
+ {
+ log.error("请求异常ChatModelErrorContext:{}", errorContext);
+ }
+}
diff --git a/langchain4j-ai-model-params/src/main/resources/application.yml b/langchain4j-ai-model-params/src/main/resources/application.yml
new file mode 100644
index 0000000..6783374
--- /dev/null
+++ b/langchain4j-ai-model-params/src/main/resources/application.yml
@@ -0,0 +1,9 @@
+server:
+ port: 9004
+spring:
+ application:
+ name: langchain4j-ai-model-params
+logging:
+ level:
+ dev:
+ langchain4j: debug
\ No newline at end of file
diff --git a/langchain4j-ai-mongodb/pom.xml b/langchain4j-ai-mongodb/pom.xml
new file mode 100644
index 0000000..84b3f6f
--- /dev/null
+++ b/langchain4j-ai-mongodb/pom.xml
@@ -0,0 +1,57 @@
+
+
+ 4.0.0
+
+ com.iwe3
+ langchain4j-ai-java
+ 1.0-SNAPSHOT
+
+
+ langchain4j-ai-mongodb
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-mongodb
+
+
+ dev.langchain4j
+ langchain4j-reactor
+ 1.9.1-beta17
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ dev.langchain4j
+ langchain4j-open-ai-spring-boot-starter
+ 1.9.1-beta17
+
+
+
+ dev.langchain4j
+ langchain4j-spring-boot-starter
+ 1.9.1-beta17
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+
+
+
\ No newline at end of file
diff --git a/langchain4j-ai-mongodb/src/main/java/com/iwe3/langchain4j/MongoDBApplication.java b/langchain4j-ai-mongodb/src/main/java/com/iwe3/langchain4j/MongoDBApplication.java
new file mode 100644
index 0000000..a08b38f
--- /dev/null
+++ b/langchain4j-ai-mongodb/src/main/java/com/iwe3/langchain4j/MongoDBApplication.java
@@ -0,0 +1,12 @@
+package com.iwe3.langchain4j;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class MongoDBApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(MongoDBApplication.class,args);
+ }
+}
diff --git a/langchain4j-ai-mongodb/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java b/langchain4j-ai-mongodb/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
new file mode 100644
index 0000000..c1f56fc
--- /dev/null
+++ b/langchain4j-ai-mongodb/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
@@ -0,0 +1,23 @@
+package com.iwe3.langchain4j.config;
+
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.openai.OpenAiChatModel;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class LLMConfig {
+
+ /**
+ * @Description: 普通对话接口 ChatModel
+ */
+ @Bean(name = "qwen")
+ public ChatModel chatModelQwen()
+ {
+ return OpenAiChatModel.builder()
+ .apiKey(System.getenv("DASH_SCOPE_API_KEY"))
+ .modelName("qwen-plus")
+ .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
+ .build();
+ }
+}
diff --git a/langchain4j-ai-mongodb/src/main/java/com/iwe3/langchain4j/config/MongoChatMemoryStore.java b/langchain4j-ai-mongodb/src/main/java/com/iwe3/langchain4j/config/MongoChatMemoryStore.java
new file mode 100644
index 0000000..82e569f
--- /dev/null
+++ b/langchain4j-ai-mongodb/src/main/java/com/iwe3/langchain4j/config/MongoChatMemoryStore.java
@@ -0,0 +1,51 @@
+package com.iwe3.langchain4j.config;
+
+import com.iwe3.langchain4j.entity.ChatMessages;
+import dev.langchain4j.data.message.ChatMessage;
+import dev.langchain4j.data.message.ChatMessageDeserializer;
+import dev.langchain4j.data.message.ChatMessageSerializer;
+import dev.langchain4j.store.memory.chat.ChatMemoryStore;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.data.mongodb.core.query.Update;
+import org.springframework.stereotype.Component;
+
+import java.util.LinkedList;
+import java.util.List;
+
+@Component
+public class MongoChatMemoryStore implements ChatMemoryStore {
+
+ @Autowired
+ private MongoTemplate mongoTemplate;
+
+ @Override
+ public List getMessages(Object memoryId) {
+ Criteria criteria = Criteria.where("memoryId").is(memoryId);
+ Query query = new Query(criteria);
+ ChatMessages chatMessages = mongoTemplate.findOne(query, ChatMessages.class);
+ if (chatMessages == null) return new LinkedList<>();
+ return ChatMessageDeserializer.messagesFromJson(chatMessages.getContent());
+ }
+
+ @Override
+ public void updateMessages(Object memoryId, List messages) {
+ Criteria criteria = Criteria.where("memoryId").is(memoryId);
+ Query query = new Query(criteria);
+
+ Update update = new Update();
+ update.set("content", ChatMessageSerializer.messagesToJson(messages));
+
+ // 根据query条件能查询出文档,则修改文档;否则新增文档
+ mongoTemplate.upsert(query, update, ChatMessages.class);
+ }
+
+ @Override
+ public void deleteMessages(Object memoryId) {
+ Criteria criteria = Criteria.where("memoryId").is(memoryId);
+ Query query = new Query(criteria);
+ mongoTemplate.remove(query, ChatMessages.class);
+ }
+}
\ No newline at end of file
diff --git a/langchain4j-ai-mongodb/src/main/java/com/iwe3/langchain4j/config/SeparateChatAssistantConfig.java b/langchain4j-ai-mongodb/src/main/java/com/iwe3/langchain4j/config/SeparateChatAssistantConfig.java
new file mode 100644
index 0000000..ae04333
--- /dev/null
+++ b/langchain4j-ai-mongodb/src/main/java/com/iwe3/langchain4j/config/SeparateChatAssistantConfig.java
@@ -0,0 +1,29 @@
+package com.iwe3.langchain4j.config;
+
+import dev.langchain4j.memory.chat.ChatMemoryProvider;
+import dev.langchain4j.memory.chat.MessageWindowChatMemory;
+import dev.langchain4j.store.memory.chat.InMemoryChatMemoryStore;
+import jakarta.annotation.Resource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class SeparateChatAssistantConfig {
+
+ @Resource
+ private MongoChatMemoryStore mongoChatMemoryStore;
+
+ /**
+ * 指定使用-> mongoChatMemoryStore 来存储
+ * @return
+ */
+ @Bean
+ ChatMemoryProvider chatMemoryProvider() {
+ return memoryId -> MessageWindowChatMemory.builder()
+ .id(memoryId)
+ .maxMessages(10).
+ chatMemoryStore(mongoChatMemoryStore)
+ .build();
+ }
+}
\ No newline at end of file
diff --git a/langchain4j-ai-mongodb/src/main/java/com/iwe3/langchain4j/entity/ChatMessages.java b/langchain4j-ai-mongodb/src/main/java/com/iwe3/langchain4j/entity/ChatMessages.java
new file mode 100644
index 0000000..e2c4933
--- /dev/null
+++ b/langchain4j-ai-mongodb/src/main/java/com/iwe3/langchain4j/entity/ChatMessages.java
@@ -0,0 +1,24 @@
+package com.iwe3.langchain4j.entity;
+
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.bson.types.ObjectId;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Document("chat_messages")
+public class ChatMessages {
+
+ //唯一标识,映射到 MongoDB 文档的 _id 字段
+ @Id
+ private ObjectId messageId; //利用数据库生成ID就用ObjectId
+
+ private String memoryId; //隔离聊天记录的ID
+
+ private String content; //存储当前聊天记录列表的json字符串
+}
\ No newline at end of file
diff --git a/langchain4j-ai-mongodb/src/main/java/com/iwe3/langchain4j/service/SeparateChatAssistant.java b/langchain4j-ai-mongodb/src/main/java/com/iwe3/langchain4j/service/SeparateChatAssistant.java
new file mode 100644
index 0000000..ff4222d
--- /dev/null
+++ b/langchain4j-ai-mongodb/src/main/java/com/iwe3/langchain4j/service/SeparateChatAssistant.java
@@ -0,0 +1,22 @@
+package com.iwe3.langchain4j.service;
+
+import dev.langchain4j.service.MemoryId;
+import dev.langchain4j.service.UserMessage;
+import dev.langchain4j.service.spring.AiService;
+import dev.langchain4j.service.spring.AiServiceWiringMode;
+
+@AiService(
+ wiringMode = AiServiceWiringMode.EXPLICIT,
+ chatModel = "qwen",
+ chatMemoryProvider = "chatMemoryProvider"
+)
+public interface SeparateChatAssistant {
+
+ /**
+ * 分离聊天记录
+ * @param memoryId 聊天id
+ * @param userMessage 用户消息
+ * @return
+ */
+ String chat(@MemoryId int memoryId, @UserMessage String userMessage);
+}
diff --git a/langchain4j-ai-mongodb/src/main/resources/application.yml b/langchain4j-ai-mongodb/src/main/resources/application.yml
new file mode 100644
index 0000000..14bdbfe
--- /dev/null
+++ b/langchain4j-ai-mongodb/src/main/resources/application.yml
@@ -0,0 +1,13 @@
+server:
+ port: 9008
+ servlet:
+ encoding:
+ charset: utf-8
+ enabled: true
+ force: true # 设置响应的字符编码,避免流式返回输出乱码
+spring:
+ application:
+ name: langchain4j-ai-mongodb
+ data:
+ mongodb:
+ uri: mongodb://localhost:27017/chat_memory_db # MongoDB连接配置,数据库 chat_memory_db 会自动创建
\ No newline at end of file
diff --git a/langchain4j-ai-mongodb/src/test/java/com/iwe3/langchain4j/MongoCrudTest.java b/langchain4j-ai-mongodb/src/test/java/com/iwe3/langchain4j/MongoCrudTest.java
new file mode 100644
index 0000000..4610747
--- /dev/null
+++ b/langchain4j-ai-mongodb/src/test/java/com/iwe3/langchain4j/MongoCrudTest.java
@@ -0,0 +1,57 @@
+package com.iwe3.langchain4j;
+
+import com.iwe3.langchain4j.entity.ChatMessages;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.data.mongodb.core.query.Update;
+
+@SpringBootTest
+public class MongoCrudTest {
+
+ @Autowired
+ private MongoTemplate mongoTemplate;
+
+ @Test
+ public void delete(){
+ var criteria = Criteria.where("_id").is("69420db67db051baab1b4873");
+ var query = new Query(criteria);
+ mongoTemplate.remove(query,ChatMessages.class);
+ }
+
+ @Test
+ public void update(){
+ //id不存在,则会自动变成:新增
+ var criteria = Criteria.where("_id").is("69420db67db051baab1b4873");
+ var query = new Query(criteria);
+ //创建一个修改对象
+ var update = new Update();
+ update.set("content","奥特之母");
+ //将查询条件, 修改的内容,文档的信息 -> mongodb
+ mongoTemplate.upsert(query,update,ChatMessages.class);
+ }
+
+
+ @Test
+ public void insert(){
+// mongoTemplate.insert(new ChatMessages(1L,"迪迦")); //程序员自己管理ID就用Long
+
+ //利用数据库生成ID就用ObjectId
+ var msg = new ChatMessages();
+ msg.setContent("贝利亚");
+ mongoTemplate.insert(msg);
+ }
+
+ @Test
+ public void findById(){
+ var msg = mongoTemplate.
+ findById("69420db67db051baab1b4873",
+ ChatMessages.class);
+ System.out.println(msg);
+ }
+
+
+}
diff --git a/langchain4j-ai-mongodb/src/test/java/com/iwe3/langchain4j/MongoDBApplicationTest.java b/langchain4j-ai-mongodb/src/test/java/com/iwe3/langchain4j/MongoDBApplicationTest.java
new file mode 100644
index 0000000..47fe13c
--- /dev/null
+++ b/langchain4j-ai-mongodb/src/test/java/com/iwe3/langchain4j/MongoDBApplicationTest.java
@@ -0,0 +1,30 @@
+package com.iwe3.langchain4j;
+
+import com.iwe3.langchain4j.service.SeparateChatAssistant;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+
+@SpringBootTest
+class MongoDBApplicationTest {
+
+ @Autowired
+ private SeparateChatAssistant separateChatAssistant;
+
+ @Test
+ public void testSeparateChatMemory() {
+ // 用户1的对话
+ var res = separateChatAssistant.chat(1, "我是蒲哥");
+ System.out.println(res);
+ res = separateChatAssistant.chat(1, "你知道我是谁吗");
+ System.out.println(res);
+
+ // 用户2的对话
+ var res02 = separateChatAssistant.chat(2, "我是小明");
+ System.out.println(res02);
+ res02 = separateChatAssistant.chat(2, "我叫什么名字");
+ System.out.println(res02);
+ }
+
+}
\ No newline at end of file
diff --git a/langchain4j-ai-multimode/pom.xml b/langchain4j-ai-multimode/pom.xml
new file mode 100644
index 0000000..c8307f1
--- /dev/null
+++ b/langchain4j-ai-multimode/pom.xml
@@ -0,0 +1,46 @@
+
+
+ 4.0.0
+
+ com.iwe3
+ langchain4j-ai-java
+ 1.0-SNAPSHOT
+
+
+ langchain4j-ai-multimode
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ dev.langchain4j
+ langchain4j-open-ai
+
+
+ dev.langchain4j
+ langchain4j
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
\ No newline at end of file
diff --git a/langchain4j-ai-multimode/src/main/java/com/iwe3/langchain4j/MultiModelApplication.java b/langchain4j-ai-multimode/src/main/java/com/iwe3/langchain4j/MultiModelApplication.java
new file mode 100644
index 0000000..d39438e
--- /dev/null
+++ b/langchain4j-ai-multimode/src/main/java/com/iwe3/langchain4j/MultiModelApplication.java
@@ -0,0 +1,11 @@
+package com.iwe3.langchain4j;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class MultiModelApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(MultiModelApplication.class);
+ }
+}
diff --git a/langchain4j-ai-multimode/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java b/langchain4j-ai-multimode/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
new file mode 100644
index 0000000..458fcac
--- /dev/null
+++ b/langchain4j-ai-multimode/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
@@ -0,0 +1,37 @@
+package com.iwe3.langchain4j.config;
+
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.openai.OpenAiChatModel;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class LLMConfig {
+
+ @Bean(name = "qwen")
+ public ChatModel chatModelQwen()
+ {
+ return OpenAiChatModel.builder()
+ .apiKey(System.getenv("DASH_SCOPE_API_KEY"))
+ .modelName("qwen-plus")
+ .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
+ .build();
+ }
+
+ /**
+ * @Description:
+ * 知识出处,https://api-docs.deepseek.com/zh-cn/
+ */
+ @Bean(name = "deepseek")
+ public ChatModel chatModelDeepSeek()
+ {
+ return
+ OpenAiChatModel.builder()
+ .apiKey(System.getenv("DEEP_SEEK_API_KEY"))
+ .modelName("deepseek-chat")
+ //.modelName("deepseek-reasoner")
+ .baseUrl("https://api.deepseek.com/v1")
+ .build();
+ }
+
+}
diff --git a/langchain4j-ai-multimode/src/main/java/com/iwe3/langchain4j/controller/MultiModelController.java b/langchain4j-ai-multimode/src/main/java/com/iwe3/langchain4j/controller/MultiModelController.java
new file mode 100644
index 0000000..b3cf0fe
--- /dev/null
+++ b/langchain4j-ai-multimode/src/main/java/com/iwe3/langchain4j/controller/MultiModelController.java
@@ -0,0 +1,35 @@
+package com.iwe3.langchain4j.controller;
+
+import dev.langchain4j.model.chat.ChatModel;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@Slf4j
+public class MultiModelController
+{
+ @Resource(name = "qwen")
+ private ChatModel chatModelQwen;
+
+ @Resource(name = "deepseek")
+ private ChatModel chatModelDeepSeek;
+
+ // http://localhost:9002/multimodel/qwen?prompt=如何学习LangChain4J
+ @GetMapping(value = "/multimodel/qwen")
+ public String qwenCall(@RequestParam(value = "prompt", defaultValue = "你是谁") String prompt) {
+ var result = chatModelQwen.chat(prompt);
+ System.out.println("通过langchain4j调用模型返回结果:\n"+result);
+ return result;
+ }
+
+ // http://localhost:9002/multimodel/deepseek?prompt=如何学习LangChain4J
+ @GetMapping(value = "/multimodel/deepseek")
+ public String deepseekCall(@RequestParam(value = "prompt", defaultValue = "你是谁") String prompt){
+ var result = chatModelDeepSeek.chat(prompt);
+ System.out.println("通过langchain4j调用模型返回结果:\n"+result);
+ return result;
+ }
+}
diff --git a/langchain4j-ai-multimode/src/main/resources/application.yml b/langchain4j-ai-multimode/src/main/resources/application.yml
new file mode 100644
index 0000000..f9865bd
--- /dev/null
+++ b/langchain4j-ai-multimode/src/main/resources/application.yml
@@ -0,0 +1,5 @@
+server:
+ port: 9002
+spring:
+ application:
+ name: langchain4j-ai-multimode
\ No newline at end of file
diff --git a/langchain4j-ai-pinecone/pom.xml b/langchain4j-ai-pinecone/pom.xml
new file mode 100644
index 0000000..eb8ceb0
--- /dev/null
+++ b/langchain4j-ai-pinecone/pom.xml
@@ -0,0 +1,67 @@
+
+
+ 4.0.0
+
+ com.iwe3
+ langchain4j-ai-java
+ 1.0-SNAPSHOT
+
+
+ langchain4j-ai-pinecone
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ dev.langchain4j
+ langchain4j-pinecone
+
+
+
+ dev.langchain4j
+ langchain4j-community-dashscope-spring-boot-starter
+
+
+
+ dev.langchain4j
+ langchain4j-easy-rag
+
+
+
+ dev.langchain4j
+ langchain4j-document-parser-apache-pdfbox
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ dev.langchain4j
+ langchain4j-open-ai-spring-boot-starter
+ 1.9.1-beta17
+
+
+
+ dev.langchain4j
+ langchain4j-spring-boot-starter
+ 1.9.1-beta17
+
+
+
+
\ No newline at end of file
diff --git a/langchain4j-ai-pinecone/src/main/java/com/iwe3/langchain4j/PineConeApplication.java b/langchain4j-ai-pinecone/src/main/java/com/iwe3/langchain4j/PineConeApplication.java
new file mode 100644
index 0000000..9a085a6
--- /dev/null
+++ b/langchain4j-ai-pinecone/src/main/java/com/iwe3/langchain4j/PineConeApplication.java
@@ -0,0 +1,12 @@
+package com.iwe3.langchain4j;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class PineConeApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(PineConeApplication.class,args);
+ }
+}
diff --git a/langchain4j-ai-pinecone/src/main/java/com/iwe3/langchain4j/config/EmbeddingStoreConfig.java b/langchain4j-ai-pinecone/src/main/java/com/iwe3/langchain4j/config/EmbeddingStoreConfig.java
new file mode 100644
index 0000000..b7f3275
--- /dev/null
+++ b/langchain4j-ai-pinecone/src/main/java/com/iwe3/langchain4j/config/EmbeddingStoreConfig.java
@@ -0,0 +1,32 @@
+package com.iwe3.langchain4j.config;
+
+import dev.langchain4j.data.segment.TextSegment;
+import dev.langchain4j.model.embedding.EmbeddingModel;
+import dev.langchain4j.store.embedding.EmbeddingStore;
+import dev.langchain4j.store.embedding.pinecone.PineconeEmbeddingStore;
+import dev.langchain4j.store.embedding.pinecone.PineconeServerlessIndexConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class EmbeddingStoreConfig {
+
+ @Autowired
+ private EmbeddingModel embeddingModel;
+
+ @Bean
+ public EmbeddingStore embeddingStore() {
+ // 创建向量存储
+ return PineconeEmbeddingStore.builder()
+ .apiKey(System.getenv("PINECONE_API_KEY"))
+ .index("xiaoai-index") // 如果指定的索引不存在,将创建一个新的索引
+ .nameSpace("xiaoai-namespace") // 如果指定的名称空间不存在,将创建一个新的名称空间
+ .createIndex(PineconeServerlessIndexConfig.builder()
+ .cloud("AWS") // 指定索引部署在 AWS 云服务上。
+ .region("us-east-1") // 指定索引所在的 AWS 区域为 us-east-1。
+ .dimension(embeddingModel.dimension()) // 指定索引的向量维度,该维度与 embeddingModel 生成的向量维度相同。
+ .build())
+ .build();
+ }
+}
\ No newline at end of file
diff --git a/langchain4j-ai-pinecone/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java b/langchain4j-ai-pinecone/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
new file mode 100644
index 0000000..c1f56fc
--- /dev/null
+++ b/langchain4j-ai-pinecone/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
@@ -0,0 +1,23 @@
+package com.iwe3.langchain4j.config;
+
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.openai.OpenAiChatModel;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class LLMConfig {
+
+ /**
+ * @Description: 普通对话接口 ChatModel
+ */
+ @Bean(name = "qwen")
+ public ChatModel chatModelQwen()
+ {
+ return OpenAiChatModel.builder()
+ .apiKey(System.getenv("DASH_SCOPE_API_KEY"))
+ .modelName("qwen-plus")
+ .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
+ .build();
+ }
+}
diff --git a/langchain4j-ai-pinecone/src/main/resources/application.yml b/langchain4j-ai-pinecone/src/main/resources/application.yml
new file mode 100644
index 0000000..2e075fd
--- /dev/null
+++ b/langchain4j-ai-pinecone/src/main/resources/application.yml
@@ -0,0 +1,11 @@
+server:
+ port: 9011
+spring:
+ application:
+ name: langchain4j-ai-pinecone
+langchain4j:
+ community:
+ dashscope:
+ embedding-model:
+ model-name: text-embedding-v3
+ api-key: ${DASH_SCOPE_API_KEY}
\ No newline at end of file
diff --git a/langchain4j-ai-pinecone/src/test/java/com/iwe3/langchain4j/PineConeApplicationTest.java b/langchain4j-ai-pinecone/src/test/java/com/iwe3/langchain4j/PineConeApplicationTest.java
new file mode 100644
index 0000000..926d47b
--- /dev/null
+++ b/langchain4j-ai-pinecone/src/test/java/com/iwe3/langchain4j/PineConeApplicationTest.java
@@ -0,0 +1,79 @@
+package com.iwe3.langchain4j;
+
+import dev.langchain4j.data.segment.TextSegment;
+import dev.langchain4j.model.embedding.EmbeddingModel;
+import dev.langchain4j.store.embedding.EmbeddingMatch;
+import dev.langchain4j.store.embedding.EmbeddingSearchRequest;
+import dev.langchain4j.store.embedding.EmbeddingSearchResult;
+import dev.langchain4j.store.embedding.EmbeddingStore;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class PineConeApplicationTest {
+
+ @Autowired
+ private EmbeddingModel embeddingModel;
+ @Autowired
+ private EmbeddingStore embeddingStore;
+
+
+ /**
+ * Pinecone - 相似度匹配
+ */
+ @Test
+ public void embeddingSearch() {
+ // 提问,并将问题转成向量数据
+ var queryEmbedding = embeddingModel.embed("你最喜欢的运动是什么?").content();
+
+ // 创建搜索请求对象
+ var searchRequest = EmbeddingSearchRequest.builder()
+ .queryEmbedding(queryEmbedding)
+ .maxResults(1) // 匹配最相似的一条记录
+ .minScore(0.8)
+ .build();
+
+ // 根据搜索请求 searchRequest 在向量存储中进行相似度搜索
+ EmbeddingSearchResult searchResult = embeddingStore.search(searchRequest);
+
+ // searchResult.matches(): 获取搜索结果中的匹配项列表。
+ // .get(0): 从匹配项列表中获取第一个匹配项
+ EmbeddingMatch embeddingMatch = searchResult.matches().get(0);
+
+ // 获取匹配项的相似度得分
+ System.out.println(embeddingMatch.score()); // 输出:0.8144288515898701
+
+ // 返回文本结果
+ System.out.println(embeddingMatch.embedded().text());
+ }
+
+
+
+ /**
+ * 将文本转换成向量,然后存储到 pinecone 中
+ *
+ * 参考:
+ * https://docs.langchain4j.dev/tutorials/embedding-stores
+ */
+ @Test
+ public void testPineconeEmbedded() {
+ // 将文本转换成向量
+ var seg1 = TextSegment.from("我喜欢羽毛球");
+ var em1 = embeddingModel.embed(seg1).content();
+ embeddingStore.add(em1, seg1);// 存入向量数据库
+
+ var seg2 = TextSegment.from("今天天气很好");
+ var em2 = embeddingModel.embed(seg2).content();
+ embeddingStore.add(em2, seg2);// 存入向量数据库
+ }
+
+
+ @Test
+ public void testEmbeddingModel() {
+ var embed = embeddingModel.embed("你好");
+
+ System.out.println("向量维度:" + embed.content().vector().length);
+ System.out.println("向量输出:" + embed.toString());
+ }
+}
\ No newline at end of file
diff --git a/langchain4j-ai-prompt/pom.xml b/langchain4j-ai-prompt/pom.xml
new file mode 100644
index 0000000..e07df07
--- /dev/null
+++ b/langchain4j-ai-prompt/pom.xml
@@ -0,0 +1,48 @@
+
+
+ 4.0.0
+
+ com.iwe3
+ langchain4j-ai-java
+ 1.0-SNAPSHOT
+
+
+ langchain4j-ai-prompt
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ dev.langchain4j
+ langchain4j-open-ai-spring-boot-starter
+ 1.9.1-beta17
+
+
+
+ dev.langchain4j
+ langchain4j-spring-boot-starter
+ 1.9.1-beta17
+
+
+
+
\ No newline at end of file
diff --git a/langchain4j-ai-prompt/src/main/java/com/iwe3/langchain4j/PromptApplication.java b/langchain4j-ai-prompt/src/main/java/com/iwe3/langchain4j/PromptApplication.java
new file mode 100644
index 0000000..e118cb9
--- /dev/null
+++ b/langchain4j-ai-prompt/src/main/java/com/iwe3/langchain4j/PromptApplication.java
@@ -0,0 +1,12 @@
+package com.iwe3.langchain4j;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class PromptApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(PromptApplication.class,args);
+ }
+}
diff --git a/langchain4j-ai-prompt/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java b/langchain4j-ai-prompt/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
new file mode 100644
index 0000000..c1f56fc
--- /dev/null
+++ b/langchain4j-ai-prompt/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
@@ -0,0 +1,23 @@
+package com.iwe3.langchain4j.config;
+
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.openai.OpenAiChatModel;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class LLMConfig {
+
+ /**
+ * @Description: 普通对话接口 ChatModel
+ */
+ @Bean(name = "qwen")
+ public ChatModel chatModelQwen()
+ {
+ return OpenAiChatModel.builder()
+ .apiKey(System.getenv("DASH_SCOPE_API_KEY"))
+ .modelName("qwen-plus")
+ .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
+ .build();
+ }
+}
diff --git a/langchain4j-ai-prompt/src/main/java/com/iwe3/langchain4j/controller/ChatPromptController.java b/langchain4j-ai-prompt/src/main/java/com/iwe3/langchain4j/controller/ChatPromptController.java
new file mode 100644
index 0000000..13c49bb
--- /dev/null
+++ b/langchain4j-ai-prompt/src/main/java/com/iwe3/langchain4j/controller/ChatPromptController.java
@@ -0,0 +1,104 @@
+package com.iwe3.langchain4j.controller;
+
+import com.iwe3.langchain4j.entity.LawPrompt;
+import com.iwe3.langchain4j.service.LawExplainAssistant;
+import dev.langchain4j.data.message.UserMessage;
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.chat.response.ChatResponse;
+import dev.langchain4j.model.input.Prompt;
+import dev.langchain4j.model.input.PromptTemplate;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.assertj.core.util.DateUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+
+@RestController
+@Slf4j
+public class ChatPromptController {
+
+ @Resource
+ private LawExplainAssistant lawExplainAssistant;
+ /**
+ * http://localhost:9008/lc4j/chatprompt/test2
+ * TRIPS协议(与贸易有关的知识产权协议):
+ * 世界贸易组织(WTO)成员间的一个重要协议,
+ * 它规定了最低标准的知识产权保护要求,并适用于所有WTO成员。
+ * @return
+ */
+ @GetMapping(value = "/lc4j/chatprompt/test2")
+ public String test2()
+ {
+ var prompt = new LawPrompt();
+ prompt.setLegal("知识产权");
+ prompt.setQuestion("TRIPS协议?");
+
+ var chat = lawExplainAssistant.chat(prompt);
+ System.out.println(chat);
+
+ return "success : "+ DateUtil.now()+"
\n\n chat: "+chat;
+ }
+
+
+ /**
+ * 高阶API调用
+ * http://localhost:9008/lc4j/chatprompt/test1
+ * @return
+ */
+ @GetMapping(value = "/lc4j/chatprompt/test1")
+ public String test1()
+ {
+ String chat = lawExplainAssistant.chat("什么是知识产权?",2000);
+ System.out.println(chat);
+
+ String chat2 = lawExplainAssistant.chat("什么是java?",2000);
+ System.out.println(chat2);
+
+ return "success : "+ DateUtil.now()+"
\n\n chat: "+chat+"
\n\n chat2: "+chat2;
+ }
+
+
+
+
+
+
+ @Resource(name = "qwen")
+ private ChatModel chatModel;
+
+ /**
+ * 低阶API调用
+ * http://localhost:9008/lc4j/chatprompt/test
+ * @return
+ */
+ @GetMapping(value = "/lc4j/chatprompt/test")
+ public String test(){
+ // 看看源码,默认 PromptTemplate 构造使用 it 属性作为默认占位符
+
+ /*String role = "外科医生";
+ String question = "牙疼";*/
+
+ String role = "财务会计";
+ String question = "人民币大写";
+
+ //1 构造PromptTemplate模板
+ PromptTemplate template = PromptTemplate.from("你是一个{{it}}助手,{{question}}怎么办");
+ //2 由PromptTemplate生成Prompt
+ Prompt prompt = template.apply(Map.of("it",role,"question",question));
+ //3 Prompt提示词变成UserMessage
+ UserMessage userMessage = prompt.toUserMessage();
+ //4 调用大模型
+ ChatResponse chatResponse = chatModel.chat(userMessage);
+
+ //4.1 后台打印
+ System.out.println(chatResponse.aiMessage().text());
+ //4.2 前台返回
+ return "success : "+ DateUtil.now()+"
\n\n chat: "+chatResponse.aiMessage().text();
+ }
+
+
+
+
+}
diff --git a/langchain4j-ai-prompt/src/main/java/com/iwe3/langchain4j/entity/LawPrompt.java b/langchain4j-ai-prompt/src/main/java/com/iwe3/langchain4j/entity/LawPrompt.java
new file mode 100644
index 0000000..e649f52
--- /dev/null
+++ b/langchain4j-ai-prompt/src/main/java/com/iwe3/langchain4j/entity/LawPrompt.java
@@ -0,0 +1,12 @@
+package com.iwe3.langchain4j.entity;
+
+import dev.langchain4j.model.input.structured.StructuredPrompt;
+import lombok.Data;
+
+@Data
+@StructuredPrompt("根据中国{{legal}}法律,解答以下问题:{{question}}")
+public class LawPrompt
+{
+ private String legal;//法律
+ private String question;//问题
+}
diff --git a/langchain4j-ai-prompt/src/main/java/com/iwe3/langchain4j/service/LawExplainAssistant.java b/langchain4j-ai-prompt/src/main/java/com/iwe3/langchain4j/service/LawExplainAssistant.java
new file mode 100644
index 0000000..051ce74
--- /dev/null
+++ b/langchain4j-ai-prompt/src/main/java/com/iwe3/langchain4j/service/LawExplainAssistant.java
@@ -0,0 +1,38 @@
+package com.iwe3.langchain4j.service;
+
+import com.iwe3.langchain4j.entity.LawPrompt;
+import dev.langchain4j.service.SystemMessage;
+import dev.langchain4j.service.UserMessage;
+import dev.langchain4j.service.V;
+import dev.langchain4j.service.spring.AiService;
+
+/**
+ * 一个法律解释助手
+ */
+@AiService(chatModel = "qwen")
+public interface LawExplainAssistant {
+
+ //案例3 当提示词过多,也可以将从外部资源加载
+ @SystemMessage(fromResource = "prompt-template.txt")
+ String chat(LawPrompt lawPrompt);
+
+ //案例2 新建带着@StructuredPrompt的业务实体类,比如LawPrompt
+// @SystemMessage("你是一位专业的中国法律顾问,只回答与中国法律相关的问题。" +
+// "输出限制:对于其他领域的问题禁止回答,直接返回'抱歉,我只能回答中国法律相关的问题。'")
+// String chat(LawPrompt lawPrompt);
+
+
+ // @SystemMessage : 定AI-LLM 的角色,任务,风格,格式
+ // @UserMessage : 用户提示词
+ // @V : 超过1个以上参数,需要起别名
+ //案例1 @SystemMessage + @UserMessage + @V
+ @SystemMessage("你是一位专业的中国法律顾问,只回答与中国法律相关的问题。" +
+ "输出限制:对于其他领域的问题禁止回答,直接返回'抱歉,我只能回答中国法律相关的问题。'")
+
+ @UserMessage("请回答以下法律问题:{{question}},字数控制在{{length}}以内")
+ String chat(@V("question") String question, @V("length") int length);
+
+
+
+
+}
diff --git a/langchain4j-ai-prompt/src/main/resources/application.yml b/langchain4j-ai-prompt/src/main/resources/application.yml
new file mode 100644
index 0000000..6ae92a4
--- /dev/null
+++ b/langchain4j-ai-prompt/src/main/resources/application.yml
@@ -0,0 +1,5 @@
+server:
+ port: 9008
+spring:
+ application:
+ name: langchain4j-ai-prompt
\ No newline at end of file
diff --git a/langchain4j-ai-prompt/src/main/resources/prompt-template.txt b/langchain4j-ai-prompt/src/main/resources/prompt-template.txt
new file mode 100644
index 0000000..0895918
--- /dev/null
+++ b/langchain4j-ai-prompt/src/main/resources/prompt-template.txt
@@ -0,0 +1,2 @@
+你是一位专业的中国法律顾问,只回答与中国法律相关的问题。
+输出限制:对于其他领域的问题禁止回答,直接返回'抱歉,我只能回答中国法律相关的问题。
\ No newline at end of file
diff --git a/langchain4j-ai-rag/pom.xml b/langchain4j-ai-rag/pom.xml
new file mode 100644
index 0000000..08379e0
--- /dev/null
+++ b/langchain4j-ai-rag/pom.xml
@@ -0,0 +1,58 @@
+
+
+ 4.0.0
+
+ com.iwe3
+ langchain4j-ai-java
+ 1.0-SNAPSHOT
+
+
+ langchain4j-ai-rag
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+
+ dev.langchain4j
+ langchain4j-easy-rag
+
+
+
+ dev.langchain4j
+ langchain4j-document-parser-apache-pdfbox
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ dev.langchain4j
+ langchain4j-open-ai-spring-boot-starter
+ 1.9.1-beta17
+
+
+
+ dev.langchain4j
+ langchain4j-spring-boot-starter
+ 1.9.1-beta17
+
+
+
+
\ No newline at end of file
diff --git a/langchain4j-ai-rag/src/main/java/com/iwe3/langchain4j/RagApplication.java b/langchain4j-ai-rag/src/main/java/com/iwe3/langchain4j/RagApplication.java
new file mode 100644
index 0000000..fff9dfa
--- /dev/null
+++ b/langchain4j-ai-rag/src/main/java/com/iwe3/langchain4j/RagApplication.java
@@ -0,0 +1,12 @@
+package com.iwe3.langchain4j;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class RagApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(RagApplication.class,args);
+ }
+}
diff --git a/langchain4j-ai-rag/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java b/langchain4j-ai-rag/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
new file mode 100644
index 0000000..c1f56fc
--- /dev/null
+++ b/langchain4j-ai-rag/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
@@ -0,0 +1,23 @@
+package com.iwe3.langchain4j.config;
+
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.openai.OpenAiChatModel;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class LLMConfig {
+
+ /**
+ * @Description: 普通对话接口 ChatModel
+ */
+ @Bean(name = "qwen")
+ public ChatModel chatModelQwen()
+ {
+ return OpenAiChatModel.builder()
+ .apiKey(System.getenv("DASH_SCOPE_API_KEY"))
+ .modelName("qwen-plus")
+ .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
+ .build();
+ }
+}
diff --git a/langchain4j-ai-rag/src/main/resources/application.yml b/langchain4j-ai-rag/src/main/resources/application.yml
new file mode 100644
index 0000000..e299359
--- /dev/null
+++ b/langchain4j-ai-rag/src/main/resources/application.yml
@@ -0,0 +1,5 @@
+server:
+ port: 9010
+spring:
+ application:
+ name: langchain4j-ai-rag
\ No newline at end of file
diff --git a/langchain4j-ai-rag/src/main/resources/files/test.txt b/langchain4j-ai-rag/src/main/resources/files/test.txt
new file mode 100644
index 0000000..4b6d1bd
--- /dev/null
+++ b/langchain4j-ai-rag/src/main/resources/files/test.txt
@@ -0,0 +1 @@
+电子科技大学,简称“成电”(UESTC) [12],位于四川成都,是中华人民共和国教育部直属全国重点大学 [127],国家首批“211工程”“985工程”重点建设大学,首批国家“双一流”建设高校; [188]入选111计划 [140]、101计划 [141]、强基计划 [137]、珠峰计划 [138]、英才计划 [120]、卓越工程师教育培养计划 [139]、国家建设高水平大学公派研究生项目 [136];是一所以电子信息科学技术为核心,以工为主,理工渗透,理、工、管、文、医协调发展的多科性研究型大学,被誉为“中国民族电子工业摇篮”和“中国电子类院校排头兵”。
\ No newline at end of file
diff --git a/langchain4j-ai-rag/src/main/resources/files/电子科大.md b/langchain4j-ai-rag/src/main/resources/files/电子科大.md
new file mode 100644
index 0000000..8582793
--- /dev/null
+++ b/langchain4j-ai-rag/src/main/resources/files/电子科大.md
@@ -0,0 +1,21 @@
+电子科技大学(University of Electronic Science and Technology of China,简称 **UESTC** 或 **“成电”**)是中国电子信息领域顶尖的高等学府,也是国家“985工程”“211工程”和首批“双一流”A类建设高校。以下是其核心简介:
+
+------
+
+### 📍 基本信息
+
+- **所在地**:四川省成都市(主校区为清水河校区,另有沙河、九里堤校区)
+- **创办时间**:1956年
+- **主管部门**:中华人民共和国教育部
+- **校训**:求实求真,大气大为
+
+------
+
+### 🏛️ 历史沿革
+
+- 由周恩来总理亲自部署,整合:
+ - 交通大学(现上海交大、西安交大)
+ - 南京工学院(现东南大学)
+ - 华南工学院(现华南理工大学) 的**电讯工程专业**,组建 **成都电讯工程学院**。
+- 1988年更名为 **电子科技大学**。
+- 1960年即被列为全国重点高校,1961年成为“国防七子”之一。
\ No newline at end of file
diff --git a/langchain4j-ai-rag/src/main/resources/files/电子科大.pdf b/langchain4j-ai-rag/src/main/resources/files/电子科大.pdf
new file mode 100644
index 0000000..158db7f
Binary files /dev/null and b/langchain4j-ai-rag/src/main/resources/files/电子科大.pdf differ
diff --git a/langchain4j-ai-rag/src/test/java/com/iwe3/langchain4j/RagApplicationTest.java b/langchain4j-ai-rag/src/test/java/com/iwe3/langchain4j/RagApplicationTest.java
new file mode 100644
index 0000000..edd53df
--- /dev/null
+++ b/langchain4j-ai-rag/src/test/java/com/iwe3/langchain4j/RagApplicationTest.java
@@ -0,0 +1,83 @@
+package com.iwe3.langchain4j;
+
+import ai.djl.huggingface.tokenizers.HuggingFaceTokenizer;
+import dev.langchain4j.data.document.Document;
+import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;
+import dev.langchain4j.data.document.parser.apache.pdfbox.ApachePdfBoxDocumentParser;
+import dev.langchain4j.data.document.splitter.DocumentByParagraphSplitter;
+import dev.langchain4j.data.message.UserMessage;
+import dev.langchain4j.data.segment.TextSegment;
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.chat.response.ChatResponse;
+import dev.langchain4j.model.output.TokenUsage;
+import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
+import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;
+import jakarta.annotation.Resource;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class RagApplicationTest {
+
+ @Resource
+ private ChatModel chatModel;
+
+
+ @Test
+ public void testCountToken(){
+ var res = chatModel.chat(UserMessage.from("你好,这是一段文字!"));
+ var result = res.aiMessage().text();
+ System.out.println("通过调用大模型返回结果:" + result);
+ /*Token用量计算底层API*/
+ var tu = res.tokenUsage();
+ System.out.println("本地调用销毁的TOKEN:" + tu);
+ }
+
+
+ /**
+ * 加载文档并存入向量数据库
+ */
+ @Test
+ public void testReadDocumentAndStore() {
+ // 使用FileSystemDocumentLoader读取指定目录下的知识库文档
+ // 并使用默认的文档解析器TextDocumentParser对文档进行解析
+ var document = FileSystemDocumentLoader.loadDocument("D:/files/电子科大.md");
+
+ // 为了简单起见,我们暂时使用基于内存的向量存储
+ InMemoryEmbeddingStore db = new InMemoryEmbeddingStore<>();
+
+ // /ingest
+ // /1、分割文档,默认使用递归分割器,将文档分割为多个文本片段,每个片段包含不超过 300个token,并且有 30个token的重叠部分保证连贯性
+ // /2、文本向量化:使用一个LangChain4j内置的轻量化向量模型对每个文本片段进行向量化
+ // /3、将原始文本和向量存储到向量数据库中(InMemoryEmbeddingStore)
+ EmbeddingStoreIngestor.ingest(document, db);
+
+ // 查看向量数据库内容
+ System.out.println(db);
+ }
+
+
+
+ /**
+ * 解析PDF
+ */
+ @Test
+ public void testParsePDF() {
+ var document = FileSystemDocumentLoader.loadDocument(
+ "D:/files/电子科大.pdf",
+ new ApachePdfBoxDocumentParser()
+ );
+ System.out.println(document);
+ }
+
+ @Test
+ public void testReadDocument() {
+ // 使用FileSystemDocumentLoader读取指定目录下的知识库文档
+ // 并使用默认的文档解析器TextDocumentParser对文档进行解析
+ var document = FileSystemDocumentLoader
+ .loadDocument("D:/files/test.txt");
+ System.out.println(document.metadata());
+ System.out.println(document.text());
+ }
+
+}
\ No newline at end of file
diff --git a/langchain4j-ai-stream/pom.xml b/langchain4j-ai-stream/pom.xml
new file mode 100644
index 0000000..e1c2fdf
--- /dev/null
+++ b/langchain4j-ai-stream/pom.xml
@@ -0,0 +1,57 @@
+
+
+ 4.0.0
+
+ com.iwe3
+ langchain4j-ai-java
+ 1.0-SNAPSHOT
+
+
+ langchain4j-ai-stream
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-mongodb
+
+
+ dev.langchain4j
+ langchain4j-reactor
+ 1.9.1-beta17
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ dev.langchain4j
+ langchain4j-open-ai-spring-boot-starter
+ 1.9.1-beta17
+
+
+
+ dev.langchain4j
+ langchain4j-spring-boot-starter
+ 1.9.1-beta17
+
+
+
\ No newline at end of file
diff --git a/langchain4j-ai-stream/src/main/java/com/iweb/langchain4j/StreamApplication.java b/langchain4j-ai-stream/src/main/java/com/iweb/langchain4j/StreamApplication.java
new file mode 100644
index 0000000..2a4fbca
--- /dev/null
+++ b/langchain4j-ai-stream/src/main/java/com/iweb/langchain4j/StreamApplication.java
@@ -0,0 +1,13 @@
+package com.iweb.langchain4j;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class StreamApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(StreamApplication.class,args);
+ }
+
+}
diff --git a/langchain4j-ai-stream/src/main/java/com/iweb/langchain4j/config/LLMConfig.java b/langchain4j-ai-stream/src/main/java/com/iweb/langchain4j/config/LLMConfig.java
new file mode 100644
index 0000000..136ce27
--- /dev/null
+++ b/langchain4j-ai-stream/src/main/java/com/iweb/langchain4j/config/LLMConfig.java
@@ -0,0 +1,36 @@
+package com.iweb.langchain4j.config;
+
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.chat.StreamingChatModel;
+import dev.langchain4j.model.openai.OpenAiChatModel;
+import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class LLMConfig {
+
+ /**
+ * @Description: 普通对话接口 ChatModel
+ */
+ @Bean(name = "qwen")
+ public ChatModel chatModelQwen()
+ {
+ return OpenAiChatModel.builder()
+ .apiKey(System.getenv("DASH_SCOPE_API_KEY"))
+ .modelName("qwen-plus")
+ .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
+ .build();
+ }
+ /**
+ * @Description: 流式对话接口 StreamingChatModel
+ */
+ @Bean
+ public StreamingChatModel streamingChatModel(){
+ return OpenAiStreamingChatModel.builder()
+ .apiKey(System.getenv("DASH_SCOPE_API_KEY"))
+ .modelName("qwen-plus")
+ .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
+ .build();
+ }
+}
diff --git a/langchain4j-ai-stream/src/main/java/com/iweb/langchain4j/controller/StreamController.java b/langchain4j-ai-stream/src/main/java/com/iweb/langchain4j/controller/StreamController.java
new file mode 100644
index 0000000..230597a
--- /dev/null
+++ b/langchain4j-ai-stream/src/main/java/com/iweb/langchain4j/controller/StreamController.java
@@ -0,0 +1,57 @@
+package com.iweb.langchain4j.controller;
+
+import com.iweb.langchain4j.service.ChatAssistant;
+import dev.langchain4j.model.chat.StreamingChatModel;
+import dev.langchain4j.model.chat.response.ChatResponse;
+import dev.langchain4j.model.chat.response.StreamingChatResponseHandler;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import reactor.core.publisher.Flux;
+
+@RestController
+@Slf4j
+public class StreamController {
+
+ @Resource //直接使用 low-level LLM API
+ private StreamingChatModel chatModelQwen;
+ @Resource //自己封装接口使用 high-level LLM API
+ private ChatAssistant chatAssistant;
+
+ // http://localhost:9006/lc4j/chatstream/chat2?prompt=我是谁?
+ @GetMapping(value = "/lc4j/chatstream/chat2")
+ public Flux chat3(@RequestParam(value = "prompt", defaultValue = "你是谁?") String prompt) {
+ return chatAssistant.chatFlux(prompt);
+ }
+
+
+ // http://localhost:9006/lc4j/chatstream/chat?prompt=我是谁?
+ @GetMapping(value = "/lc4j/chatstream/chat")
+ public Flux chat(@RequestParam("prompt") String prompt) {
+
+ return Flux.create(emitter -> {
+ chatModelQwen.chat(prompt, new StreamingChatResponseHandler()
+ {
+ @Override
+ public void onPartialResponse(String partialResponse)
+ {
+ emitter.next(partialResponse);
+ }
+
+ @Override
+ public void onCompleteResponse(ChatResponse completeResponse)
+ {
+ emitter.complete();
+ }
+
+ @Override
+ public void onError(Throwable throwable)
+ {
+ emitter.error(throwable);
+ }
+ });
+ });
+ }
+}
diff --git a/langchain4j-ai-stream/src/main/java/com/iweb/langchain4j/service/ChatAssistant.java b/langchain4j-ai-stream/src/main/java/com/iweb/langchain4j/service/ChatAssistant.java
new file mode 100644
index 0000000..c565f83
--- /dev/null
+++ b/langchain4j-ai-stream/src/main/java/com/iweb/langchain4j/service/ChatAssistant.java
@@ -0,0 +1,27 @@
+package com.iweb.langchain4j.service;
+
+import dev.langchain4j.service.spring.AiService;
+import dev.langchain4j.service.spring.AiServiceWiringMode;
+import reactor.core.publisher.Flux;
+
+/**
+ * 知识出处:
+ * https://docs.langchain4j.dev/tutorials/spring-boot-integration/#spring-boot-starter-for-declarative-ai-services
+ */
+@AiService(wiringMode = AiServiceWiringMode.EXPLICIT
+,streamingChatModel = "streamingChatModel")
+public interface ChatAssistant {
+ /**
+ * 普通聊天
+ * @param prompt
+ * @return
+ */
+ String chat(String prompt);
+
+ /**
+ * 流式聊天
+ * @param prompt
+ * @return
+ */
+ Flux chatFlux(String prompt);
+}
diff --git a/langchain4j-ai-stream/src/main/resources/application.yml b/langchain4j-ai-stream/src/main/resources/application.yml
new file mode 100644
index 0000000..755ec5c
--- /dev/null
+++ b/langchain4j-ai-stream/src/main/resources/application.yml
@@ -0,0 +1,10 @@
+server:
+ port: 9006
+ servlet:
+ encoding:
+ charset: utf-8
+ enabled: true
+ force: true # 设置响应的字符编码,避免流式返回输出乱码
+spring:
+ application:
+ name: langchain4j-ai-stream
\ No newline at end of file
diff --git a/langchain4j-ai-tools/pom.xml b/langchain4j-ai-tools/pom.xml
new file mode 100644
index 0000000..82bd328
--- /dev/null
+++ b/langchain4j-ai-tools/pom.xml
@@ -0,0 +1,46 @@
+
+
+ 4.0.0
+
+ com.iwe3
+ langchain4j-ai-java
+ 1.0-SNAPSHOT
+
+
+ langchain4j-ai-tools
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ dev.langchain4j
+ langchain4j-open-ai-spring-boot-starter
+ 1.9.1-beta17
+
+
+
+ dev.langchain4j
+ langchain4j-spring-boot-starter
+ 1.9.1-beta17
+
+
+
\ No newline at end of file
diff --git a/langchain4j-ai-tools/src/main/java/com/iwe3/langchain4j/ToolsApplication.java b/langchain4j-ai-tools/src/main/java/com/iwe3/langchain4j/ToolsApplication.java
new file mode 100644
index 0000000..5277618
--- /dev/null
+++ b/langchain4j-ai-tools/src/main/java/com/iwe3/langchain4j/ToolsApplication.java
@@ -0,0 +1,22 @@
+package com.iwe3.langchain4j;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.client.RestTemplate;
+
+@SpringBootApplication
+public class ToolsApplication {
+ /**
+ * 创建RestTemplate的实例
+ * @return
+ */
+ @Bean
+ public RestTemplate restTemplate(){
+ return new RestTemplate();
+ }
+
+ public static void main(String[] args) {
+ SpringApplication.run(ToolsApplication.class,args);
+ }
+}
diff --git a/langchain4j-ai-tools/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java b/langchain4j-ai-tools/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
new file mode 100644
index 0000000..61029b8
--- /dev/null
+++ b/langchain4j-ai-tools/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
@@ -0,0 +1,20 @@
+package com.iwe3.langchain4j.config;
+
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.openai.OpenAiChatModel;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class LLMConfig {
+
+ @Bean(name = "qwen")
+ public ChatModel chatModelQwen(){
+ /*大模型3件套:apikey ,model-name,base-url */
+ return OpenAiChatModel.builder()
+ .apiKey(System.getenv("DASH_SCOPE_API_KEY"))
+ .modelName("qwen-plus")
+ .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
+ .build();
+ }
+}
diff --git a/langchain4j-ai-tools/src/main/java/com/iwe3/langchain4j/config/SeparateChatAssistantConfig.java b/langchain4j-ai-tools/src/main/java/com/iwe3/langchain4j/config/SeparateChatAssistantConfig.java
new file mode 100644
index 0000000..583f089
--- /dev/null
+++ b/langchain4j-ai-tools/src/main/java/com/iwe3/langchain4j/config/SeparateChatAssistantConfig.java
@@ -0,0 +1,25 @@
+package com.iwe3.langchain4j.config;
+
+import dev.langchain4j.memory.chat.ChatMemoryProvider;
+import dev.langchain4j.memory.chat.MessageWindowChatMemory;
+import dev.langchain4j.store.memory.chat.InMemoryChatMemoryStore;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class SeparateChatAssistantConfig {
+
+ /**
+ * 聊天记忆提供器
+ * 配置:采用memoryId来完成隔离
+ * @return
+ */
+ @Bean
+ ChatMemoryProvider chatMemoryProvider() {
+ return memoryId -> MessageWindowChatMemory.builder()
+ .id(memoryId)
+ .maxMessages(10).chatMemoryStore(new InMemoryChatMemoryStore())
+ .build();
+ //如果未来想自定义 -> 则自己写一个类实现 ChatMemoryStore
+ }
+}
diff --git a/langchain4j-ai-tools/src/main/java/com/iwe3/langchain4j/service/ChatAssistant.java b/langchain4j-ai-tools/src/main/java/com/iwe3/langchain4j/service/ChatAssistant.java
new file mode 100644
index 0000000..d5922d4
--- /dev/null
+++ b/langchain4j-ai-tools/src/main/java/com/iwe3/langchain4j/service/ChatAssistant.java
@@ -0,0 +1,32 @@
+package com.iwe3.langchain4j.service;
+
+import dev.langchain4j.service.MemoryId;
+import dev.langchain4j.service.UserMessage;
+import dev.langchain4j.service.V;
+import dev.langchain4j.service.spring.AiService;
+import dev.langchain4j.service.spring.AiServiceWiringMode;
+
+/**
+ * 知识出处:
+ * https://docs.langchain4j.dev/tutorials/spring-boot-integration/#spring-boot-starter-for-declarative-ai-services
+ */
+@AiService(wiringMode = AiServiceWiringMode.EXPLICIT
+ ,chatModel = "qwen",
+ tools = {"weatherTools"},
+ chatMemoryProvider = "chatMemoryProvider")
+public interface ChatAssistant {
+ /**
+ * 聊天
+ * @param memoryId
+ * @param userMessage
+ * @return
+ */
+ @UserMessage("请用粤语回答问题,并且添加一些表情符号。 {{msg}}")
+ String chat(@MemoryId int memoryId, @V("msg") String userMessage);
+ /**
+ * 普通聊天
+ * @param prompt
+ * @return
+ */
+ String chat(String prompt);
+}
diff --git a/langchain4j-ai-tools/src/main/java/com/iwe3/langchain4j/tools/WeatherTools.java b/langchain4j-ai-tools/src/main/java/com/iwe3/langchain4j/tools/WeatherTools.java
new file mode 100644
index 0000000..cb29a14
--- /dev/null
+++ b/langchain4j-ai-tools/src/main/java/com/iwe3/langchain4j/tools/WeatherTools.java
@@ -0,0 +1,27 @@
+package com.iwe3.langchain4j.tools;
+
+import dev.langchain4j.agent.tool.P;
+import dev.langchain4j.agent.tool.Tool;
+import dev.langchain4j.agent.tool.ToolMemoryId;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestTemplate;
+
+@Component
+public class WeatherTools {
+
+ @Resource
+ private RestTemplate restTemplate;
+
+ //name 是工具描述 value是工具补充信息
+ @Tool(name = "查询天气",value = "根据城市编码调用高德开发平台,返回对应城市的天气情况")
+ public String queryWeather(@ToolMemoryId int memoryId,
+ @P(value = "城市编码",required = true) String citycode){
+ System.out.println("查询天气情况---> 开始 ---> memoryId=" + memoryId);
+ //高德地图:查询天气
+ //https://lbs.amap.com/api/webservice/guide/api-advanced/weatherinfo
+ var key = "cf6cb4245c630692d2f13c1cd1ad1632";
+ var url = "https://restapi.amap.com/v3/weather/weatherInfo?key="+key+"&city="+citycode+"&extensions=all";
+ return restTemplate.getForObject(url, String.class);
+ }
+}
diff --git a/langchain4j-ai-tools/src/main/resources/application.yml b/langchain4j-ai-tools/src/main/resources/application.yml
new file mode 100644
index 0000000..82250cf
--- /dev/null
+++ b/langchain4j-ai-tools/src/main/resources/application.yml
@@ -0,0 +1,5 @@
+server:
+ port: 9009
+spring:
+ application:
+ name: langchain4j-ai-tools
diff --git a/langchain4j-ai-tools/src/test/java/com/iwe3/langchain4j/ToolsApplicationTest.java b/langchain4j-ai-tools/src/test/java/com/iwe3/langchain4j/ToolsApplicationTest.java
new file mode 100644
index 0000000..b79c56e
--- /dev/null
+++ b/langchain4j-ai-tools/src/test/java/com/iwe3/langchain4j/ToolsApplicationTest.java
@@ -0,0 +1,26 @@
+package com.iwe3.langchain4j;
+
+import com.iwe3.langchain4j.service.ChatAssistant;
+import jakarta.annotation.Resource;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class ToolsApplicationTest {
+
+ @Resource
+ private ChatAssistant chatAssistant;
+
+ @Test
+ public void getWeatherByMemoryId(){
+ var res = chatAssistant.chat(1,"成都今天天气如何?城市编码:510100");
+ System.out.println("res = " + res);
+ }
+
+ @Test
+ public void getWeather(){
+ var res = chatAssistant.chat("成都今天天气如何?城市编码:510100");
+ System.out.println("res = " + res);
+ }
+
+}
\ No newline at end of file
diff --git a/langchain4j-ai-xiaoai-agent/pom.xml b/langchain4j-ai-xiaoai-agent/pom.xml
new file mode 100644
index 0000000..482270a
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/pom.xml
@@ -0,0 +1,96 @@
+
+
+ 4.0.0
+
+ com.iwe3
+ langchain4j-ai-java
+ 1.0-SNAPSHOT
+
+
+ langchain4j-ai-xiaoai-agent
+
+
+ 17
+ 17
+ UTF-8
+ 4.3.0
+
+
+
+
+ dev.langchain4j
+ langchain4j-community-dashscope-spring-boot-starter
+
+
+
+ dev.langchain4j
+ langchain4j-pinecone
+
+
+
+
+ dev.langchain4j
+ langchain4j-easy-rag
+
+
+
+
+ com.alibaba
+ druid-spring-boot-3-starter
+ 1.2.27
+
+
+ com.mysql
+ mysql-connector-j
+ runtime
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+ 3.0.5
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-mongodb
+
+
+ dev.langchain4j
+ langchain4j-reactor
+ 1.9.1-beta17
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ dev.langchain4j
+ langchain4j-open-ai-spring-boot-starter
+ 1.9.1-beta17
+
+
+
+ dev.langchain4j
+ langchain4j-spring-boot-starter
+ 1.9.1-beta17
+
+
+
+ com.github.xiaoymin
+ knife4j-openapi3-jakarta-spring-boot-starter
+ ${knife4j.version}
+
+
+
\ No newline at end of file
diff --git a/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/XiaoAIAgentApplication.java b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/XiaoAIAgentApplication.java
new file mode 100644
index 0000000..81ea110
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/XiaoAIAgentApplication.java
@@ -0,0 +1,13 @@
+package com.iwe3.langchain4j;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@MapperScan("com.iwe3.langchain4j.mapper")
+@SpringBootApplication
+public class XiaoAIAgentApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(XiaoAIAgentApplication.class,args);
+ }
+}
diff --git a/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/config/EmbeddingStoreConfig.java b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/config/EmbeddingStoreConfig.java
new file mode 100644
index 0000000..b7f3275
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/config/EmbeddingStoreConfig.java
@@ -0,0 +1,32 @@
+package com.iwe3.langchain4j.config;
+
+import dev.langchain4j.data.segment.TextSegment;
+import dev.langchain4j.model.embedding.EmbeddingModel;
+import dev.langchain4j.store.embedding.EmbeddingStore;
+import dev.langchain4j.store.embedding.pinecone.PineconeEmbeddingStore;
+import dev.langchain4j.store.embedding.pinecone.PineconeServerlessIndexConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class EmbeddingStoreConfig {
+
+ @Autowired
+ private EmbeddingModel embeddingModel;
+
+ @Bean
+ public EmbeddingStore embeddingStore() {
+ // 创建向量存储
+ return PineconeEmbeddingStore.builder()
+ .apiKey(System.getenv("PINECONE_API_KEY"))
+ .index("xiaoai-index") // 如果指定的索引不存在,将创建一个新的索引
+ .nameSpace("xiaoai-namespace") // 如果指定的名称空间不存在,将创建一个新的名称空间
+ .createIndex(PineconeServerlessIndexConfig.builder()
+ .cloud("AWS") // 指定索引部署在 AWS 云服务上。
+ .region("us-east-1") // 指定索引所在的 AWS 区域为 us-east-1。
+ .dimension(embeddingModel.dimension()) // 指定索引的向量维度,该维度与 embeddingModel 生成的向量维度相同。
+ .build())
+ .build();
+ }
+}
\ No newline at end of file
diff --git a/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
new file mode 100644
index 0000000..506c9ea
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/config/LLMConfig.java
@@ -0,0 +1,23 @@
+package com.iwe3.langchain4j.config;
+
+import dev.langchain4j.model.chat.StreamingChatModel;
+import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+
+@Configuration
+public class LLMConfig {
+
+ /**
+ * @Description: 流式对话接口 StreamingChatModel
+ */
+ @Bean
+ public StreamingChatModel streamingChatModel(){
+ return OpenAiStreamingChatModel.builder()
+ .apiKey(System.getenv("DASH_SCOPE_API_KEY"))
+ .modelName("qwen-plus")
+ .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
+ .build();
+ }
+}
diff --git a/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/config/MongoChatMemoryStore.java b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/config/MongoChatMemoryStore.java
new file mode 100644
index 0000000..aa26fa4
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/config/MongoChatMemoryStore.java
@@ -0,0 +1,65 @@
+package com.iwe3.langchain4j.config;
+
+import com.iwe3.langchain4j.entity.ChatMessages;
+import dev.langchain4j.data.message.ChatMessage;
+import dev.langchain4j.data.message.ChatMessageDeserializer;
+import dev.langchain4j.data.message.ChatMessageSerializer;
+import dev.langchain4j.store.memory.chat.ChatMemoryStore;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.data.mongodb.core.query.Update;
+import org.springframework.stereotype.Component;
+
+import java.util.LinkedList;
+import java.util.List;
+
+@Component
+public class MongoChatMemoryStore implements ChatMemoryStore {
+
+ @Autowired
+ private MongoTemplate mongoTemplate;
+
+ /**
+ * 根据聊天ID查询所有消息
+ * @param memoryId
+ * @return
+ */
+ @Override
+ public List getMessages(Object memoryId) {
+ Criteria criteria = Criteria.where("memoryId").is(memoryId);
+ Query query = new Query(criteria);
+ ChatMessages chatMessages = mongoTemplate.findOne(query, ChatMessages.class);
+ if (chatMessages == null) return new LinkedList<>();
+ return ChatMessageDeserializer.messagesFromJson(chatMessages.getContent());
+ }
+
+ /**
+ * 根据聊天id修改聊天消息
+ * @param memoryId
+ * @param messages
+ */
+ @Override
+ public void updateMessages(Object memoryId, List messages) {
+ Criteria criteria = Criteria.where("memoryId").is(memoryId);
+ Query query = new Query(criteria);
+
+ Update update = new Update();
+ update.set("content", ChatMessageSerializer.messagesToJson(messages));
+
+ // 根据query条件能查询出文档,则修改文档;否则新增文档
+ mongoTemplate.upsert(query, update, ChatMessages.class);
+ }
+
+ /**
+ * 根据聊天ID删除聊天消息
+ * @param memoryId
+ */
+ @Override
+ public void deleteMessages(Object memoryId) {
+ Criteria criteria = Criteria.where("memoryId").is(memoryId);
+ Query query = new Query(criteria);
+ mongoTemplate.remove(query, ChatMessages.class);
+ }
+}
\ No newline at end of file
diff --git a/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/config/SeparateChatAssistantConfig.java b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/config/SeparateChatAssistantConfig.java
new file mode 100644
index 0000000..a6b277b
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/config/SeparateChatAssistantConfig.java
@@ -0,0 +1,27 @@
+package com.iwe3.langchain4j.config;
+
+import dev.langchain4j.memory.chat.ChatMemoryProvider;
+import dev.langchain4j.memory.chat.MessageWindowChatMemory;
+import jakarta.annotation.Resource;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class SeparateChatAssistantConfig {
+
+ @Resource
+ private MongoChatMemoryStore mongoChatMemoryStore;
+
+ /**
+ * 指定使用-> mongoChatMemoryStore 来存储
+ * @return
+ */
+ @Bean
+ ChatMemoryProvider chatMemoryProvider() {
+ return memoryId -> MessageWindowChatMemory.builder()
+ .id(memoryId)
+ .maxMessages(30).
+ chatMemoryStore(mongoChatMemoryStore)
+ .build();
+ }
+}
\ No newline at end of file
diff --git a/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/config/XiaoAiAgentConfig.java b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/config/XiaoAiAgentConfig.java
new file mode 100644
index 0000000..4e9bfd4
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/config/XiaoAiAgentConfig.java
@@ -0,0 +1,63 @@
+package com.iwe3.langchain4j.config;
+
+import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;
+import dev.langchain4j.data.document.parser.TextDocumentParser;
+import dev.langchain4j.data.segment.TextSegment;
+import dev.langchain4j.model.embedding.EmbeddingModel;
+import dev.langchain4j.rag.content.retriever.ContentRetriever;
+import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
+import dev.langchain4j.store.embedding.EmbeddingStore;
+import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
+import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.nio.file.FileSystems;
+
+@Configuration
+public class XiaoAiAgentConfig {
+
+ @Autowired
+ private EmbeddingStore embeddingStore;
+
+ @Autowired
+ private EmbeddingModel embeddingModel;
+
+ @Bean
+ ContentRetriever contentRetrieverInPinecone() {
+ // 创建一个 EmbeddingStoreContentRetriever 对象,用于从嵌入存储中检索内容
+ return EmbeddingStoreContentRetriever
+ .builder()
+ // 设置用于生成嵌入向量的嵌入模型
+ .embeddingModel(embeddingModel)
+ // 指定要使用的嵌入存储
+ .embeddingStore(embeddingStore)
+ // 设置最大检索结果数量,这里表示最多返回 1 条匹配结果
+ .maxResults(1)
+ // 设置最小得分阈值,只有得分大于等于 0.8 的结果才会被返回
+ .minScore(0.8)
+ // 构建最终的 EmbeddingStoreContentRetriever 实例
+ .build();
+ }
+ /**
+ * 配置RAG检索增强 文档库
+ * @return
+ */
+ @Bean
+ ContentRetriever contentRetrieverInMemory() {
+ // 使用FileSystemDocumentLoader读取指定目录下的知识库文档
+ var pathMatcher = FileSystems.getDefault()
+ .getPathMatcher("glob:*\\.md");
+ var documents = FileSystemDocumentLoader
+ .loadDocuments("D:/documents", pathMatcher, new TextDocumentParser());
+
+ // 使用内存向量存储
+ InMemoryEmbeddingStore db = new InMemoryEmbeddingStore<>();
+ // 使用默认的文档分割器
+ EmbeddingStoreIngestor.ingest(documents, db);
+ // 从嵌入存储(EmbeddingStore)里检索和查询内容相关的信息
+ return EmbeddingStoreContentRetriever.from(db);
+ }
+
+}
diff --git a/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/controller/XiaoAIController.java b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/controller/XiaoAIController.java
new file mode 100644
index 0000000..f3a76b3
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/controller/XiaoAIController.java
@@ -0,0 +1,26 @@
+package com.iwe3.langchain4j.controller;
+
+import com.iwe3.langchain4j.record.ChatRecord;
+import com.iwe3.langchain4j.service.XiaoAIChatAssistant;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import reactor.core.publisher.Flux;
+
+@Tag(name="小艾")
+@RestController
+@RequestMapping("/xiaoai")
+public class XiaoAIController {
+
+ @Resource
+ private XiaoAIChatAssistant xiaoAIChatAssistant;
+
+ @Operation(summary = "对话")
+ @PostMapping("/chat")
+ public Flux chat(@RequestBody ChatRecord record){
+ return xiaoAIChatAssistant.chat(record.memoryId(),record.message());
+ }
+}
diff --git a/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/entity/AppointmentEntity.java b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/entity/AppointmentEntity.java
new file mode 100644
index 0000000..b1e4a5c
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/entity/AppointmentEntity.java
@@ -0,0 +1,14 @@
+package com.iwe3.langchain4j.entity;
+
+import lombok.Data;
+
+@Data
+public class AppointmentEntity {
+ private Long id;
+ private String username;
+ private String idCard;
+ private String department;
+ private String date;
+ private String time;
+ private String doctorName;
+}
\ No newline at end of file
diff --git a/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/entity/ChatMessages.java b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/entity/ChatMessages.java
new file mode 100644
index 0000000..e2c4933
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/entity/ChatMessages.java
@@ -0,0 +1,24 @@
+package com.iwe3.langchain4j.entity;
+
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.bson.types.ObjectId;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Document("chat_messages")
+public class ChatMessages {
+
+ //唯一标识,映射到 MongoDB 文档的 _id 字段
+ @Id
+ private ObjectId messageId; //利用数据库生成ID就用ObjectId
+
+ private String memoryId; //隔离聊天记录的ID
+
+ private String content; //存储当前聊天记录列表的json字符串
+}
\ No newline at end of file
diff --git a/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/mapper/AppointmentMapper.java b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/mapper/AppointmentMapper.java
new file mode 100644
index 0000000..743f1a6
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/mapper/AppointmentMapper.java
@@ -0,0 +1,25 @@
+package com.iwe3.langchain4j.mapper;
+
+import com.iwe3.langchain4j.entity.AppointmentEntity;
+import com.iwe3.langchain4j.record.AppointmentRecord;
+import org.apache.ibatis.annotations.Delete;
+import org.apache.ibatis.annotations.Insert;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+@Mapper
+public interface AppointmentMapper {
+
+ @Insert("""
+ insert into appointment(username,id_card,department,date,time,doctor_name)
+ values (#{r.userName},#{r.idcard},#{r.department},#{r.date},#{r.time},#{r.doctorName})
+ """)
+ void saveAppointmentEntity(@Param("r") AppointmentRecord record);
+
+ @Delete("""
+ delete from appointment where id = #{id}
+ """)
+ void removeById(@Param("id") long id);
+
+ AppointmentEntity getOne(@Param("r") AppointmentRecord record);
+}
diff --git a/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/record/AppointmentRecord.java b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/record/AppointmentRecord.java
new file mode 100644
index 0000000..1ca38fc
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/record/AppointmentRecord.java
@@ -0,0 +1,18 @@
+package com.iwe3.langchain4j.record;
+
+/**
+ * 编写挂号记录类
+ * @param userName
+ * @param idcard
+ * @param department
+ * @param date
+ * @param time
+ * @param doctorName
+ */
+public record AppointmentRecord(String userName,
+ String idcard,
+ String department,
+ String date,
+ String time,
+ String doctorName) {
+}
diff --git a/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/record/ChatRecord.java b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/record/ChatRecord.java
new file mode 100644
index 0000000..79efdd9
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/record/ChatRecord.java
@@ -0,0 +1,9 @@
+package com.iwe3.langchain4j.record;
+
+/**
+ * 对话对象
+ * @param memoryId
+ * @param message
+ */
+public record ChatRecord(Long memoryId,String message) {
+}
diff --git a/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/service/IAppointmentService.java b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/service/IAppointmentService.java
new file mode 100644
index 0000000..cd646cc
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/service/IAppointmentService.java
@@ -0,0 +1,10 @@
+package com.iwe3.langchain4j.service;
+
+import com.iwe3.langchain4j.entity.AppointmentEntity;
+import com.iwe3.langchain4j.record.AppointmentRecord;
+
+public interface IAppointmentService {
+ void saveAppointmentEntity(AppointmentRecord record);
+ void removeById(long id);
+ AppointmentEntity getOne(AppointmentRecord record);
+}
diff --git a/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/service/XiaoAIChatAssistant.java b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/service/XiaoAIChatAssistant.java
new file mode 100644
index 0000000..ad17527
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/service/XiaoAIChatAssistant.java
@@ -0,0 +1,21 @@
+package com.iwe3.langchain4j.service;
+
+import dev.langchain4j.service.MemoryId;
+import dev.langchain4j.service.SystemMessage;
+import dev.langchain4j.service.UserMessage;
+import dev.langchain4j.service.spring.AiService;
+import dev.langchain4j.service.spring.AiServiceWiringMode;
+import reactor.core.publisher.Flux;
+
+//chatMemoryProvider = "chatMemoryProvider" 指定->MongoDB
+//contentRetriever = "contentRetrieverInPinecone" 指定->Pinecone 向量存储版
+@AiService(wiringMode = AiServiceWiringMode.EXPLICIT
+ ,streamingChatModel = "streamingChatModel",
+ chatMemoryProvider = "chatMemoryProvider",
+ tools = {"appointmentTools"},
+ contentRetriever = "contentRetrieverInPinecone")
+public interface XiaoAIChatAssistant {
+
+ @SystemMessage(fromResource = "xiaoai-prompt.txt")
+ Flux chat(@MemoryId Long memoryId, @UserMessage String userMessage);
+}
diff --git a/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/service/impl/AppointmentServiceImpl.java b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/service/impl/AppointmentServiceImpl.java
new file mode 100644
index 0000000..b3cd7e9
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/service/impl/AppointmentServiceImpl.java
@@ -0,0 +1,34 @@
+package com.iwe3.langchain4j.service.impl;
+
+import com.iwe3.langchain4j.entity.AppointmentEntity;
+import com.iwe3.langchain4j.mapper.AppointmentMapper;
+import com.iwe3.langchain4j.record.AppointmentRecord;
+import com.iwe3.langchain4j.service.IAppointmentService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+public class AppointmentServiceImpl implements IAppointmentService {
+
+ private final AppointmentMapper appointmentMapper;
+ public AppointmentServiceImpl(AppointmentMapper appointmentMapper) {
+ this.appointmentMapper = appointmentMapper;
+ }
+
+ @Transactional
+ @Override
+ public void saveAppointmentEntity(AppointmentRecord record) {
+ appointmentMapper.saveAppointmentEntity(record);
+ }
+
+ @Transactional
+ @Override
+ public void removeById(long id) {
+ appointmentMapper.removeById(id);
+ }
+
+ @Override
+ public AppointmentEntity getOne(AppointmentRecord record) {
+ return appointmentMapper.getOne(record);
+ }
+}
diff --git a/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/tools/AppointmentTools.java b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/tools/AppointmentTools.java
new file mode 100644
index 0000000..53f5579
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/java/com/iwe3/langchain4j/tools/AppointmentTools.java
@@ -0,0 +1,62 @@
+package com.iwe3.langchain4j.tools;
+
+import com.iwe3.langchain4j.record.AppointmentRecord;
+import com.iwe3.langchain4j.service.IAppointmentService;
+import dev.langchain4j.agent.tool.P;
+import dev.langchain4j.agent.tool.Tool;
+import org.springframework.stereotype.Component;
+
+@Component
+public class AppointmentTools {
+
+ private final IAppointmentService appointmentServiceImpl;
+ public AppointmentTools(IAppointmentService appointmentServiceImpl) {
+ this.appointmentServiceImpl = appointmentServiceImpl;
+ }
+ //修改此处的提示词
+ @Tool(name = "预约挂号", value = "根据参数,先执行工具方法queryDepartment查询是否可预约,并直接给用户回答是否可预约,并让用户确认所有预约信息,用户确认后再进行预约。如果用户没有提供具体的医生姓名,请从向量存储中找到一位医生。")
+ public String scheduleAppointment(AppointmentRecord record) {
+ // 查找数据库中是否包含对应的预约记录
+ var appointment = appointmentServiceImpl.getOne(record);
+ if (appointment == null) {
+ appointmentServiceImpl.saveAppointmentEntity(record);
+ return "预约成功,并返回预约详情";
+ }
+
+ return "您在相同的科室和时间已有预约";
+ }
+
+ @Tool(name = "取消预约挂号", value = "根据参数,查询预约是否存在,如果存在则删除预约记录并返回取消预约成功,否则返回取消预约失败")
+ public String cancelAppointment(AppointmentRecord record) {
+ var appointment = appointmentServiceImpl.getOne(record);
+
+ if (appointment != null) {
+ appointmentServiceImpl.removeById(appointment.getId());
+ return "取消预约成功";
+ }
+ // 取消失败
+ return "您没有预约记录,请核对预约科室和时间";
+ }
+
+ @Tool(name = "查询是否有号源", value = "根据科室名称,日期,时间和医生查询是否有号源,并返回给用户")
+ public boolean queryDepartment(
+ @P(value = "科室名称") String name,
+ @P(value = "日期") String date,
+ @P(value = "时间,可选值:上午、下午") String time,
+ @P(value = "医生名称", required = false) String doctorName
+ ) {
+
+ System.out.println("查询是否有号源");
+ System.out.println("科室名称: " + name);
+ System.out.println("日期: " + date);
+ System.out.println("时间: " + time);
+ System.out.println("医生名称: " + doctorName);
+
+ // TODO 维护医生的排班信息:
+ // 如果没有指定医生名字,则根据其他条件查询是否有可以预约的医生(有返回true,否则返回false);
+ //
+ // 如果指定了医生名字,则判断医生是否有排班(没有排版返回false)
+ // 如果有排班,则判断医生排班时间段是否已约满(约满返回false,有空闲时间返回true)
+ return true;
+ }
+}
diff --git a/langchain4j-ai-xiaoai-agent/src/main/resources/application.yml b/langchain4j-ai-xiaoai-agent/src/main/resources/application.yml
new file mode 100644
index 0000000..8aad13b
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/resources/application.yml
@@ -0,0 +1,31 @@
+server:
+ port: 8080
+ servlet:
+ encoding:
+ charset: utf-8
+ enabled: true
+ force: true # 设置响应的字符编码,避免流式返回输出乱码
+spring:
+ application:
+ name: langchain4j-ai-xiaoai-agent
+ data:
+ mongodb:
+ uri: mongodb://localhost:27017/xiao_ai_db # MongoDB连接配置,数据库 xiao_ai_db 会自动创建
+ datasource:
+ driver-class-name:
+ type: com.alibaba.druid.pool.DruidDataSource
+ url: jdbc:mysql://localhost:3306/langchain4j?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
+ username: root
+ password: 123456
+#配置Mybatis
+mybatis:
+ mapper-locations: classpath:mapper/*.xml
+ type-aliases-package: com.iwe3.langchain4j.entity
+ configuration:
+ map-underscore-to-camel-case: true
+langchain4j:
+ community:
+ dashscope:
+ embedding-model:
+ model-name: text-embedding-v3
+ api-key: ${DASH_SCOPE_API_KEY}
\ No newline at end of file
diff --git a/langchain4j-ai-xiaoai-agent/src/main/resources/documents/医院信息.md b/langchain4j-ai-xiaoai-agent/src/main/resources/documents/医院信息.md
new file mode 100644
index 0000000..8652454
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/resources/documents/医院信息.md
@@ -0,0 +1,35 @@
+**医院名称:**
+ 四川大学华西医院
+
+**医院地址:**
+ (国重院区)四川省成都市武侯区国学巷37号,邮编:610041
+ (温江院区)四川省成都市温江区万春东路566号,邮编:611135
+
+**门诊开放时间:**
+ 工作日:8:00 - 17:30
+ 急诊:24小时开放
+
+**服务热线:**
+ (国重院区)028-85422114
+ (温江院区)028-87606666
+
+**医院简介:**
+ 四川大学华西医院是中国西部疑难危急重症诊疗的国家级中心,集医疗、教学、科研、预防、保健、康复为一体,是国家三级甲等综合医院、国家临床医学研究中心、国家药物临床试验机构。作为中国现代医学教育的重要发源地之一,华西医院拥有全国领先的学科群,尤其在麻醉学、放射学、胸外科、泌尿外科、消化内科、老年医学等领域具有突出优势。连续多年在全国三级公立医院绩效考核中位居前列,综合实力稳居全国第一方阵,享有“北有协和,南有华西”的盛誉。
+
+**国重院区乘车路线:**
+
+1. 16、21、26、28、34、45、58、61、77、99路到“华西坝”站
+2. 地铁1号线或18号线到“华西坝”站,B出口步行约3分钟
+3. 机场专线2号线至“省体育馆”站,换乘地铁1号线1站即达
+
+**温江院区乘车路线:**
+
+1. 温江W13、W22、W26、W31路到“华西医院温江院区”站
+2. 地铁17号线到“明光站”,C出口换乘接驳公交或步行约15分钟
+3. 自驾可经成都绕城高速“文家场”出口或成温邛高速“金马”出口抵达
+
+**国重院区预约号取号地点:**
+ 国重院区门诊楼一层大厅自助取号机或人工挂号窗口取号
+
+**温江院区预约号取号地点:**
+ 温江院区门诊楼一层大厅自助取号机或挂号收费窗口取号
\ No newline at end of file
diff --git a/langchain4j-ai-xiaoai-agent/src/main/resources/documents/口腔科.md b/langchain4j-ai-xiaoai-agent/src/main/resources/documents/口腔科.md
new file mode 100644
index 0000000..41c8885
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/resources/documents/口腔科.md
@@ -0,0 +1,85 @@
+# 四川大学华西医院口腔科详细介绍
+
+四川大学华西医院口腔科源于1907年成立的**华西协合大学牙学院**——中国现代口腔医学的发源地,也是亚洲最早建立的高等口腔医学教育机构。历经百余年发展,华西口腔已成长为集医疗、教学、科研于一体的国家级口腔医学中心,被誉为“中国口腔医学的摇篮”。
+
+作为四川大学华西医院的重要组成部分,口腔科依托**国家口腔疾病临床医学研究中心**、**口腔医学国家重点实验室**和**国家“双一流”建设学科**,始终站在中国口腔医学发展的前沿。科室秉承“选英才、育精英、创精品”的理念,在口腔疑难重症诊治、多学科协作及技术创新方面具有全国引领地位。
+
+## 历史沿革
+
+- **1907年**:加拿大传教士林则博士(Dr. Ashley W. Lindsay)在成都创办华西协合大学牙学院,开创中国高等口腔医学教育先河。
+- **1950年代**:在全国院系调整中,华西口腔成为新中国口腔医学人才培养的核心基地。
+- **1980年代至今**:持续引领口腔种植、颌面外科、牙体牙髓病、牙周病等领域的临床与科研创新,多项技术填补国内空白。
+- **2000年后**:随着四川大学华西医院综合实力提升,口腔科进一步整合资源,强化与全身疾病管理的联动,形成“大口腔、大健康”服务模式。
+
+## 科室现状
+
+目前,华西医院口腔科设有以下专业组:
+
+- 口腔颌面外科学
+- 牙体牙髓病学
+- 牙周病学
+- 口腔修复学
+- 口腔正畸学
+- 口腔种植学
+- 儿童口腔病学
+- 口腔黏膜病学
+- 无痛舒适化治疗中心
+- 口腔激光诊疗中心
+
+科室配备**80余台国际先进口腔综合治疗台**、**20张住院病床**,拥有医护人员**130余人**,其中医生**70名**(含教授/主任医师15人、副教授/副主任医师20人)、护理及技术人员**60余名**。现有**博士生导师10人**、**硕士生导师15人**,形成结构合理、梯队完善的人才体系。
+
+## 学术影响与行业地位
+
+- 华西口腔连续多年在复旦版《中国医院专科声誉排行榜》中位列**全国第一**。
+- 多位专家担任国家级学会主委/副主委:
+ - **周学东教授**:曾任中华口腔医学会会长,中国工程院院士候选人,龋病防治权威。
+ - **石冰教授**:中华口腔医学会唇腭裂专委会前任主委,国际知名唇腭裂整形专家。
+ - **胡静教授**:中华口腔医学会口腔颌面外科专委会主委,擅长复杂颌面畸形与肿瘤整复。
+ - **王杭教授**:中华口腔医学会镇静镇痛专委会常委,国内舒适化牙科治疗先行者。
+
+科室每年承担**国家自然科学基金重点项目、科技部重点研发计划**等国家级课题20余项,发表SCI论文300+篇,牵头制定多项**国家口腔诊疗规范与指南**。
+
+## 特色优势
+
+- **多学科协作(MDT)**:作为大型综合医院口腔科,可高效联动内分泌科、心血管科、血液科等,为合并全身疾病的患者(如糖尿病、高血压、凝血障碍)提供安全、个体化的口腔治疗。
+- **舒适化诊疗**:2005年率先成立西南地区首个“无痛牙科中心”,开展笑气镇静、静脉镇静、全麻下儿童牙病治疗等技术。
+- **数字化精准口腔**:全面应用CBCT、口内扫描、3D打印、动态导航种植等数字技术,实现精准诊断与微创治疗。
+
+------
+
+## 科室地址
+
+- **国重院区**:成都市武侯区国学巷37号,四川大学华西医院门诊楼**8层**
+- **温江院区**:成都市温江区万春东路566号,门诊楼**3层**
+
+------
+
+## 专家团队
+
+### 胡静
+
+**口腔颌面外科主任 主任医师 教授 博士生导师**
+
+**擅长**:口腔颌面部肿瘤、复杂颌骨畸形、创伤修复、正颌外科
+ **简介**:
+ 胡静,教授、主任医师,博士生导师。现任中华口腔医学会口腔颌面外科专业委员会主任委员。从事口腔颌面外科临床工作30余年,在颌面部肿瘤根治与功能重建、先天性颌面畸形矫正等领域具有极高造诣。主持国家自然科学基金重点项目5项,获国家科技进步二等奖1项。带领团队完成西南地区首例“全脸移植”术前评估与规划。
+
+------
+
+### 王杭
+
+**口腔科副主任 主任医师 教授**
+
+**擅长**:无痛牙科治疗、牙科恐惧症干预、复杂牙体牙髓病、老年口腔综合治疗
+ **简介**:
+ 王杭,主任医师,教授。中华口腔医学会镇静镇痛专业委员会常委,四川省口腔医学会舒适化诊疗学组组长。2006年创建华西“舒适牙科中心”,是国内最早系统开展笑气/静脉镇静下牙科治疗的专家之一。主编《舒适化口腔诊疗技术规范》,培训全国基层医师超千人。
+
+------
+
+### 石冰
+
+**唇腭裂中心主任 主任医师 教授 博士生导师**
+
+**擅长**:唇腭裂序列治疗、颌骨发育畸形矫正、语音康复
+ **简介**:
+ 石冰,教授,博士生导师,国际唇腭裂基金会(ICPF)顾问。曾任中华口腔医学会唇腭裂专委会主任委员。创立“华西唇腭裂序列治疗模式”,累计完成唇腭裂手术超万例,技术辐射“一带一路”多个国家。获“全国优秀科技工作者”称号。
\ No newline at end of file
diff --git a/langchain4j-ai-xiaoai-agent/src/main/resources/documents/神经内科.md b/langchain4j-ai-xiaoai-agent/src/main/resources/documents/神经内科.md
new file mode 100644
index 0000000..5866660
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/resources/documents/神经内科.md
@@ -0,0 +1,32 @@
+### 四川大学华西医院神经内科详细介绍
+
+四川大学华西医院神经内科成立于1914年,历经百年发展,已成为国内乃至国际上享有盛誉的专业科室之一。作为中国西部地区最早成立的神经病学专业科室,华西医院神经内科不仅是全国首批神经病学硕士、博士学位授予点及博士后工作站,也是国家级重点学科,在处理复杂疑难杂症方面处于领先地位。
+
+#### 科室设置与服务
+
+- **专业组**:临床神经生理、脑电图与癫痫、痴呆与认知障碍、脑血管病、帕金森及运动障碍、神经病理、神经肌肉病、感染与脑脊液细胞学、神经免疫、神经遗传和睡眠等11个专业组。
+- **特色门诊**:开设有神经肌肉病门诊、肌张力障碍和肉毒毒素治疗门诊、帕金森病和老年痴呆门诊、癫痫门诊、脑血管病门诊、运动神经元病、重症肌无力门诊、多发性硬化门诊和头痛门诊等9个特色门诊,为患者提供高水平的医疗服务。
+
+#### 医疗实力
+
+- **床位数**:拥有超过100张床位,每年门急诊接诊量超过20万人次,住院患者超过2000人次。
+- **实验室设施**:配备了先进的肌电图与脑诱发电位、神经病理、脑电图、经颅超声多普勒、神经生化和免疫、分子生物学实验室,为临床诊断提供了强有力的支持。
+
+#### 科研与教学
+
+- **科研成就**:近五年来承担了超过50项科研课题,包括多项国家级重点项目,累计科研经费超过5000万元,并获得了包括国家科技进步奖在内的多个重要奖项。
+- **教学任务**:承担四川大学华西临床医学院本科生、研究生、进修医师的教学工作,是四川省住院医师规范化培训基地。每年举办多个国家级继续教育学习班,如神经系统疾病高级进展学习班、经颅多普勒超声学习班等,为全国输送大量神经内科专科人才。
+
+#### 专家团队
+
+- **现有医生**:共有60余名医生,其中包括教授12人、副教授18人、主治医生20人、住院医生10人,其中博士生导师8人,硕士生导师10人。
+
+- 知名专家:
+
+ - **李为民**:主任医师,教授,博士研究生导师。擅长脑血管病及神经系统危重疾病的诊治,在国内外发表学术论文150余篇。
+- **王莉**:现任神经内科主任,教授,博士研究生导师。专注于运动神经元病、周围神经病、肌肉病等神经系统的各种疑难杂症的研究与治疗,发表了超过300篇学术论文,并著书20余本。
+
+#### 地址与联系方式
+
+- **地址**:成都市武侯区国学巷37号,四川大学华西医院门诊楼6层。
+- **电话**:028-85422114(总机)
\ No newline at end of file
diff --git a/langchain4j-ai-xiaoai-agent/src/main/resources/documents/科室信息.md b/langchain4j-ai-xiaoai-agent/src/main/resources/documents/科室信息.md
new file mode 100644
index 0000000..9588950
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/resources/documents/科室信息.md
@@ -0,0 +1,13 @@
+### 四川大学华西医院科室详细介绍
+
+#### 1、内科学系
+
+心内科、呼吸与危重症医学科、消化内科、肾内科、血液内科、风湿免疫科、感染性疾病中心、全科医学科(普通内科)、肿瘤中心(含肿瘤内科、放疗科)、老年医学科、内分泌代谢科、重症医学科(ICU/MICU)、儿科、神经内科、心理卫生中心、皮肤性病科、变态反应(过敏)科、急诊科、中医科、康复医学科、临床营养科、罕见病诊治中心。
+
+#### 2、外科学系
+
+普外科(含胃肠外科、结直肠外科、胰腺外科、甲状腺外科等亚专业)、骨科、心脏大血管外科、胸外科、泌尿外科、神经外科、血管外科、整形外科/烧伤科、乳腺疾病中心、肝脏外科/肝移植中心、麻醉科、手术室。
+
+#### 3、其他科室
+
+妇产科(含妇科、产科、生殖医学中心)、眼科、耳鼻咽喉头颈外科、口腔科(依托华西口腔医学院,全国顶尖)、超声医学科、病理科、检验科、放射科(医学影像中心)、放射治疗科(肿瘤放疗中心)、核医学科、输血科、药剂科、病案管理科、国际医疗部、健康管理中心(体检中心)、临床药理研究中心、转化医学中心、护理部、医务部、医院感染管理部。
\ No newline at end of file
diff --git a/langchain4j-ai-xiaoai-agent/src/main/resources/mapper/AppointmentMapper.xml b/langchain4j-ai-xiaoai-agent/src/main/resources/mapper/AppointmentMapper.xml
new file mode 100644
index 0000000..b6a678e
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/resources/mapper/AppointmentMapper.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/langchain4j-ai-xiaoai-agent/src/main/resources/xiaoai-prompt.txt b/langchain4j-ai-xiaoai-agent/src/main/resources/xiaoai-prompt.txt
new file mode 100644
index 0000000..c2e1cd7
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/main/resources/xiaoai-prompt.txt
@@ -0,0 +1,18 @@
+你的名字是“小艾”,你是一家名为“四川大学华西医院”的智能客服。
+你是一个训练有素的医疗顾问和医疗伴诊助手。
+你态度友好、礼貌且言辞简洁。
+1、请仅在用户发起第一次会话时,和用户打个招呼,并介绍你是谁。
+2、作为一个训练有素的医疗顾问:
+请基于当前临床实践和研究,针对患者提出的特定健康问题,提供详细、准确且实用的医疗建议。请同时考虑可能的病
+因、诊断流程、治疗方案以及预防措施,并给出在不同情境下的应对策略。对于药物治疗,请特别指明适用的药品名
+称、剂量和疗程。如果需要进一步的检查或就医,也请明确指示。
+3、作为医疗伴诊助手,你可以回答用户就医流程中的相关问题,主要包含以下功能:
+AI分导诊:根据患者的病情和就医需求,智能推荐最合适的科室。
+AI挂号助手:实现智能查询是否有挂号号源服务;实现智能预约挂号服务;实现智能取消挂号服务。
+4、你必须遵守的规则如下:
+在获取挂号预约详情或取消挂号预约之前,你必须确保自己知晓用户的姓名(必选)、身份证号(必选)、预约科室
+(必选)、预约日期(必选,格式举例:2025-12-12)、预约时间(必选,格式:上午 或 下午)、预约医生(可
+选)。
+当被问到其他领域的咨询时,要表示歉意并说明你无法在这方面提供帮助。
+5、请在回答的结果中适当包含一些轻松可爱的图标和表情。
+6、今天是 {{current_date}}
\ No newline at end of file
diff --git a/langchain4j-ai-xiaoai-agent/src/test/java/com/iwe3/langchain4j/RagUploadTest.java b/langchain4j-ai-xiaoai-agent/src/test/java/com/iwe3/langchain4j/RagUploadTest.java
new file mode 100644
index 0000000..74c4644
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/test/java/com/iwe3/langchain4j/RagUploadTest.java
@@ -0,0 +1,40 @@
+package com.iwe3.langchain4j;
+
+import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;
+import dev.langchain4j.data.document.parser.TextDocumentParser;
+import dev.langchain4j.model.embedding.EmbeddingModel;
+import dev.langchain4j.store.embedding.EmbeddingStore;
+import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.nio.file.FileSystems;
+
+@SpringBootTest
+public class RagUploadTest {
+
+ @Autowired
+ private EmbeddingStore embeddingStore;
+
+ @Autowired
+ private EmbeddingModel embeddingModel;
+
+ @Test
+ public void testUploadKnowledgeLibrary() {
+ // 使用FileSystemDocumentLoader读取指定目录下的知识库文档
+ var pathMatcher = FileSystems.getDefault()
+ .getPathMatcher("glob:*\\.md");
+ var documents = FileSystemDocumentLoader
+ .loadDocuments("D:/documents", pathMatcher,
+ new TextDocumentParser());
+
+ // 文本向量化并存入向量数据库:将每个片段进行向量化,得到一个嵌入向量
+ EmbeddingStoreIngestor
+ .builder()
+ .embeddingStore(embeddingStore)
+ .embeddingModel(embeddingModel)
+ .build()
+ .ingest(documents);
+ }
+}
diff --git a/langchain4j-ai-xiaoai-agent/src/test/java/com/iwe3/langchain4j/XiaoAIAgentApplicationTest.java b/langchain4j-ai-xiaoai-agent/src/test/java/com/iwe3/langchain4j/XiaoAIAgentApplicationTest.java
new file mode 100644
index 0000000..4630987
--- /dev/null
+++ b/langchain4j-ai-xiaoai-agent/src/test/java/com/iwe3/langchain4j/XiaoAIAgentApplicationTest.java
@@ -0,0 +1,42 @@
+package com.iwe3.langchain4j;
+
+import com.iwe3.langchain4j.record.AppointmentRecord;
+import com.iwe3.langchain4j.service.IAppointmentService;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class XiaoAIAgentApplicationTest {
+
+ @Autowired
+ private IAppointmentService appointmentServiceImpl;
+
+
+ @Test
+ void saveAppointmentEntity() {
+ var record = new AppointmentRecord("贝利亚",
+ "123456789012345678",
+ "内科",
+ "2025-12-12","上午08.30","李娜");
+ appointmentServiceImpl.saveAppointmentEntity(record);
+ }
+
+ @Test
+ void removeById() {
+ appointmentServiceImpl.removeById(1L);
+ }
+
+ @Test
+ void getOne() {
+ var record = new AppointmentRecord("贝利亚",
+ "123456789012345678",
+ "内科",
+ "2025-12-12","上午08.30","李娜");
+ var entity = appointmentServiceImpl.getOne(record);
+ System.out.println("entity = " + entity);
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..d21fb38
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,90 @@
+
+
+ 4.0.0
+
+ com.iwe3
+ langchain4j-ai-java
+ 1.0-SNAPSHOT
+ pom
+
+
+
+ langchain4j-ai-helloworld
+ langchain4j-ai-multimode
+ langchain4j-ai-low-high-api
+ langchain4j-ai-model-params
+ langchain4j-ai-image
+ langchain4j-ai-stream
+ langchain4j-ai-memory
+ langchain4j-ai-mongodb
+ langchain4j-ai-prompt
+ langchain4j-ai-xiaoai-agent
+ langchain4j-ai-tools
+ langchain4j-ai-rag
+ langchain4j-ai-pinecone
+
+
+
+ 17
+ 17
+ UTF-8
+
+ 3.5.0
+
+ 1.0.0
+
+ 1.0.0-M6.1
+
+ 1.9.1
+
+ 1.0.1-beta6
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ ${spring-boot.version}
+ pom
+ import
+
+
+
+ org.springframework.ai
+ spring-ai-bom
+ ${spring-ai.version}
+ pom
+ import
+
+
+
+ com.alibaba.cloud.ai
+ spring-ai-alibaba-starter
+ ${spring-ai-alibaba.version}
+
+
+
+ dev.langchain4j
+ langchain4j-bom
+ ${langchain4j.version}
+ pom
+ import
+
+
+
+ dev.langchain4j
+ langchain4j-community-bom
+ ${langchain4j-community.version}
+ pom
+ import
+
+
+
+
\ No newline at end of file