文文美人鱼 發表於 2025-8-29 20:38:00

3. LangChain4j + 低阶 和 高阶 API的详细说明

<h1 id="3-langchain4j--低阶-和-高阶-api的详细说明">3. LangChain4j + 低阶 和 高阶 API的详细说明</h1>
<p>@</p><div class="toc"><div class="toc-container-header">目录</div><ul><li>3. LangChain4j + 低阶 和 高阶 API的详细说明</li><li>LangChain4j + 低阶 和 高阶 API的详细说明<ul><li>LangChain4j在两个抽象层(低阶 / 高阶)提供不同的 api<ul><li>low level 低阶</li><li>high level 高阶</li></ul></li><li>low level 低阶 API 的使用<ul><li>大模型中的Token VS Web开发中的Token</li></ul></li><li>high level 高阶 API 的详细使用</li></ul></li><li>最后:</li></ul></div><p></p>
<h1 id="langchain4j--低阶-和-高阶-api的详细说明">LangChain4j + 低阶 和 高阶 API的详细说明</h1>
<p>https://docs.langchain4j.dev/get-started/</p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823593-1291703291.png" class="lazyload"></p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823708-195462746.png" class="lazyload"></p>
<p>https://docs.langchain4j.dev/tutorials/chat-and-language-models/</p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823529-1332790799.png" class="lazyload"></p>
<p>LLM 目前有两种 API 类型:</p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823552-1057016089.png" class="lazyload"></p>
<ul>
<li><code>LanguageModel</code>。它们的 API 非常简单 - 接受 <code>String</code> 作为输入并返回 <code>String</code> 作为输出。 这种 API 现在正在被聊天 API(第二种 API 类型)所取代。</li>
<li>ChatModel。这些接受多个 <code>ChatMessage</code> 作为输入并返回单个 <code>AiMessage</code> 作为输出。 <code>ChatMessage</code> 通常包含文本,但某些 LLM 也支持其他模态(例如,图像、音频等)。 这类聊天模型的例子包括 OpenAI 的 <code>gpt-4o-mini</code> 和 Google 的 <code>gemini-1.5-pro</code>。</li>
</ul>
<p><strong>LangChain4j 不会再扩展对</strong> <code>LanguageModel</code> <strong>的支持, 因此在所有新功能中,我们将使用</strong> <strong>ChatModel</strong> API。</p>
<p><code>ChatModel</code> 是 LangChain4j 中与 LLM 交互的低级 API,提供最大的能力和灵活性。 还有一个高级 API(AI 服务),我们将在介绍完基础知识后再讨论。</p>
<p>除了 <code>ChatModel</code> 和 <code>LanguageModel</code> 外,LangChain4j 还支持以下类型的模型:</p>
<ul>
<li><code>EmbeddingModel</code> - 这种模型可以将文本转换为 <code>Embedding</code>。</li>
<li><code>ImageModel</code> - 这种模型可以生成和编辑 <code>Image</code>。</li>
<li><code>ModerationModel</code> - 这种模型可以检查文本是否包含有害内容。</li>
<li><code>ScoringModel</code> - 这种模型可以对查询的多个文本片段进行评分(或排名), 本质上确定每个文本片段与查询的相关性。这对 RAG 很有用。 这些将在后面介绍。</li>
</ul>
<p>现在,让我们仔细看看 <code>ChatModel</code> API。</p>
<pre><code class="language-java">public interface ChatModel {

    String chat(String userMessage);
   
    ...
}
</code></pre>
<p>如您所见,有一个简单的   <code>chat </code>    方法,它接受   <code>String </code>    作为输入并返回   <code>String </code>    作为输出,类似于   <code>LanguageModel </code>   。 这只是一个便捷方法,让您可以快速轻松地进行试验,而无需将   <code>String </code>    包装在   <code>UserMessage </code>    中。</p>
<p>​</p>
<h2 id="langchain4j在两个抽象层低阶--高阶提供不同的-api">LangChain4j在两个抽象层(低阶 / 高阶)提供不同的 api</h2>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823588-276246995.png" class="lazyload"></p>
<ul>
<li>https://docs.langchain4j.dev/intro</li>
</ul>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823894-1504077482.png" class="lazyload"></p>
<blockquote>
<ul>
<li>LangChain4j 在两个抽象层次上运行:<br>
- 低层次。在这个层次上,您拥有最大的自由度和访问所有低级组件的权限,如 ChatModel,、<code>UserMessage</code>、<code>AiMessage</code>、<code>EmbeddingStore</code>、<code>Embedding</code> 等。 这些是您的 LLM 驱动应用程序的"原语"。 您可以完全控制如何组合它们,但需要编写更多的粘合代码。<br>
- 高层次。在这个层次上,您使用高级 API(如 AI 服务)与 LLM 交互, 它隐藏了所有复杂性和样板代码。 您仍然可以灵活地调整和微调行为,但是以声明式方式完成。</li>
</ul>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823561-49951373.png" class="lazyload"></p>
</blockquote>
<h3 id="low-level-低阶">low level 低阶</h3>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823848-1019024026.png" class="lazyload"></p>
<p>ChatModel 接口如下的默认实现的方法:</p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823497-1599087215.png" class="lazyload"></p>
<p>ChatModel提供的--种极其简便的方法:如下:</p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823904-224256204.png" class="lazyload"></p>
<pre><code class="language-java">default String chat(String userMessage) {
    ChatRequest chatRequest = ChatRequest.builder()
            .messages(UserMessage.from(userMessage))
            .build();

    ChatResponse chatResponse = chat(chatRequest);

    return chatResponse.aiMessage().text();
}

