【Ai生态开发】Spring AI上架,打造专属业务大模型,AI开发再也不是难事!

本文涉及的产品
NLP自然语言处理_基础版,每接口每天50万次
NLP 自学习平台,3个模型定制额度 1个月
NLP自然语言处理_高级版,每接口累计50万次
简介: 【Ai生态开发】Spring AI上架,打造专属业务大模型,AI开发再也不是难事!

需求 就是说假设现在有一个 商城系统 里面有查询订单的api和获取商品购买方式的api   用户只需要输入 “帮我看看我前几天买过最便宜的衣服”  经过语言处理 ai就能够调用 查询订单的api并在里面自动的添加查询条件以及 排序条件  这是我们的目标  本文就是来讲解实现这样的目标


Spring AI介绍


Spring AI 是 AI 工程师的一个应用框架,它提供了一个友好的 API 和开发 AI 应用的抽象,旨在简化 AI 应用的开发工序。


提供对常见模型的接入能力,目前已经上架 https://start.spring.io/,提供大家测试访问。(请注意虽然已经上架 start.spring.io,但目前还是在 Spring 私服,未发布至 Maven 中央仓库)


基本知识讲解:


函数调用


函数调用(Function Calling)是OpenAI在2023年6月13日对外发布的新能力。根据OpenAI官方博客描述,函数调用能力可以让大模型输出一个请求调用函数的消息,其中包含所需调用的函数信息、以及调用函数时所携带的参数信息。这是一种将大模型(LLM)能力与外部工具/API连接起来的新方式。


比如用户输入:


What’s the weather like in Tokyo?

使用function calling,可实现函数执行get_current_weather(location: string),从而获取函数输出,即得到对应地理位置的天气情况。这其中,location这个参数及其取值是借助大模型能力从用户输入中抽取出来的,同时,大模型判断得到调用的函数为get_current_weather。


开发人员可以使用大模型的function calling能力实现:


  • 在进行自然语言交流时,通过调用外部工具回答问题(类似于ChatGPT插件);
  • 将自然语言转换为调用API调用,或数据库查询语句;
  • 从文本中抽取结构化数据
  • 其它


实现步骤


1. 添加依赖

 <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
      <groupId>org.springframework.ai</groupId>
      <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
  </dependency>
 
 <!-- 配置 Spring 仓库 -->
  <repositories>
      <repository>
          <id>spring-milestones</id>
          <name>Spring Milestones</name>
          <url>https://repo.spring.io/milestone</url>
          <snapshots>
              <enabled>false</enabled>
          </snapshots>
      </repository>
  </repositories>


2. 配置 OpenAI 相关参数

spring:

 ai:

   openai:

     base-url: # 支持 openai-sb、openai-hk 等中转站点,如用官方则不填

     api-key: sk-xxxx


3.创建一个Spring Controller处理HTTP请求。


在Spring项目中创建一个Controller类,用于处理提取要素的HTTP请求和生成调用的API和变量集合。

import com.google.gson.Gson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
 
import java.util.HashMap;
import java.util.Map;
 
@RestController
public class ElementExtractionController {
 
    @Autowired
    private ElementExtractionService elementExtractionService;
 
    @PostMapping("/extract-elements")
    public ResponseEntity<Map<String, Object>> extractElements(@RequestBody String userInput) {
        Map<String, Object> result = elementExtractionService.extractElements(userInput);
        return ResponseEntity.ok(result);
    }
}


创建一个ElementExtractionService服务类来提取要素


创建一个服务类,用于封装提取要素的逻辑。在这个服务类中,可以使用自然语言处理技术来分析用户输入并提取需求和变量。可以使用现有的开源NLP库或API,如NLTK、SpaCy、Stanford CoreNLP、Google Cloud Natural Language API等


这里使用NLTK库来进行文本分析和实体识别,以提取用户输入中的需求和变量:

import org.springframework.stereotype.Service;
import edu.stanford.nlp.simple.Document;
import edu.stanford.nlp.simple.Sentence;
 
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
@Service
public class ElementExtractionService {
 
