笔记2-大模型接入

代码地址

https://github.com/bbhhe/hu-ai-agent.git

本节内容

  1. 在 AI 应用平台上创建智能体应用、工作流应用、智能体编排应用

  2. 使用至少一个 AI 软件客户端,推荐Cursor

  3. 完成后端项目初始化

  4. 实践 4 种程序调用 AI 大模型的方式

  5. 使用 Ollama 部署 1 个本地大模型,并且通过 Spring AI 调用

一、AI平台上创建智能体应用

之前在文心智能体平台上创建过几个:

0.png
一个基础的角色扮演智能体:

https://mbd.baidu.com/ma/s/0oFvEBR8


还有一个工作流模式的:

https://mbd.baidu.com/ma/s/vdqJRoz8

二、使用AI客户端

使用字节的trea开发工具,在亿级流量点赞项目中生成前端,并辅助开发:

Ai辅助开发点赞系统笔记-高可用方案&trea生成前端代码

三、后端项目初始化

新建项目

使用gradle构建项目,jdk版本21,spring版本3.4.5


点完创建,修改下gradle配置

gradle/wrapper/gradle-wrapper.properties

python
复制代码
distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https://mirrors.aliyun.com/macports/distfiles/gradle/gradle-8.13-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists

修改setting.properties,增加阿里云公共仓库地址

python
复制代码
// 插件库 pluginManagement {     repositories {         maven { url 'https://maven.aliyun.com/repository/public/' }  // 阿里云公共仓库         maven { url 'https://maven.aliyun.com/repository/gradle-plugin/' }  // Gradle 插件专用仓库         gradlePluginPortal()     } } dependencyResolutionManagement {     repositories {         maven { url 'https://maven.aliyun.com/repository/public/' }         mavenCentral()  // 可保留作为备用源     } } rootProject.name = 'hu-ai-agent'

修改build.gradle

python
复制代码
repositories {     maven { url 'https://maven.aliyun.com/repository/public/' }     mavenCentral() }

整合依赖

添加hutool工具库和Knife4j接口文档(参考 官方文档 引入)

  1. 在build.gradle添加

python
复制代码
implementation 'cn.hutool:hutool-all:5.8.37' implementation("com.github.xiaoymin:knife4j-openapi3-jakarta-spring-boot-starter:4.4.0")
  1. 新增controller健康检查

python
复制代码
@RestController @RequestMapping("/health") public class HealthController {     @GetMapping     public String healthCheck() {         return "ok";     } }
  1. 创建application.yml,删除application.properties

yaml
复制代码
spring:   application:     name: hu-ai-agent server:   port: 8123   servlet:     context-path: /api # springdoc-openapi springdoc:   swagger-ui:     path: /swagger-ui.html     tags-sorter: alpha     operations-sorter: alpha   api-docs:     path: /v3/api-docs   group-configs:     - group: 'default'       paths-to-match: '/**'       packages-to-scan: com.bbhhe.huaiagent.controller # knife4j knife4j:   enable: true   setting:     language: zh_cn
  1. 启动项目

扩展:gradle统一版本管理

**libs.versions.toml**文件是Gradle构建工具中用于集中管理依赖版本和插件版本的一种方式。

要用途

  1. 集中管理依赖版本:将所有依赖项的版本号统一管理在一个文件中
  2. 提高可维护性:方便查找和更新依赖版本
  3. 减少重复:避免在多模块项目中重复声明相同依赖版本
  4. 类型安全访问:在构建脚本中提供类型安全的访问方式

首先创建gradle/libs.versions.toml文件

