个人总结 - LangChain4j应用(3)
github:
https://github.com/langchain4j/langchain4j/releases
官方文档:
https://docs.langchain4j.dev/intro
简要介绍:
LangChain4j是一个旨在简化大语言模型(LLMs)与Java应用程序集成的框架。
Tools(函数调用)
定义:允许LLM必要时调用一个或多个可用工具,这些工具通常由开发人员定义。工具可以是任何东西:网络搜索、对外部 API 的调用或特定代码段的执行等。LLM实际上无法自己调用该工具,而是去表达调用特定工具的意图。例如,我们知道LLM本身并不擅长数学。所以为LLM声明一个“数学工具”。当给定一个数学问题时,LLM可能会思考如果要正确回答该问题的话,它需要先调用提供的“数学工具”。
Low Level Tool API:
-
使用 ChatLanguageModel或StreamingChatLanguageModel 的
generate(List ChatMessage , List ToolSpecification)
方法。 -
ToolSpecification 是一个对象,包含有关该工具的所有信息:
- 工具名称(清晰的名称)
- 工具的描述(全面的描述)
- 工具的参数及其描述(每个参数的描述)
-
创建ToolSpecification的方式:
ToolSpecification toolSpecification = ToolSpecification.builder() .name("获取天气") .description("返回给定城市的天气预报") .addParameter("city", type("string"), description("应返回天气预报的城市")) .addParameter("temperatureUnit", enums(TemperatureUnit.class), description("温度单位")) .build();
class WeatherTools { @Tool("返回给定城市的天气预报") public String getWeather(@P("天气预报应该返回的城市") String city, @P("温度单位") TemperatureUnit temperatureUnit){ ... } } List<ToolSpecification> toolSpecifications = ToolSpecifications.toolSpecificationsFrom(WeatherTools.class);
-
如果 LLM 决定调用该工具,则返回的 AiMessage 将在 toolExecutionRequests 字段中包含该工具的信息。在这种情况下,AiMessage.hasToolExecutionRequests() 将返回 true。
-
如果要将工具执行的结果发送回 LLM,则需要创建一个 ToolExecutionResultMessage(每个 ToolExecutionRequest 一个)并将其与所有先前的消息一起发送:
String result = "It is expected to rain in London tomorrow."; ToolExecutionResultMessage toolExecutionResultMessage = ToolExecutionResultMessage.from(toolExecutionRequest, result); List<ChatMessage> messages = List.of(userMessage, aiMessage, toolExecutionResultMessage); Response<AiMessage> response2 = model.generate(messages, toolSpecifications);
High Level Tool API
-
使用 @Tool 注释来注释任何 Java 方法,可以接受任意数量的各种类型的参数,并将其与 AiServices 一起使用。AiServices 会自动将此类方法转换为 ToolSpecifications,并将它们包含在与 LLM 的每次交互的请求中。当LLM决定调用该工具时,AI Service将自动执行相应的方法,并且该方法的返回值(如果有)将被发送回LLM。可以在 DefaultToolExecutor 中找到实现细节。
-
Tool的返回类型:
- void:在该方法成功返回时,“Success”字符串将发送至 LLM。
- String:不进行任何转换。
- 其他返回类型:返回值会先转换为 JSON,然后再发送到 LLM。
-
注解:
@P
:修饰参数,包括value:参数的描述;required:该参数是否必填。@ToolMemoryId
:当工具方法需要根据当前用户的聊天上下文来进行操作时
-
示例:
interface WebGrab { String grab(String query); } class WebGrabTool{ @Tool("根据搜索参数,获取与之相关的URL") public List<String> searchGoogle(@P("搜索参数") String query) { return googleSearchService.search(query); } @Tool("给定URL,返回网页内容") public String getWebPageContent(@P("网页的URL") String url, @ToolMemoryId String memoryId) { // 获取与特定 memoryId 关联的聊天记录 List<ChatMessage> history = aiService.chatMemory().getMessages(memoryId); Document jsoupDocument = Jsoup.connect(url).get(); return jsoupDocument.body().text(); } } WebGrab webGrab = AiServices.builder(WebGrab.class) .chatLanguageModel(model) .tools(new WebGrabTool()) .build(); webGrab.grab("ailu");
-
访问已执行的工具:如果希望访问在AiServices执行期间调用的工具,可以将返回类型包装在 Result 类中从而获取ToolExecution,
ToolExecutionRequest
是工具调用前的请求描述,而ToolExecution
是工具调用后的详细信息,比如是否成功执行、执行结果是什么等等。interface Assistant { Result<String> chat(String userMessage); } Result<String> result = assistant.chat("Cancel my booking 123-456"); String answer = result.content(); List<ToolExecution> toolExecutions = result.toolExecutions();
-
以编程方式实现Tools
-
创建ToolSpecification:
ToolSpecification toolSpecification = ToolSpecification.builder() .name("获取预订详情") .description("返回预订详情") .addParameter("bookingNumber", type("string"), description("格式类似为B-12345的预订编号")) .build();
-
对于每个 ToolSpecification,都需要提供一个 ToolExecutor 实现,该实现将处理 LLM 生成的工具执行请求
// 定义一个工具执行器,用于处理工具执行请求 ToolExecutor toolExecutor = (toolExecutionRequest, memoryId) -> { // 将工具执行请求中的参数部分(JSON格式)转换为Map对象 Map<String, Object> arguments = fromJson(toolExecutionRequest.arguments()); String bookingNumber = arguments.get("bookingNumber").toString(); // getBooking是一个已经定义好的方法,可以从数据库中获取 Booking booking = getBooking(bookingNumber); return booking.toString(); };
-
一旦我们有一个或多个 (ToolSpecification, ToolExecutor) 对,我们就可以在创建 AI 服务时指定它们:
Assistant assistant = AiServices.builder(Assistant.class) .chatLanguageModel(chatLanguageModel) .tools(singletonMap(toolSpecification, toolExecutor)) .build();
-
-
动态指定工具:
-
配置一个 ToolProvider,每次调用 AiServices 时都会向 LLM 提供ToolProvider包含的工具。
// 定义一个工具提供者,该提供者根据用户消息决定是否提供特定工具 // toolProviderRequest 包括 UserMessage 和 chat memory ID ToolProvider toolProvider = (toolProviderRequest) -> { // 检查用户消息是否包含关键词"booking" if(toolProviderRequest.userMessage().singleText().contains("booking")) { ToolSpecification toolSpecification = ToolSpecification.builder() .name("获取预订详情") .description("返回预订详情") .addParameter("bookingNumber", type("string")) .build(); return ToolProviderResult.builder() .add(toolSpecification, toolExecutor) .build(); } }; Assistant assistant = AiServices.builder(Assistant.class) .chatLanguageModel(model) .toolProvider(toolProvider) .build();
-
-
各model支持项目
Provider | Streaming | Tools | JSON mode | Supported Modalities (Input) | Observability | Local | Native | Comments |
Amazon Bedrock | ✅ | ✅ | text | ✅ | ||||
Anthropic | ✅ | ✅ | text, image | ✅ | ||||
Azure OpenAI | ✅ | ✅ | ✅ | text, image | ✅ | |||
ChatGLM | text | |||||||
DashScope | ✅ | ✅ | text, image, audio | ✅ | ||||
GitHub Models | ✅ | ✅ | ✅ | text | ✅ | |||
Google AI Gemini | ✅ | ✅ | text, image, audio, video, PDF | ✅ | ||||
Google Vertex AI Gemini | ✅ | ✅ | ✅ | text, image, audio, video, PDF | ✅ | |||
Google Vertex AI PaLM 2 | text | ✅ | ||||||
Hugging Face | text | |||||||
Jlama | ✅ | ✅ | text | ✅ | ✅ | |||
LocalAI | ✅ | ✅ | text | ✅ | ||||
Mistral AI | ✅ | ✅ | ✅ | text | ||||
Ollama | ✅ | ✅ | ✅ | text, image | ✅ | ✅ | ||
OpenAI | ✅ | ✅ | ✅ | text, image | ✅ | Compatible with: Ollama, LM Studio, GPT4All, etc. | ✅ | Compatible with: Groq, etc. |
Qianfan | ✅ | ✅ | text | |||||
Cloudflare Workers AI | text | |||||||
Zhipu AI | ✅ | ✅ | text, image | ✅ |