一、AI应用开发技术架构

1.纯Prompt问答

用户直接向AI应用进行提问,AI应用拿到提示词后进行整理分析后传给大模型,大模型将结果返还给AI应用最后给到用户。类似于我们平时的直接对话

利用大模型推理能力完成应用的核心功能

应用场景:

  • 文本摘要分析
  • 舆情分析
  • 坐席检查
  • AI对话

2.Agent+Function Calling

当我们的需求中涉及到业务的实现,比如让AI生成一份旅行计划,并根据计划给我们订酒店。如:千问给我们订外卖

将应用端业务能力与AI大模型推理能力结合,简化复杂业务功能开发

应用场景:

  • 旅行指南
  • 数据提取
  • 数据聚合分析
  • 课程顾问

3.RAG Embeddings(知识库拓展)

大模型的知识是通过历史的数据训练来的。如果要大模型生成发布之后的事情,很有可能大模型就不知道,RAG相当于给大模型一本教材,让它根据这本教材进行学习。

离线步骤:

  • 文档加载
  • 文档切分
  • 文档编码
  • 写入知识库

在线步骤:

  • 获得用户问题
  • 检索知识库中相关知识片段
  • 将检索结果和用户问题填入Prompt模版
  • 用最终获得的Prompti调用LLM
  • 由LLM生成回复

应用场景:

  • 个人知识库
  • AI客服助手

4.Fine-tuning(模型微调)

在大模型实在不如人意的时候,自己调试大模型。一般实现不了

二、java语言中当下最热门的两个框架

当下最热门的两个框架:springAIlangchain4j

他们的异同:

SpringAI是Spring出版的,所以适配了SpringBoot等,要求jdk高一些

LangChain4j是python中LangChain框架出版的,更适用于低版本

因为spring是专门为java开发的框架,所以更新会很快,更适用于新的大模型,并且更能无缝接入springboot项目

三、SpringAI

快速入门

1.引入依赖

<!-- Spring AI 版本管理(必须) -->
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.ai</groupId>
      <artifactId>spring-ai-bom</artifactId>
      <version>1.0.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>



        <!-- Spring AI 核心(所有模型通用) -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-core</artifactId>
        </dependency>

  <!-- OpenAI(ChatGPT) -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
        </dependency>

        <!-- 阿里云通义千问 -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-qwen-spring-boot-starter</artifactId>
        </dependency>

        <!-- 百度文心一言 -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-wenxin-spring-boot-starter</artifactId>
        </dependency>

        <!-- 字节跳动豆包 -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-doubao-spring-boot-starter</artifactId>
        </dependency>

        <!-- 讯飞星火 -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-spark-spring-boot-starter</artifactId>
        </dependency>

2.配置化

spring:
  ai:
    # 通义千问(阿里)
    qwen:
      api-key: sk-你的APIKey
      chat:
        options:
          model: qwen-turbo
          temperature: 0.7

    # 豆包(字节)
    doubao:
      api-key: sk-你的APIKey
      chat:
        options:
          model: doubao-lite-4k
          temperature: 0.7

    # OpenAI
    openai:
      api-key: sk-你的APIKey
      base-url: https://api.openai.com
      chat:
        options:
          model: gpt-3.5-turbo
          temperature: 0.7

    # 文心一言(百度)
    wenxin:
      api-key: 你的APIKey
      secret-key: 你的SecretKey
      chat:
        options:
          model: ernie-3.5-8k

    # 讯飞星火
    spark:
      api-key: 你的APIKey
      api-secret: 你的APISecret
      app-id: 你的APPID
      chat:
        options:
          model: generalv3

3.配置客户端

配置客户端

@Configuration
public class CommonConfiguration {
    @Bean
    public ChatClient chatClient(OllamaChatModel chatModel){
        return  ChatClient
        .builder(chatModel)
        .defaultSystem("你是小查,是我的智能助手,以后你要为我的生活、学习服务,请以小查的省份和语气回答问题")
        .build();
    }
}

阻塞式输出

这里springAI已经帮我们整理好了,call()方法用来调用大模型,content()用来将结果解析返回,不用我们自己解析。

流式输出

流式输出只需要把call()方法改为Stream()

会话日志

SpringAI利用AOP原理提供了AI会话时的拦截、增强等功能,也就是Advisor

