Java大模型开发入门 (11/15):让AI自主行动 - 初探LangChain4j中的智能体(Agents)

前言

在过去的十篇文章里,我们已经打造出了一个相当强大的AI应用。它有记忆,能进行多轮对话;它有知识,能通过RAG回答关于我们私有文档的问题。它就像一个博学的“学者”,你可以向它请教任何在其知识范围内的问题。

但是,这个“学者”有一个巨大的局限:它只能说,不能做

  • 如果你问它:“今天北京天气怎么样?” 它只能根据训练数据回答一个大概,无法获取实时信息。
  • 如果你问它:“345乘以678等于多少?” 像gpt-4o-mini这样的高级模型或许能算对,但它本质上是在“预测”答案,而非进行精确计算,对于复杂运算容易出错。
  • 如果你让它:“帮我预订一张明天去上海的火车票。” 它更是无能为力。

今天,我们将为我们的AI引入一个革命性的新能力:行动。我们将把它从一个“问答机器人”,升级为一个能使用工具的 “智能体(Agent)” ,让它能够响应我们的指令,去执行真正的任务。

第一部分:什么是AI Agent?从“聊天”到“行动”

AI Agent和我们之前构建的聊天机器人(Chatbot)最大的区别在于:

Chatbot 的工作是根据上下文生成文本
Agent 的工作是根据用户目标,选择并执行动作(使用工具),最终达成目标。

这个过程模仿了人类助理的工作模式。当你对助理说:“帮我算一下5加上7等于几?” 助理不会凭空猜测,而是会执行以下步骤:

  1. 思考(Reasoning): “老板想让我算个数,这是一个加法运算。”
  2. 选择工具(Tool Selection): “我应该使用‘计算器’这个工具。”
  3. 准备参数(Parameter Extraction): “计算器的‘加法’功能需要两个数字,它们是5和7。”
  4. 执行工具(Tool Execution): 在计算器上按下 5 + 7 =
  5. 观察结果(Observation): 计算器显示结果是 12
  6. 生成最终回复(Response Generation): “老板,5加上7等于12。”

这个“思考->行动”的循环,就是Agent的核心。这之所以能实现,得益于现代大语言模型(如gpt-4o-mini)内置的强大能力——工具调用(Tool Calling)。我们只需向模型描述我们有哪些可用的工具,模型就能在需要时,告诉我们应该调用哪个工具以及需要提供哪些参数。

第二部分:在LangChain4j中定义一个“工具”

在LangChain4j中,赋予AI一个工具非常简单:你只需要创建一个普通的Java方法,并给它加上@Tool注解。

这个注解的作用就是向大语言模型“注册”这个方法,并告诉模型:

  • 这个工具是干什么用的(通过注解的value属性或方法的 Javadoc)。
  • 这个工具需要哪些参数(通过方法的参数列表)。

实战:创建一个计算器工具

  1. 创建Tools
    service包下创建一个新文件CalculatorTools.java

    package com.example.aidemoapp.service;import dev.langchain4j.agent.tool.Tool;
    import org.springframework.stereotype.Component;@Component // 将这个类注册为一个Spring Bean
    public class CalculatorTools {@Tool("Calculates the sum of two integers")public int add(int a, int b) {System.out.println("Tool executed: add(" + a + ", " + b + ")");return a + b;}@Tool("Calculates the difference between two integers")public int subtract(int a, int b) {System.out.println("Tool executed: subtract(" + a + ", " + b + ")");return a - b;}
    }
    

    代码解析

    • @Component:让Spring能够发现并管理这个类的实例。
    • @Tool("..."):注解的描述至关重要!LLM会根据这个描述来判断用户的意图是否与该工具匹配。描述写得越清晰,Agent就越“聪明”。
第三部分:构建一个能使用工具的Agent