</code></pre>
<pre><code class="language-java">@GetMapping(value = "/langchain4j/hello")
public String hello(@RequestParam(value = "prompt", defaultValue = "你是谁") String prompt)
{
    String result = chatModel.chat(prompt);

    System.out.println("通过langchain4j调用模型返回结果:\n"+result);

    return result;
}

</code></pre>
<hr>
<h3 id="high-level-高阶">high level 高阶</h3>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823521-1700373479.png" class="lazyload"></p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823556-1561671219.png" class="lazyload"></p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823845-2004969788.png" class="lazyload"></p>
<h2 id="low-level-低阶-api-的使用">low level 低阶 API 的使用</h2>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823543-1029465508.png" class="lazyload"></p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823586-1500377827.png" class="lazyload"></p>
<p>导入相关的依赖:</p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823529-1465511542.png" class="lazyload"></p>
<pre><code class="language-xml">
    &lt;dependencies&gt;

      &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
      &lt;/dependency&gt;
      &lt;!--langchain4j-open-ai 基础--&gt;
      &lt;!--所有调用均基于 OpenAI 协议标准,实现一致的接口设计与规范LangChain4j 提供与许多 LLM 提供商的集成
      从最简单的开始方式是从 OpenAI 集成开始https://docs.langchain4j.dev/get-started    --&gt;
      &lt;dependency&gt;
            &lt;groupId&gt;dev.langchain4j&lt;/groupId&gt;
            &lt;artifactId&gt;langchain4j-open-ai&lt;/artifactId&gt;
      &lt;/dependency&gt;
      &lt;!--langchain4j 高阶--&gt;
      &lt;dependency&gt;
            &lt;groupId&gt;dev.langchain4j&lt;/groupId&gt;
            &lt;artifactId&gt;langchain4j&lt;/artifactId&gt;
      &lt;/dependency&gt;


      &lt;dependency&gt;
            &lt;groupId&gt;junit&lt;/groupId&gt;
            &lt;artifactId&gt;junit&lt;/artifactId&gt;
            &lt;version&gt;3.8.1&lt;/version&gt;
            &lt;scope&gt;test&lt;/scope&gt;
      &lt;/dependency&gt;
    &lt;/dependencies&gt;
</code></pre>
<p>配置对应大模型的配置类。</p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823531-1833144194.png" class="lazyload"></p>
<pre><code class="language-java">package com.rainbowsea.langchain4j02lowhighapi.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;