toml
复制代码
[versions] # 插件版本 spring-boot = "3.4.5" spring-dependency-management = "1.1.7" # 依赖版本 hutool = "5.8.37" knife4j = "4.4.0" dashscope-sdk = "2.20.0" spring-ai = "1.0.0-M6" commonmark = "0.24.0" jsoup = "1.19.1" bailian = "2.0.6" itext-core = "9.1.0" itext-asian = "9.1.0" spring-ai-alibaba = "1.0.0-M6.1" jsonschema-generator = "4.38.0" lombok = "1.18.30" [libraries] # Spring Boot 相关 spring-boot-starter-web = { module = "org.springframework.boot:spring-boot-starter-web" } spring-boot-starter-test = { module = "org.springframework.boot:spring-boot-starter-test" } # 工具库 hutool-all = { module = "cn.hutool:hutool-all", version.ref = "hutool" } knife4j-openapi3 = { module = "com.github.xiaoymin:knife4j-openapi3-jakarta-spring-boot-starter", version.ref = "knife4j" } dashscope-sdk = { module = "com.alibaba:dashscope-sdk-java", version.ref = "dashscope-sdk" } spring-ai-markdown = { module = "org.springframework.ai:spring-ai-markdown-document-reader", version.ref = "spring-ai" } commonmark = { module = "org.commonmark:commonmark", version.ref = "commonmark" } jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" } bailian = { module = "com.aliyun:bailian20231229", version.ref = "bailian" } itext-core = { module = "com.itextpdf:itext-core", version.ref = "itext-core" } itext-asian = { module = "com.itextpdf:font-asian", version.ref = "itext-asian" } spring-ai-alibaba = { module = "com.alibaba.cloud.ai:spring-ai-alibaba-starter", version.ref = "spring-ai-alibaba" } jsonschema-generator = { module = "com.github.victools:jsonschema-generator", version.ref = "jsonschema-generator" } lombok = { module = "org.projectlombok:lombok", version.ref = "lombok" } [plugins] spring-boot = { id = "org.springframework.boot", version.ref = "spring-boot" } spring-dependency-management = { id = "io.spring.dependency-management", version.ref = "spring-dependency-management" }

修改build.gradle

