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

大家好 这里是苏泽 后端是工作 ai是兴趣 

对于ai的产生我的立场是拥抱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);
    }
}

3.创建一个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

 

本文只是简单提供一个可行的思路做参考 真正做出可拓展性的ai开发插件道路还很长 先在这立个小flag吧  希望今年能够完成这个小目标  如果有一起开发这个项目的伙伴可以跟我来讨论哦

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024年2月24日~2024年3月1日周报(调整网络结构)

文章目录 一、前言二、实验情况2.1 结果展示2.2 灵感收集 三、小结 一、前言 上周学习了数学表达式、了解了DDNet的网络框架。   在本周&#xff0c;寻找改进网络框架与超参数的灵感&#xff0c;并跑代码查看效果。另外&#xff0c;完成了毕业设计开题报告任务。 二、实验情…

【javaEE-唠嗑局】如何用jconsole观察进程里的多线程情况

&#x1f4e2;编程环境&#xff1a;idea 如何用jconsole观察进程里的多线程情况 1. 打开jdk2. 打开jconsole3. 查看每个线程的情况 以下面这段代码为例&#xff1a;代码运行时&#xff0c;包括一个进程&#xff0c;该进程中有两个线程。 package thread; public class Demo1 …

无法调试MFC源码

VS无法调试MFC源码 起初 有时候就是这么无奈&#xff0c;MFC源码各种问题没有办法调试&#xff0c;可是又想看下代码如何调用&#xff0c;里面做了些什么&#xff0c;从哪儿调出&#xff0c;学习一下大神的思路什么的。整理一下有可能的原因。 检查生成代码设置 需要设置正…

十二、Nacos源码系列:Nacos配置中心原理(四)- RefreshEvent 事件处理

前面文章&#xff0c;我们说到回调监听器的方法中&#xff0c;主要就是发布了一个RefreshEvent事件&#xff0c;这个事件主要由 SpringCloud 相关类来处理。今天我们继续分析后续的流程。 RefreshEvent 事件会由 RefreshEventListener 来处理&#xff0c;该 listener 含有一个 …

【YOLO系列】YOLOv9论文超详细解读(翻译 +学习笔记)

前言 时隔一年&#xff0c;YOLOv8还没捂热&#xff0c;YOLO系列最新版本——YOLOv9 终于闪亮登场&#xff01; YOLOv9的一作和v7一样。v4也有他。 他于2017年获得台湾省National Central University计算机科学与信息工程博士学位&#xff0c;现在就职于该省Academia Sinica的…

计算机二级MySQL-错题、知识点合集04

计算机二级MySQL 第四章 索引 主键约束&#xff0c;不允许为空也不允许重复。 NOT NULL非空约束属于自定义完整约束 PRIMARY KEY 属于实体完整性约束 FOREIGN KEY外键约束 外键与其引用的主键应分别属于不同的表&#xff0c;可以属于同一个关系&#xff1b;一个关系中可以定…

【java 基础】闲话 ClassLoader 和 SPI (一)

文章目录 引子双亲委派模型你真的明白了吗&#xff1f; 双亲委派“不够用了”SPI机制 其他琐碎 引子 有别于 java 提供的 IO 模块&#xff0c;java 中的classloader主要是用来加载类的&#xff0c;当然除了加载类&#xff0c;也可以加载资源文件。 那么首先我们会问一个问题&…

光伏业务管理软件有哪些推荐?

光伏业务管理软件是用于光伏电站的设计、施工、运营和维护等各个环节的软件工具。以下是一些推荐的光伏业务管理软件&#xff1a; PVsyst 这是一款全球广泛使用的光伏系统设计软件&#xff0c;可以进行详细的系统设计&#xff0c;包括组件匹配、逆变器选择、系统布局等。 鹧…

电子信息行业数字化转型创新应用挑战赛火热进行中,速戳

由深圳市宝安区人民政府、中国信息通信研究院联合举办的“第七届工业互联网数据创新应用大赛——解决方案赛道&#xff1a;电子信息行业数字化转型创新应用挑战赛”火热进行中&#xff01;大赛报名时间截至2024年3月15日&#xff0c;并将于3月25日在深圳宝安进行线下决赛答辩。…

如何辨别GPT3还是GPT4?

辨别后台使用的是GPT3还是GPT4可以提问以下问题验证&#xff1a; 1.昨天的当天的明天是哪天&#xff1f; 2.树上有9只鸟&#xff0c;猎人射杀了一只&#xff0c;还剩下多少只&#xff1f; 3.为什么周树人要打鲁迅&#xff1f; GPT3回答&#xff1a; GPT4回答&#xff1a; 如…