    public Map<String, Object> extractElements(String userInput) {
        // 使用NLTK库进行文本分析和实体识别
        Document doc = new Document(userInput);
        List<Sentence> sentences = doc.sentences();
 
        // 提取需求
        String requirement = extractRequirement(sentences);
 
        // 提取变量
        Map<String, String> variables = extractVariables(sentences);
 
        // 构建结果
        Map<String, Object> result = new HashMap<>();
        result.put("api", requirement);
        result.put("variables", variables);
        return result;
    }
 
    private String extractRequirement(List<Sentence> sentences) {
        // 在这里根据实际需求,从句子中提取需求
        // 可以使用关键词提取、模式匹配等方法
 
        // 这里示例直接返回第一句话作为需求
        if (!sentences.isEmpty()) {
            return sentences.get(0).text();
        }
 
        return "";
    }
 
    private Map<String, String> extractVariables(List<Sentence> sentences) {
        // 在这里根据实际需求,从句子中提取变量
        // 可以使用实体识别、关键词提取等方法
 
        // 这里示例直接从第一句话中提取名词作为变量
        Map<String, String> variables = new HashMap<>();
        if (!sentences.isEmpty()) {
            Sentence sentence = sentences.get(0);
            for (String word : sentence.words()) {
                if (isNoun(word)) {
                    variables.put(word, "true");
                }
            }
        }
 
        return variables;
    }
 
    private boolean isNoun(String word) {
        // 在这里根据实际需求,判断一个词是否为名词
        // 可以使用词性标注、词典匹配等方法
 
        // 这里示例简单判断是否以大写字母开头,作为名词的判断条件
        return Character.isUpperCase(word.charAt(0));
    }
}

那么下一步 :

4.封装一个API来操作open ai的Assistants API

创建一个Spring Service来操作OpenAI Assistants API。

创建一个服务类,用于封装操作OpenAI Assistants API的逻辑。

import com.google.gson.Gson;
import okhttp3.*;
 
import org.springframework.stereotype.Service;
 
import java.io.IOException;
 
@Service
public class OpenAIAssistantsService {
 
    public String callOpenAIAssistantsAPI(String prompt) {
        OkHttpClient client = new OkHttpClient();
        MediaType mediaType = MediaType.parse("application/json");
 
        JsonObject requestBody = new JsonObject();
        requestBody.addProperty("prompt", prompt);
        requestBody.addProperty("max_tokens", 32);
        requestBody.addProperty("stop", null);
 
        RequestBody body = RequestBody.create(mediaType, requestBody.toString());
        Request request = new Request.Builder()
                .url(OPENAI_API_URL)
                .post(body)
                .addHeader("Authorization", "Bearer " + OPENAI_API_KEY)
                .build();
 
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                String responseBody = response.body().string();
                JsonObject jsonObject = new Gson().fromJson(responseBody, JsonObject.class);
                return jsonObject.getAsJsonObject("choices")
                        .get(0)
                        .getAsJsonObject()
                        .get("text")
                        .getAsString();
            } else {
                System.out.println("OpenAI Assistants API调用失败: " + response.code() + " - " + response.message());
            }
        } catch (IOException e) {
            System.out.println("OpenAI Assistants API调用异常: " + e.getMessage());
        }
 
        return null;
    }
}


创建一个自定义函数签名。


创建一个函数,它将调用其他项目中的API,并返回结果。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
@Service
public class CustomFunctionService {
 
    @Autowired
    private OtherAPIService otherAPIService;
 
    public String customFunction(String apiId, String inputParameters) {
        // 根据API的ID筛选需要调用的API
        String apiEndpoint = getApiEndpoint(apiId);
 
        // 调用其他项目中的API,并进行处理
        String result = otherAPIService.callOtherAPI(apiEndpoint, inputParameters);
 
        // 对结果进行处理,并返回
        return "处理后的结果:" + result;
    }
 