@Configuration
public class CommonConfiguration {
    @Bean
    public ChatClient chatClient(OllamaChatModel chatModel){
        return  ChatClient
                .builder(chatModel)
                .defaultSystem("你是小查,是我的智能助手,以后你要为我的生活、学习服务,请以小查的省份和语气回答问题")
                // 配置日志Advisor
                .defaultAdvisors(new SimpleLoggerAdvisor())
                .build();
    }
}
logging:
level:
org.springframework.ai.chat.client.advisor: debug
com.langdang.heimaai: debug
2026-05-10T17:21:33.719+08:00 DEBUG 29784 --- [heima-ai] [nio-8080-exec-1] o.s.a.c.c.advisor.SimpleLoggerAdvisor    : request: ChatClientRequest[prompt=Prompt{messages=[SystemMessage{textContent='你是小查,是我的智能助手,以后你要为我的生活、学习服务,请以小查的省份和语气回答问题', messageType=SYSTEM, metadata={messageType=SYSTEM}}, UserMessage{content='你是谁', metadata={messageType=USER}, messageType=USER}], modelOptions=org.springframework.ai.ollama.api.OllamaChatOptions@717b7c3b}, context={}]
2026-05-10T17:21:46.626+08:00 DEBUG 29784 --- [heima-ai] [nio-8080-exec-1] o.s.a.c.c.advisor.SimpleLoggerAdvisor    : response: {
  "result" : {
    "output" : {
      "messageType" : "ASSISTANT",
      "metadata" : {
        "messageType" : "ASSISTANT"
      },
      "toolCalls" : [ ],
      "media" : [ ],
      "text" : "您好!我是由中国的深度求索(DeepSeek)公司开发的智能助手。我可以帮助您处理各种问题、提供信息和指导,您可以随时问我任何问题或请求帮助。"
    },
    "metadata" : {
      "finishReason" : "stop",
      "contentFilters" : [ ],
      "empty" : false
    }
  },
  "results" : [ {
    "output" : {
      "messageType" : "ASSISTANT",
      "metadata" : {
        "messageType" : "ASSISTANT"
      },
      "toolCalls" : [ ],
      "media" : [ ],
      "text" : "您好!我是由中国的深度求索(DeepSeek)公司开发的智能助手。我可以帮助您处理各种问题、提供信息和指导,您可以随时问我任何问题或请求帮助。"
    },
    "metadata" : {
      "finishReason" : "stop",
      "contentFilters" : [ ],
      "empty" : false
    }
  } ],
  "metadata" : {
    "id" : "",
    "model" : "deepseek-r1:7b",
    "rateLimit" : {
      "requestsRemaining" : 0,
      "requestsLimit" : 0,
      "requestsReset" : 0.0,
      "tokensLimit" : 0,
      "tokensRemaining" : 0,
      "tokensReset" : 0.0
    },
    "usage" : {
      "promptTokens" : 33,
      "completionTokens" : 240,
      "totalTokens" : 273
    },
    "promptMetadata" : [ ],
    "empty" : false
  }
}
您好!我是由中国的深度求索(DeepSeek)公司开发的智能助手。我可以帮助您处理各种问题、提供信息和指导,您可以随时问我任何问题或请求帮助。

会话记忆

如果想让AI有对话记忆,其实就是靠存储它自己生成的回答再发给它来实现。

也就是把他自己的回答重新放到messages里

SpringAI已经提供了相应的存储对话id的接口

我们直接使用spring封装好的方法


    @Bean
    public ChatClient chatClient(OllamaChatModel chatModel, ChatMemory chatMemory) {
        return ChatClient.builder(chatModel)
                .defaultSystem("你是小查,是我的智能助手,以后你要为我的生活、学习服务,请以小查的身份和语气回答问题")
                .defaultAdvisors(
                        new SimpleLoggerAdvisor(),
                        // 直接用 builder(chatMemory) 构建,不额外指定 defaultConversationId
                        MessageChatMemoryAdvisor.builder(chatMemory)
                                .build()
                )
                .build();
    }
    @Bean
    public ChatMemory chatMemory() {
        return MessageWindowChatMemory.builder()
                .maxMessages(20) // 保留最近20轮对话
                .build();
    }

也就是加上这一段即可让对话有记忆

 // 直接用 builder(chatMemory) 构建,不额外指定defaultConversationId
 MessageChatMemoryAdvisor.builder(chatMemory)


 @Bean
    public ChatMemory chatMemory() {
        return MessageWindowChatMemory.builder()
                .maxMessages(20) // 保留最近20轮对话
                .build();
    }

但是一个正常的的AI软件肯定不是我一个人用,假设现在另一个问,如果2个人呢?他还会保持着原有的记忆。现在也就是记忆是没有边界的,是模糊的。

会话ID


// 官方文档 https://springdoc.cn/spring-ai/api/chat-memory.html#_%E8%81%8A%E5%A4%A9%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%9A%84_memory
    @RequestMapping("/chat")
    public String chatModel(String prompt,String conversationId){
        String content = chatClient.prompt()
                .user(prompt)
                .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId))
                .call()
                .content();
        System.out.println(content);
        return content;
    }

增加 .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId))

其中conversationId就是会话id

可以看到在会话id相同时候是有记忆的

但是如果我更换了会话id呢?

他就懵了

这是因为springai的chatMemory方法是通过存储会话id(conversationId)和会话内容(message)来记录内容

会话记录

可以看到,这里的chatMemoryStore是一个map其中key为String,value是一个List泛型是一个message,

那么message是什么呢?

这里就不卖关子了,点进message后里面是一个接口,接口中MessageType是一个枚举,其中记录了发送人的类型和内容。

利用这一点,我们重写一个messageVO来展示发送人和发送内容

调用chatMemory的get()方法获取一个List,这个list里存储了发送人和发送内容

利用stream留将message转化成我们需要的类型即可获取到会话记录

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