全闪存加速信创数据库数仓一体机解决方案

立足行业&#xff0c;深度解读 在新的大数据生态中&#xff0c;传统数据库/数据仓库技术和产品成为大数据生态中的组成部分&#xff0c;对结构化数据的存储和计算进行支撑。 数据库&数据仓库一体机是高端、核心数据管理产品&#xff0c;在我国党政、银行、交通等领域广泛…

市场热点袭来,直接加仓可靠吗?九方智投洪帮主助投资者明确几大要点

消费电子近期再度走强&#xff0c;多企业均出现涨停。消费电子出现乐观局面&#xff0c;有投资者认为是因为目前市场需求旺盛&#xff0c;产业链正在积极拉货&#xff0c;持续加单&#xff0c;各类手机新机也在积极备货&#xff0c;消费电子库存低。面对市场情绪高涨&#xff0…

LabVIEW最佳传输系统设计

LabVIEW最佳传输系统设计 介绍了基于LabVIEW软件开发的最佳基带传输系统和最佳带通传输系统的设计。通过软件仿真实现了脉冲成形滤波器和匹配滤波器的设计&#xff0c;证明了系统在消除码间干扰和抗噪声方面的优异性能。此设计不仅激发了学生的学习兴趣&#xff0c;还有助于提…

AI智能分析网关V4车辆违停算法在园区场景中的应用及特点

随着城市化进程的加速&#xff0c;车辆违停问题愈发严重&#xff0c;给城市交通带来了极大的困扰。为了解决这一问题&#xff0c;AI技术逐渐被应用于车辆违停的检测中。AI检测算法在车辆违停方面的应用&#xff0c;主要是通过计算机视觉技术&#xff0c;对道路上的车辆进行实时…

nodejs配置环境变量后不生效(‘node‘ 不是内部或外部命令,也不是可运行的程序或批处理文件)

一、在我们安装Node.js后&#xff0c;有时候会遇到node命令不管用的情况&#xff0c;关键是在安装时候已经添加配置了环境变量&#xff0c;向下面这样 但是还是不管用&#xff0c;这是因为环境变量配置不正确&#xff0c;权重不够&#xff0c;或者是命令冲突导致&#xff0c;解…

人工智能驱动的自拍时代:短视频美颜SDK技术的发展趋势

在短视频自拍的过程中&#xff0c;美颜技术的应用已经成为了许多人的必备工具&#xff0c;其中短视频美颜SDK技术的发展更是推动了自拍时代的进步。 1.人工智能技术的崛起 传统的美颜功能主要是通过简单的图像处理和滤镜效果来实现&#xff0c;但是这种方法往往会导致照片失真…

【Java】UWB高精度工业定位系统项目源代码

目录 UWB技术原理 优势 1. 高精度&#xff1a; 2. 抗干扰能力强&#xff1a; 3. 定位范围广&#xff1a; 4. 实时性强&#xff1a; 应用前景 定位系统源码功能介绍 实时定位&#xff1a; 轨迹回放&#xff1a; 区域管理&#xff1a; 巡检管理: 数据可视化分析&…

【ArcPy】批量读取文件夹excel中XY并转为点shp

示例展示 代码 只读取excel中含有XY字段的文件&#xff0c;并将矢量命名为excel文件名称。 import os import pandas as pd import arcpy folder_path r"C:\Users\admin\Desktop\excelfile" extension"xlsx" files [file for file in os.listdir(folder…

Prometheus(二):NodeExporter和Grafana的安装和使用

目录 1 Node Exporter安装1.1 简介1.2 安装1.3 Prometheus收集node_exporter数据 2 安装Grafana2.1 安装2.2 使用1、创建数据源2、选择模板3、模板导入 2.3 grafana创建用户1、创建用户2、验证 总结 1 Node Exporter安装 1.1 简介 node exporter是Prometheus的收集数据的组件…

使用 WordPress SureMembers 创建 Patreon 等粉丝网站

各行各业的创意专业人士和爱好者越来越多地转向在线平台分享他们的作品、建立忠实的粉丝并创造收入。 无论您是新晋艺术家还是知名影响者&#xff0c;拥有粉丝订阅网站都可以帮助您将热情货币化&#xff0c;同时培养紧密的支持者社区。 根据Statista的一份报告&#xff0c;到…