java
复制代码
plugins { id 'java' alias(libs.plugins.spring.boot) alias(libs.plugins.spring.dependency.management) } group = 'com.bbhhe' version = '0.0.1-SNAPSHOT' java { toolchain { languageVersion = JavaLanguageVersion.of(21) } } configurations { compileOnly { extendsFrom annotationProcessor } } repositories { maven { url 'https://maven.aliyun.com/repository/public/' } maven { url 'https://repo.spring.io/milestone' name 'Spring Milestones' // 禁用快照版本 mavenContent { releasesOnly() } } mavenCentral() } configurations { all { exclude group: 'org.slf4j', module: 'slf4j-simple' } } dependencies { implementation libs.spring.boot.starter.web //implementation 'org.springframework.boot:spring-boot-starter-jdbc' //runtimeOnly 'org.postgresql:postgresql' implementation libs.hutool.all implementation libs.knife4j.openapi3 implementation libs.dashscope.sdk implementation libs.spring.ai.markdown implementation libs.commonmark implementation libs.jsoup //implementation("org.springframework.ai:spring-ai-starter-vector-store-pgvector:1.0.0-M7") implementation libs.bailian implementation libs.itext.core testImplementation libs.itext.asian //阿里集成springai implementation libs.spring.ai.alibaba implementation libs.jsonschema.generator //implementation 'org.springframework.boot:spring-boot-starter-jdbc' //implementation("org.xerial:sqlite-jdbc:3.49.1.0") // langchain java版本 //implementation("dev.langchain4j:langchain4j-community-dashscope:1.0.0-beta2") //ollama调用本地大模型 //implementation("org.springframework.ai:spring-ai-ollama-spring-boot-starter:1.0.0-M6") compileOnly libs.lombok annotationProcessor libs.lombok testImplementation libs.spring.boot.starter.test testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } tasks.named('test') { useJUnitPlatform() }

最后构建运行测试

四、4种大模型调用方式

4.1 SDK接入

有的模型提供专属SDK在其官网并由调用样例。

安装阿里云百炼SDK_大模型服务平台百炼(Model Studio)-阿里云帮助中心

在build.gradle中引入依赖:

groovy
复制代码
implementation("com.alibaba:dashscope-sdk-java:2.19.5")

在百炼控制台获取APIKEY:

百炼控制台


创建测试类:
java
复制代码
package com.bbhhe.huaiagent.sdk; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Arrays; import java.lang.System; import com.alibaba.dashscope.aigc.generation.Generation; import com.alibaba.dashscope.aigc.generation.GenerationParam; import com.alibaba.dashscope.aigc.generation.GenerationResult; import com.alibaba.dashscope.common.Message; import com.alibaba.dashscope.common.Role; import com.alibaba.dashscope.exception.ApiException; import com.alibaba.dashscope.exception.InputRequiredException; import com.alibaba.dashscope.exception.NoApiKeyException; import com.alibaba.dashscope.utils.JsonUtils; public class DashscopeTests {     private static final String apiKey = "sk-xxxxx";     public static GenerationResult callWithMessage() throws ApiException, NoApiKeyException, InputRequiredException {         Generation gen = new Generation();         Message systemMsg = Message.builder()                 .role(Role.SYSTEM.getValue())                 .content("You are a helpful assistant.")                 .build();         Message userMsg = Message.builder()                 .role(Role.USER.getValue())                 .content("你是谁?")                 .build();         GenerationParam param = GenerationParam.builder()                 // 若没有配置环境变量,请用百炼API Key将下行替换为:.apiKey("sk-xxx")                 .apiKey(apiKey)                 // 此处以qwen-plus为例,可按需更换模型名称。模型列表:https://help.aliyun.com/zh/model-studio/getting-started/models                 .model("qwen-plus")                 .messages(Arrays.asList(systemMsg, userMsg))                 .resultFormat(GenerationParam.ResultFormat.MESSAGE)                 .build();         return gen.call(param);     }     public static void main(String[] args) {         try {             GenerationResult result = callWithMessage();             String json = JsonUtils.toJson(result);             System.out.println(json);         } catch (ApiException | NoApiKeyException | InputRequiredException e) {             // 使用日志框架记录异常信息             System.err.println("An error occurred while calling the generation service: " + e.getMessage());         } catch (UnsupportedEncodingException e) {             throw new RuntimeException(e);         } catch (IOException e) {             throw new RuntimeException(e);         }         System.exit(0);     } }

调用测试类:


踩坑:JDK21 + IDEA 控制台输出乱码

解决方案:添加vm参数,-Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8

参考文章:关于IDEA控制台中文乱码问题_idea system.out.println 中文乱码-CSDN博客

4.2 HTTP接入

对于 SDK 不支持的编程语言或需要更灵活控制的场景,可以直接使用 HTTP 请求调用 AI 大模型的 API。

deepseek http调用官网: 首次调用 API | DeepSeek API Docs

通过大模型转换上面代码:


复制到IDEA中,替换apikey
java
复制代码
package com.bbhhe.huaiagent.sdk; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; public class DeepSeekApiExample {     public static void main(String[] args) {         // 设置请求URL         String url = "https://api.deepseek.com/chat/completions";         // 构建请求体         JSONObject requestBody = new JSONObject();         requestBody.set("model", "deepseek-chat");         requestBody.set("messages", JSONUtil.parseArray("[{\"role\": \"system\", \"content\": \"You are a helpful assistant.\"}, {\"role\": \"user\", \"content\": \"你好!\"}]"));         requestBody.set("stream", false);         // 发送POST请求         HttpResponse response = HttpRequest.post(url)                 .header("Content-Type", "application/json")                 .header("Authorization", "Bearer sk-xxxx")                 .body(requestBody.toString())                 .execute();         // 输出响应结果         System.out.println(response.body());     } }

测试请求:

4.3 SpringAi

SpringAi旨在简化包含人工智能功能的应用程序的开发,而不会产生不必要的复杂性。

Spring AI 提供了抽象,作为开发 AI 应用程序的基础。 这些抽象具有多种实现,支持以最少的代码更改轻松交换组件。

Spring AI 提供以下功能:

  • 跨 AI 提供商的可移植 API 支持,用于聊天、文本到图像和嵌入模型。支持同步和流式处理 API 选项。此外,还可以访问特定于模型的特征。

  • 支持所有主要的 AI 模型提供商,例如 Anthropic、OpenAI、Microsoft、Amazon、Google 和 Ollama。支持的模型类型包括:

    - 聊天完成

    - 嵌入

    - 文本到图像

    - 音频转录

    - 文本到语音

    - 适度

  • 结构化输出 - AI 模型输出到 POJO 的映射。

  • 支持所有主要的矢量数据库提供商,例如 Apache Cassandra、Azure Cosmos DB、Azure Vector Search、Chroma、Elasticsearch、GemFire、MariaDB、Milvus、MongoDB Atlas、Neo4j、OpenSearch、Oracle、PostgreSQL/PGVector、PineCone、Qdrant、Redis、SAP Hana、Typesense 和 Weaviate。

  • 跨 Vector Store 提供商的可移植 API,包括新颖的类似 SQL 的元数据过滤器 API。

  • 工具/函数调用 - 允许模型请求执行客户端工具和函数,从而根据需要访问必要的实时信息并采取措施。

  • 可观察性 - 提供对 AI 相关作的见解。

  • 数据工程的文档摄取 ETL 框架

  • AI 模型评估 - 帮助评估生成的内容并防止幻觉响应的实用程序。

  • AI 模型和向量存储的 Spring Boot 自动配置和启动器。

  • ChatClient API - 用于与 AI 聊天模型通信的 Fluent API,惯用性类似于 WebClient 和 RestClient API。

  • Advisors API - 封装重复的生成式 AI 模式,转换发送到和传出语言模型 (LLM) 的数据,并提供跨各种模型和用例的可移植性。

  • 支持 Chat Conversation Memory and Retrieval Augmented Generation (RAG)。

Spring AI 默认没有支持所有的大模型(尤其是国产的),更多的是支持兼容 OpenAI API 的大模型的集成,参考 官方的模型对比。因此,我们如果想要调用阿里系大模型(比如通义千问),推荐直接使用阿里自主封装的 Spring AI Alibaba 框架,它不仅能直接继承阿里系大模型,用起来更方便,而且与标准的 Spring AI 保持兼容。

可以参考下列官方文档,来跑通调用大模型的流程:MQC0hpPVRHb1z16WelKwyDbGjanYlRbICLCyF5cJS9Q=

1)引入依赖:

groovy
复制代码
implementation("com.alibaba.cloud.ai:spring-ai-alibaba-starter:1.0.0-M6.1")

官方提醒:由于 spring-ai 相关依赖包还没有发布到中央仓库,如出现 spring-ai-core 等相关依赖解析问题,请在项目的 pom.xml 依赖中加入如下仓库配置。

groovy
复制代码
maven {         url 'https://repo.spring.io/milestone'         name 'Spring Milestones'         // 禁用快照版本         mavenContent {             releasesOnly()         } }

2)增加配置

yaml
复制代码
spring:   application:     name: hu-ai-agent   ai:     dashscope:       api-key: sk-xxxx       chat:         options:           model: qwen-plus

3)编写示例代码,注意要注入 <font style="color:rgb(31, 35, 40);">dashscopeChatModel</font>

java
复制代码
package com.bbhhe.huaiagent.controller; import jakarta.annotation.Resource; import org.springframework.ai.chat.messages.AssistantMessage; import org.springframework.ai.chat.model.ChatModel; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; // 取消注释即可在 SpringBoot 项目启动时执行 @Component public class SpringAiAiInvoke implements CommandLineRunner {     @Resource     private ChatModel dashscopeChatModel;     @Override     public void run(String... args) throws Exception {         AssistantMessage output = dashscopeChatModel.call(new Prompt("你好,我是小胡"))                 .getResult()                 .getOutput();         System.out.println(output.getText());     } }

上述代码实现了 CommandLineRunner 接口,我们启动 Spring Boot 项目时,会自动注入大模型 ChatModel 依赖,并且单次执行该类的 run 方法,达到测试的效果。

启动报错:

java
复制代码
Exception in thread "main" java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on the classpath. Either remove Logback or the competing implementation (class org.slf4j.simple.SimpleLoggerFactory loaded from file:/C:/Users/binbin/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-simple/2.0.17/9872a3fd794ffe7b18d17747926a64d61526ca96/slf4j-simple-2.0.17.jar). If you are using WebLogic you will need to add 'org.slf4j' to prefer-application-packages in WEB-INF/weblogic.xml: org.slf4j.simple.SimpleLoggerFactory

项目中同时存在多个 SLF4J 的日志实现,导致 SLF4J 无法确定使用哪个日志实现。SLF4J 要求只能有一个日志实现绑定,否则会抛出 异常。

解决方法

  1. 移除冲突的依赖

    • 如果使用 Logback 作为日志实现,移除 slf4j-simple 依赖。

    • 如果使用 slf4j-simple 作为日志实现,移除 Logback 依赖

java
复制代码
configurations {     all {         exclude group: 'org.slf4j', module: 'slf4j-simple'     } }

4.4 LangChain4j

Spring AI 作用一样,LangChain4j 是一个专注于构建基于大语言模型(LLM)应用的 Java 框架,作为知名 AI 框架 LangChain 的 Java 版本,它提供了丰富的工具和抽象层,简化了与 LLM 的交互和应用开发。

LangChain 官方是没有支持阿里系大模型的,只能用 社区版本的整合大模型包。可以在官方文档中查询支持的模型列表:LangChain4j模型集成

要接入阿里云灵积模型,可以参考官方文档:DashScope模型集成,提供了依赖和示例代码。

1)首先引入依赖:

groovy
复制代码
//implementation("com.alibaba.cloud.ai:spring-ai-alibaba-starter:1.0.0-M6.1") implementation("dev.langchain4j:langchain4j-community-dashscope:1.0.0-beta2")
  1. 调用示例
java
复制代码
package com.bbhhe.huaiagent.sdk; import dev.langchain4j.community.model.dashscope.QwenChatModel; import dev.langchain4j.model.chat.ChatLanguageModel; public class LangChainAiInvoke {     public static void main(String[] args) {         ChatLanguageModel qwenModel = QwenChatModel.builder()                 .apiKey("sk-xxx")                 .modelName("qwen-max")                 .build();         String answer = qwenModel.chat("你好,我是程序员小胡");         System.out.println(answer);     } }

运行结果:

五、SpringAi调用本地大模型

本地可以直接使用开源项目 Ollama 快速安装大模型,无需自己执行脚本安装、也省去了复杂的环境配置 参考 官方文档

5.1 Spring AI 调用 Ollama 大模型

1)引入依赖build.gradle

groovy
复制代码
//implementation("com.alibaba.cloud.ai:spring-ai-alibaba-starter:1.0.0-M6.1") //implementation("dev.langchain4j:langchain4j-community-dashscope:1.0.0-beta2") implementation("org.springframework.ai:spring-ai-ollama-spring-boot-starter:1.0.0-M6")
  1. 修改配置文件application.yml

yaml
复制代码
spring:   application:     name: hu-ai-agent   ai:     ollama:       base-url: http://localhost:11434       chat:         model: deepseek-r1:1.5b
  1. 测试用例

java
复制代码
package com.bbhhe.huaiagent.controller; import jakarta.annotation.Resource; import org.springframework.ai.chat.messages.AssistantMessage; import org.springframework.ai.chat.model.ChatModel; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; // 取消注释即可在 SpringBoot 项目启动时执行 @Component public class OllamaAiInvoke implements CommandLineRunner {     @Resource     private ChatModel ollamaChatModel;     @Override     public void run(String... args) throws Exception {         AssistantMessage output = ollamaChatModel.call(new Prompt("你好,我是小胡"))                 .getResult()                 .getOutput();         System.out.println(output.getText());     } }

4)测试结果

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
小胡
下载 APP