我们将使用AiServices来创建一个新的Agent。这次,在构建AiService时,我们会告诉它有哪些工具(Tools)是可用的。

  1. config/LangChain4jConfig.java中创建Agent Bean
    我们将创建一个新的AI服务,专门用于演示Agent功能。

    // LangChain4jConfig.java// ... 其他Bean的定义 ...
    import com.example.aidemoapp.service.AgentAssistant;
    import com.example.aidemoapp.service.CalculatorTools;// ...@Configuration
    public class LangChain4jConfig {// ... 其他已有的Bean ...// 步骤1: 定义一个新的Agent服务接口Bean@Beanpublic AgentAssistant agentAssistant(ChatModel chatLanguageModel, CalculatorTools calculatorTools) {return AiServices.builder(AgentAssistant.class).chatModel(chatLanguageModel).tools(calculatorTools) // <-- 关键步骤:将工具注册到AI服务中.build();}
    }
    
  2. 定义AgentAssistant接口
    service包下创建AgentAssistant.java

    package com.example.aidemoapp.service;public interface AgentAssistant {String chat(String userMessage);
    }
    
  3. 创建AgentController
    controller包下创建AgentController.java

    package com.example.aidemoapp.controller;import com.example.aidemoapp.service.AgentAssistant;
    import lombok.RequiredArgsConstructor;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;@RestController
    @RequestMapping("/api/agent")
    @RequiredArgsConstructor
    public class AgentController {private final AgentAssistant agentAssistant;@GetMapping("/chat")public String chat(@RequestParam("query") String query) {return agentAssistant.chat(query);}
    }
    
第四步:测试我们的新Agent!
  1. 启动Spring Boot应用。

  2. 进行一次普通聊天
    请求URL: http://localhost:8080/api/agent/chat?query=Who are you?
    你会得到一个正常的回答,比如“我是一个乐于助人的助手”。此时,查看后台日志,没有任何"Tool executed"的打印。

  3. 进行一次需要使用工具的聊天
    请求URL: http://localhost:8080/api/agent/chat?query=What is 5 plus 7?
    稍等片刻,你会得到回答:“5 plus 7 is 12.”
    现在,查看后台日志,你会看到:

    Tool executed: add(5, 7)
    

    这证明了Agent成功地理解了你的意图,并调用了正确的Java方法!

  4. 再试一次
    请求URL: http://localhost:8080/api/agent/chat?query=What is 100 minus 33?
    你会得到回答:“100 minus 33 is 67.”
    后台日志会显示:

    Tool executed: subtract(100, 33)
    
总结

今天,我们成功地为我们的AI应用解锁了一项颠覆性的能力——行动。通过LangChain4j的@Tool注解和AiServices,我们轻松地将一个普通的Java方法变成了AI可以调用的工具,构建了一个初级的AI智能体。

我们的AI不再只是一个“知道分子”,它变成了一个能干活的“行动派”。

目前我们的工具还很简单,只是一个本地的计算器。但在真实世界中,工具的能力是无限的:它可以是一个调用外部天气API的HTTP客户端,一个查询数据库的DAO,甚至是一个发送邮件的服务。如何构建一个能与真实世界API交互的、更强大的Agent呢?


源码获取

本文中所有实战代码均已同步更新至Gitee仓库。建议您git pull拉取最新代码,对照本文进行学习。

  • Gitee仓库地址: https://gitee.com/chaocloud/springboot-langchain4j-demo.git

下一篇预告:
Java大模型开发入门 (12/15):Agent实战 - 打造能调用外部API的智能助手》—— 我们将把难度升级,封装一个能查询实时天气信息的API作为工具,打造一个能回答“明天上海天气怎么样?”这类问题的、更实用的智能助手。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/87093.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt KDReports详解与使用

Qt KDReports详解与使用 一、KD Reports 简介二、安装与配置三、核心功能与使用1、创建基础报表2、添加表格数据3、导出为 PDF4、XML报表定义 四、高级功能1、动态数据绑定2、自定义图表3、模板化设计4、页眉页脚设置 五、常见问题六、总结七、实际应用示例&#xff1a;发票生成…