    private String getApiEndpoint(String apiId) {//这里还会有很多具体业务的api就不一一列举了
        // 根据API的ID获取相应的API的URL或其他信息
        // 这里可以根据实际情况进行实现
        if (apiId.equals("api1")) {
            return "https://api.example.com/api1";
        } else if (apiId.equals("api2")) {
            return "https://api.example.com/api2";
        } else {
            throw new IllegalArgumentException("无效的API ID: " + apiId);
        }
    }
}

创建一个Spring Controller来调用自定义函数。

创建一个Controller类,它将调用自定义函数,并返回结果。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
 
import java.util.HashMap;
import java.util.Map;
 
@RestController
public class CustomFunctionController {
 
    @Autowired
    private CustomFunctionService customFunctionService;
 
    @PostMapping("/call-custom-function")
    public ResponseEntity<String> callCustomFunction(@RequestBody String userInput) {
        String result = customFunctionService.customFunction(userInput);
        return ResponseEntity.ok(result);
    }
}

在上面提取要素的服务(ElementExtractionService)的基础上,我们可以再封装一个Assistants服务,它将接受用户的请求并调用提取要素的服务。然后,Assistants服务将提取的要素和变量(uid)作为输入传递给封装了OpenAI的服务(OpenAIAssistantsService),并根据要素选择适当的API进行调用,并返回对应的结果。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import java.util.Map;
 
@Service
public class AssistantsService {
 
    @Autowired
    private ElementExtractionService elementExtractionService;
 
    @Autowired
    private OpenAIAssistantsService openAIAssistantsService;
 
    public String processUserRequest(String userInput) {
        // 提取要素
        Map<String, Object> elements = elementExtractionService.extractElements(userInput);
 
        // 获取要素和变量
        String requirement = (String) elements.get("api");
        Map<String, String> variables = (Map<String, String>) elements.get("variables");
        String uid = (String) elements.get("uid");
 
        // 调用OpenAI Assistants服务
        String result = openAIAssistantsService.callOpenAIAssistantsAPI(requirement, variables, uid);
 
        return result;
    }
}

AssistantsService类接受用户的请求,并调用ElementExtractionService来提取要素。然后,它获取要素、变量和uid,并将它们作为参数传递给OpenAIAssistantsService的callOpenAIAssistantsAPI方法。该方法根据要素选择适当的API进行调用,并返回结果。


具体的业务实现“提取要素”的逻辑部分


请注意,为了实现这个过程,还需要修改ElementExtractionService中提取要素的逻辑,以确保这个服务能符合具体业务的逻辑  例如我提到的 “帮我看看我买过最便宜的衣服”

import org.springframework.stereotype.Service;
import edu.stanford.nlp.simple.Document;
import edu.stanford.nlp.simple.Sentence;
 
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
@Service
public class ElementExtractionService {
 
    public Map<String, Object> extractElements(String userInput) {
        // 使用NLTK库进行文本分析和实体识别
        Document doc = new Document(userInput);
        List<Sentence> sentences = doc.sentences();
 
        // 提取需求
        String requirement = extractRequirement(sentences);
 
        // 提取变量
        Map<String, String> variables = extractVariables(sentences);
 
        // 构建结果
        Map<String, Object> result = new HashMap<>();
        result.put("api", requirement);
        result.put("variables", variables);
        return result;
    }
 
    private String extractRequirement(List<Sentence> sentences) {
        // 在这里根据实际需求,从句子中提取需求
        // 可以使用关键词提取、模式匹配等方法
 
        // 这里示例直接返回第一句话作为需求
        if (!sentences.isEmpty()) {
            return sentences.get(0).text();
        }
 
        return "";
    }
 
    private Map<String, String> extractVariables(List<Sentence> sentences) {
        // 在这里根据实际需求,从句子中提取变量
        // 可以使用实体识别、关键词提取等方法
 
        // 这里示例从第一句话中提取名词作为变量,并根据特定模式进行匹配
        Map<String, String> variables = new HashMap<>();
        if (!sentences.isEmpty()) {
            Sentence sentence = sentences.get(0);
            List<String> words = sentence.words();
            for (int i = 0; i < words.size() - 1; i++) {
                String currentWord = words.get(i);
                String nextWord = words.get(i + 1);
                if (isNoun(currentWord) && nextWord.equals("的")) {
                    variables.put(currentWord, "true");
                }
            }
        }
 
        return variables;
    }
 