/**
* @Date 2025-05-27 22:04
* @Description: 知识出处 https://docs.langchain4j.dev/get-started
*/
@Configuration
public class LLMConfig
{
    @Bean(name = "qwen")
    public ChatModel chatModelQwen()
    {
      return OpenAiChatModel.builder()
                .apiKey(System.getenv("aliQwen_api"))
                .modelName("qwen-plus")
                .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
                .build();
    }

    /**
   * @Description: 知识出处,https://api-docs.deepseek.com/zh-cn/
   */
    @Bean(name = "deepseek")// 可以在根据@Resoure(name = "deepseek") 导入不同的实体类
    public ChatModel chatModelDeepSeek()
    {
      return
                OpenAiChatModel.builder()
                        .apiKey(System.getenv("deepseek_api"))
                        .modelName("deepseek-chat")
                        //.modelName("deepseek-reasoner")
                        .baseUrl("https://api.deepseek.com/v1")
                        .build();
    }
}

</code></pre>
<p>编写 Controller ,如下,其实就是跟我们编写的第一个连接大模型的 Hello World 是一样的</p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823680-1777682522.png" class="lazyload"></p>
<p>启动测试:</p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823520-844280977.png" class="lazyload"></p>
<h3 id="大模型中的token-vs-web开发中的token">大模型中的Token VS Web开发中的Token</h3>
<p>大模型当中的 Token</p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823739-862499833.png" class="lazyload"></p>
<p>Web 开发中的 Token</p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823552-1386138380.png" class="lazyload"></p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823504-81177234.png" class="lazyload"></p>
<pre><code class="language-java">// http://localhost:9002/lowapi/api02
    @GetMapping(value = "/lowapi/api02")
    public String api02(@RequestParam(value = "prompt", defaultValue = "你是谁") String prompt)
    {
      ChatResponse chatResponse = chatModelDeepSeek.chat(UserMessage.from(prompt));

      String result = chatResponse.aiMessage().text();
      System.out.println("通过langchain4j调用模型返回结果:"+result);

      TokenUsage tokenUsage = chatResponse.tokenUsage();
      System.out.println("本次调用消耗Token:"+tokenUsage);

      result = result +"\t\n"+ tokenUsage;

      return result;
    }
}
</code></pre>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823490-591793891.png" class="lazyload"></p>
<p><strong>ChatMessage 其实就是一个 prompt ,就是被大模型封装了一层,让其更好的被大模型读取识别而已。</strong></p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203824122-660811273.png" class="lazyload"></p>
<p>运行测试:</p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203825225-2052705057.png" class="lazyload"></p>
<h2 id="high-level-高阶-api-的详细使用">high level 高阶 API 的详细使用</h2>
<ul>
<li>https://docs.langchain4j.dev/tutorials/ai-services/</li>
</ul>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823549-1451459133.png" class="lazyload"></p>
<p>翻译:</p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823591-672647952.png" class="lazyload"></p>
<p><strong>AI Service 的高阶 API 的使用:</strong></p>
<p>具体的编码步骤如下:https://docs.langchain4j.dev/tutorials/ai-services/#simplest-ai-service</p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823585-113779660.png" class="lazyload"></p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823532-112791979.png" class="lazyload"></p>
<ol>
<li><strong>定义 AI Service 接口:</strong></li>
</ol>
<p>我们知道,按照Java开发一般习惯,有接口就要有实现类 比如接口ChatAssistant,就会有实现类ChatAssistantImpl现在用高阶api- AIServics不用你自己写 impl实现类,交给langchain4j给你搞定。(接口名是随意的,你只要见名之意即可)</p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823511-1893460952.png" class="lazyload"></p>
<pre><code class="language-java">package com.rainbowsea.langchain4j02lowhighapi.service;