Spring Cloud 原生中间件

&#x1f4dd; 代码记录 Consul&#xff08;服务注册与发现 分布式配置管理&#xff09; 拥有服务治理功能&#xff0c;实现微服务之间的动态注册与发现 ❌不在使用Eureka&#xff1a;1. 停更进维 2. 注册中心独立且和微服务功能解耦 Consul官网 Spring官方介绍 三个注册中…

CMake实践: 以开源库QSimpleUpdater为例,详细讲解编译、查找依赖等全过程

目录 1.环境和工具 2.CMake编译 3.查找依赖文件 3.1.windeployqt 3.2.dumpbin 4.总结 相关链接 QSimpleUpdater&#xff1a;解锁 Qt 应用自动更新的全新姿势-CSDN博客 1.环境和工具 windows 11, x64 Qt5.12.12或Qt5.15.2 CMake 4.0.2 干净的windows 7&#xff0c;最好是…

WordToCard制作高考志愿填报攻略小卡片【豆包版】

一、什么是WordToCard WordToCard是一个免费的工具&#xff0c;能够将Word文档自动转换为美观的知识卡片或图文海报。以下是它的主要特点&#xff1a; 功能优势 格式支持&#xff1a;支持标题、列表、表格、LaTeX公式等多种格式。模板丰富&#xff1a;提供多种风格的模板&am…

什么是PostCSS

PostCSS是一个用 JavaScript 工具和插件转换 CSS 代码的工具 PostCSS是基于 JavaScript 的 CSS 转换引擎&#xff0c;通过插件系统对 CSS 进行现代化处理&#xff0c;PostCSS 不是预处理器&#xff0c;而是 CSS 的编译器工具链&#xff0c;如同 Babel 之于 JavaScript&#xf…

游戏引擎学习第315天:取消排序键的反向顺序

仓库:https://gitee.com/mrxiao_com/2d_game_8 必须保证代码能跟上不然调试很麻烦 回顾并为今天定调 目前正处于对引擎中 Z 轴处理方式进行修改的阶段。上次我们暂停在一个节点&#xff0c;当时我们希望不再让所有屏幕上的精灵都必须通过同一个排序路径进行排序。我们想要将…

MySQL EXPLAIN 详解

MySQL EXPLAIN 详解:掌握 SQL 性能优化的关键工具 在日常数据库开发和优化过程中,很多开发者会遇到 SQL 查询变慢、索引未命中等问题。MySQL 提供了一个非常实用的工具 —— EXPLAIN 关键字,它可以帮助我们分析 SQL 查询的执行计划,识别潜在的性能瓶颈,从而有针对性地进行…

k8s使用私有harbor镜像源

前言 在node上手动执行命令可以正常从harbor拉取镜像&#xff0c;但是用k8s不行&#xff0c;使用kubectl describe pods xxx 提示未授权 unauthorized to access repository。 处理方法 创建一个secrete资源对象。以下示例中 registry-harbor 为secret资源对象的名称。除了邮…

AI绘画能发展到企业大规模使用的地步么?

1 技术演进与当前成熟度 AI绘画技术经历了从实验室概念到商业级工具的蜕变过程。早期技术受限于模型坍缩等问题&#xff0c;难以满足商业需求。关键突破出现在新型生成模型的应用&#xff0c;大幅提升生成速度至30秒内&#xff0c;在画面逻辑性和风格多样性方面实现质的飞跃。…

使用MyBatis-Plus实现数据权限功能

什么是数据权限 数据权限是指系统根据用户的角色、职位或其他属性&#xff0c;控制用户能够访问的数据范围。与传统的功能权限&#xff08;菜单、按钮权限&#xff09;不同&#xff0c;数据权限关注的是数据行级别的访问控制。 常见的数据权限控制方式包括&#xff1a; 部门数…