    private boolean isNoun(String word) {
        // 在这里根据实际需求,判断一个词是否为名词
        // 可以使用词性标注、词典匹配等方法
 
        // 这里示例简单判断是否以大写字母开头,作为名词的判断条件
        return Character.isUpperCase(word.charAt(0));
    }
}

我将extractVariables方法进行了修改。现在它从第一句话中提取名词作为变量,并且根据特定模式进行匹配。特定模式是判断当前词是否为名词,以及下一个词是否为"的"。如果匹配成功,则将当前词作为变量存储。


这样我们就基本实现了一开始的那个目标:


假设现在有一个 商城系统 里面有查询订单的api和获取商品购买方式的api   用户只需要输入 “帮我看看我前几天买过最便宜的衣服”  经过语言处理 ai就能够调用 查询订单的api并在里面自动的添加查询条件以及 排序条件  这是我们的目标  本文就是来讲解实现这样的目标


更长远的目标:


希望能够开发出一款中间件(作为一个服务被注册到项目当中) 能够作为open ai 和具体项目的桥梁  即在开发配置当中我输入我的已有项目的服务的签名   那这个助手能够根据用户的自然语言输入 自动的去调用执行 项目中已有的各种服务 来做各种各样的复杂的数据库查询 等操作


本文所受启发 参考文献:


  1. Function calling and other API updates: https://openai.com/blog/function-calling-and-other-api-updates
  2. OpenAI assistants in LangChain: https://python.langchain.com/docs/modules/agents/agent_types/openai_assistants
  3. Multi-Input Tools in LangChain: https://python.langchain.com/docs/modules/agents/tools/multi_input_tool
  4. examples/Assistants_API_overview_python.ipynb: https://github.com/openai/opena...
  5. The Spring Boot Actuator is the one dependency you should include in every project (danvega.dev)
  6. Assistants API won't allow external web request - API - OpenAI Developer Forum
