个人总结 - LangChain4j应用(3)

个人总结 - 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 类中从而获取ToolExecutionToolExecutionRequest工具调用前的请求描述,而 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支持项目

ProviderStreamingToolsJSON modeSupported Modalities (Input)ObservabilityLocalNativeComments
Amazon Bedrocktext
Anthropictext, image
Azure OpenAItext, image
ChatGLMtext
DashScopetext, image, audio
GitHub Modelstext
Google AI Geminitext, image, audio, video, PDF
Google Vertex AI Geminitext, image, audio, video, PDF
Google Vertex AI PaLM 2text
Hugging Facetext
Jlamatext
LocalAItext
Mistral AItext
Ollamatext, image
OpenAItext, imageCompatible with: Ollama, LM Studio, GPT4All, etc.Compatible with: Groq, etc.
Qianfantext
Cloudflare Workers AItext
Zhipu AItext, image

### Quarkus与LangChain4j集成及使用案例 Quarkus 是一种专为 Java 开发者设计的 Kubernetes 原生框架,能够优化基于 JVM 的应用性能并支持云原生开发环境。而 LangChain4j 则是用于简化大型语言模型 (LLM)Java 应用程序之间集成的一个框架[^2]。 对于希望将这两项技术结合起来使用的开发者来说,可以考虑以下几个方面: #### 配置依赖关系 为了使 Quarkus 项目能顺利引入 LangChain4j 功能,在 `pom.xml` 文件中添加相应的 Maven 依赖项是非常重要的一步。这通常涉及到指定版本号以及任何必要的仓库地址来获取最新的库文件。 ```xml <dependency> <groupId>com.langchain4j</groupId> <artifactId>langchain4j-core</artifactId> <version>${langchain4j.version}</version> </dependency> ``` #### 初始化ChatLanguageModel实例 鉴于未来的新特性会围绕 ChatLanguageModel API 展开工作而不是传统的 LanguageModel 接口[^3],因此建议创建一个专门的服务类或者配置类来进行初始化操作,并通过 CDI 或其他方式将其注入到业务逻辑层当中去。 ```java import com.langchain4j.chat.ChatLanguageModel; import jakarta.enterprise.context.ApplicationScoped; @ApplicationScoped public class LLMService { private final ChatLanguageModel chatModel; public LLMService() { this.chatModel = new ChatLanguageModel.Builder() .setApiKey(System.getenv("API_KEY")) .build(); } // 提供对外访问的方法... } ``` #### 构建RESTful接口 利用 Quarkus 自带的强大 RESTEasy 支持,很容易就可以构建起一套完整的 HTTP 请求处理机制。这样不仅可以让前端更容易地调用后端服务,同时也方便后续扩展更多功能模块。 ```java import org.eclipse.microprofile.rest.client.inject.RestClient; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; @Path("/api/llm") @Produces(MediaType.APPLICATION_JSON) public class LLMApiResource { @Inject LLMService llmService; @GET @Path("/query/{text}") public String query(@PathParam("text") String text){ return llmService.query(text); } } ``` 上述代码片段展示了如何在一个典型的 Quarkus 应用程序里实现与 LangChain4j 的基本交互模式。当然实际应用场景可能会更加复杂多变,具体实现细节还需要根据项目的特殊需求做适当调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

艾露z

谢谢侬!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值