/**
* 我们知道,按照Java开发一般习惯,有接口就要有实现类
* 比如接口ChatAssistant,就会有实现类ChatAssistantImpl
* 现在用高阶api-AIServics不用你自己写impl实现类,交给langchain4j给你搞定
* &lt;p&gt;
* 本次配置用的是langchain4j原生整合,没有引入sprinboot,不需要接口头上配置@AiService注解标签
*/
public interface ChatAssistant {
    String chat(String prompt);
}

</code></pre>
<p>LLMConfig类配置当中配置调用大模型的三件套(大模型的 Key,大模型 name,大模型的 url)</p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823524-778393741.png" class="lazyload"></p>
<pre><code class="language-java">
import com.rainbowsea.langchain4j02lowhighapi.service.ChatAssistant;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.service.AiServices;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* @Date 2025-05-27 22:04
* @Description: 知识出处 https://docs.langchain4j.dev/get-started
*/
@Configuration
public class LLMConfig
{



    @Bean(name = "qwen")
    public ChatModel chatModelQwen()
    {
      return OpenAiChatModel.builder()
                .apiKey(System.getenv("aliQwen_api"))
                .modelName("qwen-plus")
                .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
                .build();
    }
}
</code></pre>
<ol start="3">
<li><strong>对我们自我编写的 AI Service 的接口类,配置器实现类的配置(配置指明那个大模型实现我们这个接口类),配置好后,调用</strong> <code>AiServices.create()</code><strong>方法就好创建好我们自定义的接口实现类。</strong></li>
</ol>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823533-2100685972.png" class="lazyload"></p>
<pre><code class="language-java">
import com.rainbowsea.langchain4j02lowhighapi.service.ChatAssistant;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.service.AiServices;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* @Date 2025-05-27 22:04
* @Description: 知识出处 https://docs.langchain4j.dev/get-started
*/
@Configuration
public class LLMConfig
{

    @Bean(name = "qwen")
    public ChatModel chatModelQwen()
    {
      return OpenAiChatModel.builder()
                .apiKey(System.getenv("aliQwen_api"))
                .modelName("qwen-plus")
                .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
                .build();
    }



    // High-Api https://docs.langchain4j.dev/tutorials/ai-services#simplest-ai-service
    @Bean
    public ChatAssistant chatAssistant(@Qualifier("qwen") ChatModel chatModelQwen)
    {
      return AiServices.create(ChatAssistant.class, chatModelQwen);
    }

}
</code></pre>
<p>AlService是如何工作的</p>
<p>https://docs.langchain4j.dev/tutorials/ai-services/#how-does-it-work</p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203824291-1284054559.png" class="lazyload"></p>
<ol start="4">
<li><strong>最后编写对于业务的 Controller 类</strong>。直接调用我们的接口类,因为该接口的实现类已经被我们通过<strong>调用</strong> <code>AiServices.create()</code><strong>方法就好创建好我们自定义的接口实现类。同时我们也将其加入</strong> <code>@Bean</code><strong>加入到了 IOC 容器当中管理了,所以可以直接,通过</strong> <code>@Resource</code> 注解注入。</li>
</ol>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823492-1705134941.png" class="lazyload"></p>
<pre><code class="language-java">package com.rainbowsea.langchain4j02lowhighapi.controller;

import com.rainbowsea.langchain4j02lowhighapi.service.ChatAssistant;
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 HighApiController
{
    @Resource
    private ChatAssistant chatAssistant;

    @GetMapping(value = "/highapi/highapi")
    public String highApi(@RequestParam(value = "prompt", defaultValue = "你是谁") String prompt)
    {
      return chatAssistant.chat(prompt);
    }
}
</code></pre>
<p>运行测试:</p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203823847-1175225603.png" class="lazyload"></p>
<h1 id="最后">最后:</h1>
<blockquote>
<p>“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”</p>
<p><img alt="在这里插入图片描述" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202508/3084824-20250829203824682-1934141213.gif" class="lazyload"></p>
</blockquote><br><br>
来源:https://www.cnblogs.com/TheMagicalRainbowSea/p/19065140
頁: [1]
查看完整版本: 3. LangChain4j + 低阶 和 高阶 API的详细说明