相关文章
|
19天前
|
机器学习/深度学习 人工智能 前端开发
AI+Code驱动的M站首页重构实践:从技术债务到智能化开发
本文分享了阿里巴巴找品M站首页重构项目中AI+Code提效的实践经验。面对M站技术栈陈旧、开发效率低下的挑战,我们通过楼层动态化架构重构和AI智能脚手架,实现了70%首页场景的标准化覆盖 + 30%的非标场景的研发提速,开发效率分别提升90%+与40%+。文章详细介绍了楼层模板沉淀、AI辅助代码生成、智能组件复用评估等核心实践,为团队AI工程能力升级提供了可复制的方法论。
169 15
AI+Code驱动的M站首页重构实践:从技术债务到智能化开发
|
15天前
|
数据采集 存储 人工智能
智能体(AI Agent)开发实战之【LangChain】(二)结合大模型基于RAG实现本地知识库问答
智能体(AI Agent)开发实战之【LangChain】(二)结合大模型基于RAG实现本地知识库问答
|
21天前
|
机器学习/深度学习 人工智能 运维
探讨AI数字人软件系统的开发与部署策略
随着科技发展,人工智能成为经济转型的关键驱动力,AI数字人软件系统在各行业广泛应用。本文探讨其开发与部署策略,助力企业和开发者参考。开发策略包括需求分析、技术选型、模块化设计、数据驱动及安全性保障;部署策略涵盖硬件环境、软件配置、分布式与云端部署以及运维保障,推动系统智能化与稳定性提升。
|
21天前
|
人工智能 自然语言处理 算法
AI时代如何让大模型「读懂」企业数据?——从“单一问数”到“复杂决策”的智能跃迁
从早期的传统BI,到敏捷BI,再到智能BI,BI工具正逐步进化为具备类人推理能力的数字助手。Gartner预测,到2025年,增强型消费者体验将首次推动增强型BI(ABI)能力的采用率超过50%,这将深刻重塑企业的业务流程与决策模式,“人人都是数据消费者”的时代正加速到来。
|
18天前
|
数据采集 人工智能 编解码
2025年颠覆闭源大模型?MonkeyOCR:这款开源AI文档解析模型,精度更高,速度更快!
还在依赖昂贵且慢的闭源OCR工具?华中科技大学开源的MonkeyOCR文档解析模型,以其超越GPT4o的精度和更快的推理速度,在单机单卡(3090)上即可部署,正颠覆业界认知。本文将深入解析其设计哲学、核心突破——大规模自建数据集,并分享实测体验与避坑指南。
292 0
|
18天前
|
机器学习/深度学习 人工智能 自然语言处理
AI生成内容为什么有"AI味"?各大模型如何破局
本文深入探讨了AI生成内容中普遍存在的“AI味”现象,从技术角度剖析其成因及解决方法。“AI味”主要表现为语言模式同质化、情感表达平淡、创新性不足和上下文理解局限。这些特征源于训练数据偏差、损失函数设计及安全性约束等技术因素。各大厂商如OpenAI、Anthropic、Google以及国内的百度、阿里云等,正通过多样性训练、Constitutional AI、多模态融合等方法应对这一挑战。未来,对抗性训练、个性化定制、情感建模等技术创新将进一步减少“AI味”。尽管“AI味”反映了当前技术局限,但随着进步,AI生成内容将更自然,同时引发关于人类创作与AI生成界限的哲学思考。
71 0
|
18天前
|
Java API 微服务
Java 21 与 Spring Boot 3.2 微服务开发从入门到精通实操指南
《Java 21与Spring Boot 3.2微服务开发实践》摘要: 本文基于Java 21和Spring Boot 3.2最新特性,通过完整代码示例展示了微服务开发全流程。主要内容包括:1) 使用Spring Initializr初始化项目,集成Web、JPA、H2等组件;2) 配置虚拟线程支持高并发;3) 采用记录类优化DTO设计;4) 实现JPA Repository与Stream API数据访问;5) 服务层整合虚拟线程异步处理和结构化并发;6) 构建RESTful API并使用Springdoc生成文档。文中特别演示了虚拟线程配置(@Async)和StructuredTaskSco
69 0
|
17天前
|
机器学习/深度学习 人工智能 自然语言处理
当无人机遇上Agentic AI:新的应用场景及挑战
本文简介了Agentic AI与AI Agents的不同、Agentic无人机的概念、应用场景、以及所面临的挑战
100 5
当无人机遇上Agentic AI:新的应用场景及挑战
|
2月前
|
开发框架 人工智能 Java
破茧成蝶:阿里云应用服务器让传统 J2EE 应用无缝升级 AI 原生时代
本文详细介绍了阿里云应用服务器如何助力传统J2EE应用实现智能化升级。文章分为三部分:第一部分阐述了传统J2EE应用在智能化转型中的痛点,如协议鸿沟、资源冲突和观测失明;第二部分展示了阿里云应用服务器的解决方案,包括兼容传统EJB容器与微服务架构、支持大模型即插即用及全景可观测性;第三部分则通过具体步骤说明如何基于EDAS开启J2EE应用的智能化进程,确保十年代码无需重写,轻松实现智能化跃迁。
290 40
|
2月前
|
人工智能 数据挖掘
🔔阿里云百炼智能体和工作流可以发布为组件了,AI应用变成“搭积木”
本文介绍了如何通过智能体组件化设计快速生成PPT。首先,创建一个“PPT大纲生成”智能体并发布为组件,该组件可根据用户输入生成结构清晰的大纲。接着,在新的智能体应用中调用此组件与MCP服务(如ChatPPT),实现从大纲到完整PPT的自动化生成。整个流程模块化、复用性强,显著降低AI开发门槛,提升效率。非技术人员也可轻松上手,满足多样化场景需求。
🔔阿里云百炼智能体和工作流可以发布为组件了,AI应用变成“搭积木”

热门文章

最新文章