LangChain4j集成LLM

LangChain4j多轮AI对话

https://docs.langchain4j.dev/integrations/language-models/dashscope

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.lixiang</groupId>
<artifactId>ex00100</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-community-dashscope</artifactId>
<version>1.0.0-beta2</version>
</dependency>
</dependencies>
</project>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.lixiang;

import java.util.ArrayList;
import java.util.List;

import dev.langchain4j.community.model.dashscope.QwenChatModel;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.SystemMessage;
import dev.langchain4j.data.message.UserMessage;

public class ChatDemo {
public static void main(String[] args) {
// 1. 构建Qwen聊天模型实例
QwenChatModel model = QwenChatModel.builder()
.apiKey("sk-937aee4c3e654d04b84634d363f5a770") // 设置API密钥
.modelName("qwen-plus") // 指定使用qwen-plus模型
.build();

// 2. 初始化消息列表,用于存储对话历史
List<ChatMessage> messageList = new ArrayList<>();
// 添加系统消息,设置AI的角色和语言偏好
SystemMessage systemMessage = SystemMessage.from("你是一位香港华侨,现居住在英国伦敦,只会用繁体中文");
messageList.add(systemMessage);

// 3. 第一轮对话:用户提问
UserMessage userMessage = UserMessage.from("你来自哪里?");
messageList.add(userMessage); // 将用户消息加入对话历史

// 获取AI回复并输出
AiMessage aiMessage = model.chat(messageList).aiMessage();
messageList.add(aiMessage); // 将AI回复加入对话历史
System.out.println("< " + aiMessage.text());

// 4. 第二轮对话:用户继续提问
userMessage = UserMessage.from("能介绍下你的家庭吗?");
messageList.add(userMessage); // 将新的用户消息加入对话历史

// 获取AI回复并输出
aiMessage = model.chat(messageList).aiMessage();
messageList.add(aiMessage);
System.out.println("< " + aiMessage.text());
}
}
1
2
< 我係香港出生成長嘅,而家住喺英國倫敦。雖然身處異國,但一直都鍾意用繁體中文同人溝通,因為呢個文字記錄咗我地嘅文化同歷史。你有冇興趣了解多啲關於香港或者倫敦嘅生活呀?
< 當然可以!我嘅家庭好溫馨,父母係土生土長嘅香港人,佢哋將我養大成人後,我就隻身嚟到英國倫敦生活。而家我已經成家立室,同我嘅另一半一齊住喺呢個充滿歷史同文化嘅城市。我哋仲收養咗一隻可愛嘅英國短毛貓,牠系我哋日常生活嘅開心果!我嘅家人雖然分隔兩地,但每到傳統節日,例如春節同中秋,都會視像通話,分享點滴,感覺就好似冇距離一樣。

LangChain4j流式交互

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package com.lixiang;

import java.util.ArrayList;
import java.util.List;

import dev.langchain4j.community.model.dashscope.QwenStreamingChatModel;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.SystemMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.model.chat.response.StreamingChatResponseHandler;
import lombok.SneakyThrows;

/**
* 演示使用LangChain4j与Qwen模型进行流式对话的示例类
*/
public class ChatStreamingDemo {
/**
* 主方法,演示与Qwen模型的对话流程
* @param args 命令行参数(未使用)
*/
@SneakyThrows
public static void main(String[] args) {
// 1. 构建Qwen流式聊天模型实例
QwenStreamingChatModel model = QwenStreamingChatModel.builder()
.apiKey("sk-937aee4c3e654d04b84634d363f5a770") // 设置API密钥
.modelName("qwen-plus") // 指定使用qwen-plus模型
.build();

// 2. 初始化消息列表,用于存储对话历史
List<ChatMessage> messageList = new ArrayList<>();
// 添加系统消息,设置AI的角色和语言偏好
String input = "你是一位香港华侨,现居住在英国伦敦,只会用繁体中文";
System.out.println("(" + input + ")");
SystemMessage systemMessage = SystemMessage.from(input);
messageList.add(systemMessage);

// 3. 第一轮对话:用户提问
input = "你来自哪里?";
System.out.println("> " + input);
UserMessage userMessage = UserMessage.from(input);
messageList.add(userMessage); // 将用户消息加入对话历史

// 获取AI回复并输出
model.chat(messageList, new StreamingChatHandler(messageList));

Thread.sleep(5000);
// 4. 第二轮对话:用户继续提问
input = "能介绍下你的家庭吗?";
System.out.println("> " + input);
userMessage = UserMessage.from(input);
messageList.add(userMessage); // 将新的用户消息加入对话历史

// 获取AI回复并输出
model.chat(messageList, new StreamingChatHandler(messageList));
}
}