大模型——Dify 与 Browser-use 结合使用

大模型——Dify 与 Browser-use 结合使用 Dify 与 Browser-use 的结合使用,能够通过 AI 决策与自动化交互的协同,构建智能化、场景化的业务流程。 以下是两者的整合思路与技术落地方案: 一、核心组合逻辑 分工定位 Dify:作为AI模型调度中枢,负责自然语言理解、决策生成、…

transformer demo

import torch import torch.nn as nn import torch.nn.functional as F import math import numpy as np import pytestclass PositionalEncoding(nn.Module):def __init__(self, d_model, max_seq_length5000):super(PositionalEncoding, self).__init__()# 创建位置编码矩阵p…

centos 8.3(阿里云服务器)mariadb由系统自带版本(10.3)升级到10.6

1. 备份数据库 在进行任何升级操作前&#xff0c;务必备份所有数据库&#xff1a; mysqldump -u root -p --all-databases > all_databases_backup.sql # 或者为每个重要数据库单独备份 mysqldump -u root -p db_name1 > db_name1_backup.sql mysqldump -u root -p db…

如何稳定地更新你的大模型知识(算法篇)

目录 在线强化学习的稳定知识获取机制:算法优化与数据策略一、算法层面的稳定性控制机制二、数据处理策略的稳定性保障三、训练过程中的渐进式优化策略四、环境设计与反馈机制的稳定性影响五、稳定性保障的综合应用策略六、总结与展望通过强化学习来让大模型学习高层语义知识,…

图的遍历模板

图的遍历 BFS 求距离 #include<bits/stdc.h>using namespace std;int n, m, k,q[20001],dist[20001]; vector<int> edge[20001];int main(){scanf("%d%d%d",&n,&m,&k);for (int i 1;i<m;i){int x,y;scanf("%d%d",&x,&am…

Java集合 - LinkedList底层源码解析

以下是基于 JDK 8 的 LinkedList 深度源码解析&#xff0c;涵盖其数据结构、核心方法实现、性能特点及使用场景。我们从 类结构、Node节点、插入/删除/访问操作、线程安全、性能对比 等角度进行详细分析 一、类结构与继承关系 1. 类定义 public class LinkedList<E> e…

Pytorch 卷积神经网络参数说明一

系列文章目录 文章目录 系列文章目录前言一、卷积层的定义1.常见的卷积操作2. 感受野3. 如何理解参数量和计算量4.如何减少计算量和参数量 二、神经网络结构&#xff1a;有些层前面文章说过&#xff0c;不全讲1. 池化层&#xff08;下采样&#xff09;2. 上采样3. 激活层、BN层…

C++ 中的 iostream 库:cin/cout 基本用法

iostream 是 C 标准库中用于输入输出操作的核心库&#xff0c;它基于面向对象的设计&#xff0c;提供了比 C 语言的 stdio.h 更强大、更安全的 I/O 功能。下面详细介绍 iostream 库中最常用的输入输出工具&#xff1a;cin 和 cout。 一、 基本概念 iostream 库&#xff1a;包…

SAP复制一个自定义移动类型

SAP复制移动类型 在SAP系统中&#xff0c;复制移动类型201可以通过事务码OMJJ或SPRO路径完成&#xff0c;用于创建自定义的移动类型以满足特定业务需求。 示例操作步骤 进入OMJJ事务码&#xff1a; 打开事务码OMJJ&#xff0c;选择“移动类型”选项。 复制移动类型&#xff…

Bambu Studio 中的“回抽“与“装填回抽“的区别

回抽 装填回抽: Bambu Studio 中的“回抽” (Retraction) 和“装填回抽”(Prime/Retract) 是两个不同的概念&#xff0c;它们都与材料挤出机的操作过程相关&#xff0c;但作用和触发条件有所不同。 回抽(Retraction): 回抽的作用, 在打印机移动到另一个位置之前&#xff0c;将…