一、簡單說明模型
LLM目前有兩種API提供
- LanguageModel:接收一個a作為輸入并返回一個b作為輸出,這種是已經過時的
- ChatLanguageModel:接收多個輸入,然后返回相應的輸出
ChatLanguaggeModel是LangChain4j中LLM交互低級API,它提供了最大的功能和靈活性。除此之外還有一個高級API(AIService)。
ChatLanguageModel還支持的模型有:
- EmbeddingModel:把文本轉換為Embedding
- ImageModel:用來生成和編輯圖片
- ModerationModel:這個模型可以檢查文本中是否包含有害內容
- ScoringModel:可以根據查詢對多段文本進行評分(排名),實際上就是用來確定每段文本與查詢的關聯性,這個對于RAG來說是非常有用的
二、ChatLanguageModel的API
ChatLanguageModel是一個接口,其定義如下:
public interface ChatLanguageModel {default String generate(String userMessage) {return generate(UserMessage.from(userMessage)).content().text();}default Response<AiMessage> generate(ChatMessage... messages) {return generate(asList(messages));}Response<AiMessage> generate(List<ChatMessage> messages);default Response<AiMessage> generate(List<ChatMessage> messages, List<ToolSpecification> toolSpecifications) {throw new IllegalArgumentException("Tools are currently not supported by this model");}default Response<AiMessage> generate(List<ChatMessage> messages, ToolSpecification toolSpecification) {throw new IllegalArgumentException("Tools are currently not supported by this model");}@Experimentaldefault ChatResponse chat(ChatRequest request) {throw new UnsupportedOperationException();}@Experimentaldefault Set<Capability> supportedCapabilities() {return emptySet();}
}
注意:現在我們看的是關于LangChain4j 0.36.2版本!!
三、關于ChatMessage
這個表示是一個聊天消息,當前有四種類型的聊天消息,每種消息的“來源”對應其中一種
- UserMessage:來自己于用戶的消息,這里指的用戶可以是應用使用的最終用戶或者是應用本身,它是相對于LLM大語言模型來說的
- AiMessage:由AI生成的消息,通常是為了響應
- ToolExecutionResultMessage:聊天過程中執行相關的工具(函數)的結果
- SystemMessage:來自己系統的消息,通常用來定義LLM在對話中的角色說明(指定AI應該如何表現以及以何種方式回答...)
- CustomMessage:可以包含任意屬性的自定義消息,這種消息不是所有的大模型語言都支持,只有支持它的才可以使用
使用多個ChatMessage
我們看到接口中方法定義為什么我們要使用多個ChatMessage?
注意:我們在于LLM進行聊天對話時,它本質上是無狀態的,它們是不會維護對話狀態的,如果要支持多論對話并且讓AI理解對話的上下文,那么就需要使用到多個ChatMessage。因為這個時候我們就需要把多論對話中的所有聊天消息告訴AI,讓它了解整個上下文的情況,從而達到一個有狀態的假象。
如下所示:
UserMessage firstUserMessage = UserMessage.from("你好,我叫鵬鵬");
AiMessage firstAiMessage = model.generate(firstUserMessage).content();
UserMessage secondUserMessage = UserMessage.from("我叫什么名字?");
AiMessage secondAiMessage = model.generate(firstUserMessage,firstAiMessage,SecondUserMessage).content();
向上面這樣手動去維護與管理這些消息是很麻煩的,實際的使用中我們會使用ChatMemory(先了解后續會說)
關于UserMessage
在UserMessage這個類中我們可以看到下面這個方法:
public static UserMessage userMessage(Content... contents) {return from(contents);
}
這個方法可以傳入多個Content,最終得到一個UserMessage對象
而Content是一個接口,它有如下一些實現(不同的實現可以傳入不同類型的內容)
- TextContent
- ImageContent
- AudioContent
- VideoContent
- PdfFileContent
通過這些不同的Content我們就可以把不同類型的內容轉為UserMessage,然后傳給LLM,如下所示:
UserMessage userMessage = UserMessage.from(TextContent.from("請描述下面的圖片信息"),ImageContent.from("https://ex.com/myCat.png")
);
Response<AiMessage> response = model.generate(userMessage);
TextContent
它是最為簡單的一種,就是把一個普通的文本轉為一個字符串
UserMessage.from(TextContent.from("Hello")) 與 UserMessage.from("Hello")這兩者沒有任何區別。
一次可以向UserMessage當中提供一個或多個TextContent
UserMessage userMessage = UserMessage.from(TextContext.from("Hello"),TextContext.from("你好啊!"));
ImageContent
根據不同的LLM提供商,ImageContent可以從URL地址或者Base64的二進制數據來提供ImageContent
如下所示,使用Base64的二進數據來提供ImageContent
byte[] imageBytes = readBytes("D:\\myImage\\hi.png");
String imgData = Base64.getEncoder().encodeToString(imageBytes);
ImageContent imageContent = ImageContent.from(imgData,"image/png");
UserMessage userMessage = UserMessage.from(imageContent);
AudioContent
它類似于ImageContent,它表示的是音頻內容
VideoContent
它類似于ImageContent,它表示的是視頻內容
PdfFileContent
它類似于ImageContent,表示的是PDF文件的二進制內容
四、實踐示例
POM依賴
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-dashscope-spring-boot-starter</artifactId><!-- 添加排除項 --><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j-simple</artifactId></exclusion></exclusions></dependency><!-- lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j</artifactId></dependency>
</dependencies>
其中SpringBoot指定版本為:3.3.5,langchain4j指定版本為0.36.2
yml配置
langchain4j:dashscope:chat-model:api-key: sk-09a****************3686d6c4cfb#model-name: deepseek-v3model-name: qwen-max-latestchat:systemMessage: 你是普京,接下來以普京的語氣來進行對話
其中aipkey是在阿里百煉平臺申請的aipkey,這里要使用時需要替換為自已申請好的apikey
主啟動
@SpringBootApplication
public class ChatApplication {public static void main(String[] args) {SpringApplication.run(ChatApplication.class, args);}
}
controller
@Slf4j
@RestController
@RequestMapping("/chat")
public class ChatController {// 注入聊天大語言模型@Resourceprivate ChatLanguageModel chatLanguageModel;@Value("${chat.systemMessage}")private String systemMessage;@GetMapping("/simple")public String chat(@RequestParam("message") String message) {UserMessage userMessage = UserMessage.from(message);Response<AiMessage> generate = chatLanguageModel.generate(userMessage);log.info("generate: {}", generate);return generate.content().text();}@GetMapping("/sys/simple")public String chatSys(@RequestParam("message") String message) {Response<AiMessage> aiResponse;UserMessage userMessage = UserMessage.from(message);if (systemMessage != null && !systemMessage.isEmpty()) {SystemMessage systemMessage = SystemMessage.from(this.systemMessage);aiResponse = chatLanguageModel.generate(List.of(systemMessage, userMessage));} else {aiResponse = chatLanguageModel.generate(userMessage);}if (aiResponse == null) {return "大模型未返回任何內容~~~";}log.info("generate: {}", aiResponse);return aiResponse.content().text();}
}
這其中有兩個不同的請求,一個是簡單的聊天請求,另一個是我們指定了特定的SystemMessage的請求。