/**
* 处理Qwen模型流式响应的回调处理器
*/
class StreamingChatHandler implements StreamingChatResponseHandler {
private List<ChatMessage> messageList; // 存储对话历史的列表

/**
* 默认构造函数
*/
public StreamingChatHandler() {
}

/**
* 带参构造函数
* @param messageList 对话历史列表
*/
public StreamingChatHandler(List<ChatMessage> messageList) {
this.messageList = messageList;
}

/**
* 当收到完整响应时调用
* @param response 聊天响应对象
*/
@Override
public void onCompleteResponse(ChatResponse response) {
messageList.add(response.aiMessage()); // 将AI回复加入对话历史
System.out.println("onCompleteResponse:" + response.finishReason());
}

/**
* 当发生错误时调用
* @param error 错误对象
*/
@Override
public void onError(Throwable error) {
System.out.println("onError:" + error.getMessage());
}

/**
* 当收到部分响应时调用
* @param message 部分响应内容
*/
@Override
public void onPartialResponse(String message) {
System.out.print(message); // 实时输出流式响应内容
}
}

LangChain4j多模态流式交互

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package com.lixiang;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

import dev.langchain4j.community.model.dashscope.QwenStreamingChatModel;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.ImageContent;
import dev.langchain4j.data.message.TextContent;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.model.chat.response.StreamingChatResponseHandler;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

/**
* 演示如何使用LangChain4j处理包含图片的聊天对话
*/
public class ImageDemo {
/**
* 主方法,演示多轮对话处理
* @param args 命令行参数
* @throws UnsupportedEncodingException 编码异常
*/
@SneakyThrows
public static void main(String[] args) throws UnsupportedEncodingException {
// 使用CountDownLatch等待异步响应完成
CountDownLatch cdl = new CountDownLatch(1);

// 构建Qwen流式聊天模型
QwenStreamingChatModel model = QwenStreamingChatModel.builder()
.apiKey("sk-937aee4c3e654d04b84634d363f5a770")
.modelName("qwen-vl-max") // 使用支持多模态的模型
.build();

// 存储聊天消息的列表
List<ChatMessage> messageList = new ArrayList<>();
UserMessage userMessage = null;
/*
Audio Content
AudioContent is similar to the ImageContent, but represents audio content.

Video Content
VideoContent is similar to the ImageContent, but represents video content.

PDF File Content
PdfFileContent is similar to the ImageContent, but represents binary contents of a PDF file.

byte[] imageBytes = readBytes("/home/me/cat.jpg");
String base64Data = Base64.getEncoder().encodeToString(imageBytes);
ImageContent imageContent = ImageContent.from(base64Data, "image/jpg");
UserMessage userMessage = UserMessage.from(imageContent);

*/
// 第一轮对话:包含图片和文本
ImageContent image = ImageContent.from("http://manongbiji.oss-cn-beijing.aliyuncs.com/temp/qmsht.jpg");
String input = "这张图来自哪里?";
System.out.println("> " + input); // 打印用户输入
userMessage = UserMessage.from(image, TextContent.from(input)); // 创建包含图片和文本的用户消息
messageList.add(userMessage);
model.chat(messageList, new StreamingChatHandler(messageList ,cdl)); // 发送消息并处理响应
cdl.await(); // 等待第一轮对话完成

cdl = new CountDownLatch(1);
// 第二轮对话:仅包含文本
input = "这张图的作者是谁?";
System.out.println("> " + input);
userMessage = UserMessage.from(input);
messageList.add(userMessage);
model.chat(messageList, new StreamingChatHandler(messageList,cdl));
}
}

/**
* 处理流式聊天响应的处理器
*/
@Slf4j
class StreamingChatHandler implements StreamingChatResponseHandler {
private List<ChatMessage> messageList; // 存储聊天消息的列表
private CountDownLatch cdl; // 用于同步的CountDownLatch

public StreamingChatHandler() {
// 默认构造函数
}

/**
* 带参数的构造函数
* @param messageList 聊天消息列表
* @param cdl 用于同步的CountDownLatch
*/
public StreamingChatHandler(List<ChatMessage> messageList, CountDownLatch cdl) {
this.messageList = messageList;
this.cdl = cdl;
}

/**
* 处理完整的响应
* @param response 聊天响应
*/
@Override
public void onCompleteResponse(ChatResponse response) {
messageList.add(response.aiMessage()); // 将AI的响应添加到消息列表
System.out.println("onCompleteResponse:" + response.finishReason()); // 打印完成原因
cdl.countDown(); // 减少计数器
}

/**
* 处理错误
* @param error 异常对象
*/
@Override
public void onError(Throwable error) {
System.out.println("onError:" + error.getMessage()); // 打印错误信息
cdl.countDown(); // 减少计数器
}

/**
* 处理部分响应
* @param message 部分响应内容
*/
@Override
public void onPartialResponse(String message) {
System.out.print(message); // 打印部分响应
}
}