GPT+向量数据库+Function calling=垂直领域小助手

引言

将 GPT、向量数据库和 Function calling 结合起来,可以构建一个垂直领域小助手。例如,我们可以使用 GPT 来处理自然语言任务,使用向量数据库来存储和管理领域相关的数据,使用 Function calling 来实现领域相关的推理和计算规则。这样,我们就可以构建一个针对特定领域的小助手,例如医疗保健、金融服务、法律咨询等。

今天为大家分享一个保险领域AI小助手的DEMO展示,含代码!!!

工具介绍

GPT

GPT (Generative Pretrained Transformer)是一种基于 Transformer 架构的大型语言模型,通过在大量文本上进行无监督学习,模型学习到了语言的统计规律和语义表示,从而能够处理各式各样的自然语言任务,例如文本生成、知识问答、推理计算、阅读理解等。
本文使用模型:gpt-3.5-turbo
本文使用GPT方法:Chat Completions API

向量数据库

向量数据库 是一种用于存储和管理向量数据的数据仓库,其中向量是一种将文本、图像、音频等非结构化数据转换为可计算的稠密向量表示的技术。通过使用向量数据库,我们可以快速地查找和比较相似的向量,从而实现诸如文本分类、聚类、推荐系统等应用。
本文使用腾讯云向量数据库

Function calling

Function calling 是一种在编程语言中调用函数的机制。通过函数调用,我们可以将复杂的任务分解为多个简单的函数,并通过调用这些函数来完成任务。在自然语言处理中,我们可以使用 Function calling 来实现自定义的推理和计算规则。
本文使用:gpt-3.5的Function calling

代码:

向腾讯云向量向量数据库构建数据

0、maven依赖

java 复制代码
<vectordatabase-sdk-java.version>1.2.0</vectordatabase-sdk-java.version>
<okhttp.version>4.9.2</okhttp.version>
<dependency>
            <groupId>com.tencent.tcvectordb</groupId>
            <artifactId>vectordatabase-sdk-java</artifactId>
            <version>${vectordatabase-sdk-java.version}</version>
            <exclusions>
            <!--因为我项目依赖了log4j相关其他包所以这里对impl包进行了排除 -->
                <exclusion>
                    <groupId>org.apache.logging.log4j</groupId>
                    <artifactId>log4j-slf4j-impl</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
<dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>${okhttp.version}</version>
        </dependency>

1、获取腾讯云client信息
这里的相关Url和相关账户请替换成自己的

java 复制代码
/**
     * 链接信息
     */
    private static VectorDBClient CLIENT = null;

    /**
     * 存放消息体的地方-模拟数据库,因为是DEMO所以没有接数据库只在自己内存用一下
     */
    private static Map<String, LinkedList<MessageV2>> SESSION_MSG_MAP = new HashMap<>(10);



/**
     * 获取腾讯云client信息
     * @return client
     */
    @PostConstruct
    private void initVectorDBClient(){
        if(CLIENT == null){
            log.info("VectorTestController  buildVectorDBClient -----------开始");
            // 创建VectorDB Client 这里的相关Url和相关账户请替换成自己的
            ConnectParam connectParam = ConnectParam.newBuilder()
                    .withUrl(apolloConfigHolder.getDashVector2040312EndPoint())
                    .withUsername(apolloConfigHolder.getDashVectorUserName2040312())
                    .withKey(apolloConfigHolder.getDashVectorApiKey2040312())
                    .withTimeout(30)
                    .build();
            log.info("VectorTestController  buildVectorDBClient -----------参数,connectParam = {}", JsonUtil.getJsonString(connectParam));
            CLIENT = new VectorDBClient(connectParam, ReadConsistencyEnum.EVENTUAL_CONSISTENCY);
            log.info("VectorTestController  buildVectorDBClient -----------成功");
        }
    }

2、创建腾讯云数据库

java 复制代码
/**
     * 创建腾讯云数据库
     * @param databaseName
     * @return
     */
    private Database buildDatabase(String databaseName){
        log.info("VectorTestController  createDatabase -----------开始 , databaseName = {}", databaseName);
        SdbCommonAssert.notBlank(databaseName, ErrorCode.PARAMS_IS_NULL);
        Database db = CLIENT.createDatabase(databaseName);
        log.info("VectorTestController  createDatabase -----------成功 , databaseName = {}", databaseName);
        return db;
    }

3、向指定数据库和分区构建初始化数据

java 复制代码
/**
     * databaseName=zzz
     * collectionName=zzz
     * 向指定分区构建初始化数据
     * @return 初始化数据与否
     */
    @RequestMapping("test/initXXX")
    public com.shuidihuzhu.sdb.models.Response<Boolean> initCollection(@RequestParam(name = "databaseName",required = true) String databaseName,
                                                                       @RequestParam(name = "collectionName",required = true) String collectionName){
        SdbCommonAssert.notBlank(databaseName, ErrorCode.PARAMS_IS_NULL);
        SdbCommonAssert.notBlank(collectionName, ErrorCode.PARAMS_IS_NULL);
        List<String> listDatabase = CLIENT.listDatabase();
        Boolean clientBuildFlag = Boolean.FALSE;
        for (String database : listDatabase){
            if(Objects.equals(database,databaseName)){
                clientBuildFlag = Boolean.TRUE;
            }
        }
        Database db = null;
        if(!clientBuildFlag){
            db = this.buildDatabase(databaseName);
        }else {
            db = CLIENT.database(databaseName);
        }
        Boolean collectionFlag = Boolean.FALSE;
        Collection collection = null;
        List<Collection> collections = db.listCollections();
        for(Collection collectionItem : collections){
            if(Objects.equals(collectionItem.getCollection(),collectionName)){
                collectionFlag = Boolean.TRUE;
                collection = collectionItem;
            }
        }
        if(!collectionFlag){
            CreateCollectionParam collectionParam = CreateCollectionParam.newBuilder()
                    .withName(collectionName)
                    .withReplicaNum(2)
                    .withShardNum(1)
                    .withDescription("小超公司基本法信息章节存储表,存储小超公司历史基本法信息及基本法版本信息")
                    .addField(new FilterIndex("id", FieldType.String, IndexType.PRIMARY_KEY))
                    .addField(new FilterIndex("chapterName", FieldType.String, IndexType.FILTER))
                    .addField(new FilterIndex("pageNo", FieldType.Uint64, IndexType.FILTER))
                    .addField(new FilterIndex("chapterNo", FieldType.Uint64, IndexType.FILTER))
                    .addField(new FilterIndex("parentChapterNo", FieldType.Uint64, IndexType.FILTER))
                    .addField(new VectorIndex("vector", 768, IndexType.HNSW, MetricType.COSINE, new HNSWParams(16, 200)))
                    .withEmbedding(
                            Embedding
                                    .newBuilder()
                                    .withModel(EmbeddingModelEnum.BGE_BASE_ZH)
                                    .withField("lawText")
                                    .withVectorField("vector")
                                    .build())
                    .build();
            collection = db.createCollection(collectionParam);
            AffectRes affectRes = db.setAlias(collectionName, collectionName);
            if(Objects.equals(affectRes.getCode(),0)){
                log.info("VectorTestController  initCollection setAlias -----------成功 , collectionName = {}", collectionName);
            }else {
                log.info("VectorTestController   initCollection setAlias -----------失败 , collectionName = {} ,affectRes = {}", collectionName,JsonUtil.getJsonString(affectRes));
            }
        }
        
//该信息为虚拟信息,不能产生任何价值也不代表任何利益相关,纯粹是虚拟构建
        Document doc1 = Document.newBuilder()
                .withId("test0001")
                .addDocField(new DocField("chapterName","首年度佣金发放规则"))
                .addDocField(new DocField("pageNo",13))
                .addDocField(new DocField("chapterNo",22))
                .addDocField(new DocField("parentChapterNo",5))
                .addDocField(new DocField("lawText","首年度佣金发放规则:一、保单在当月最后一天(含)前承保(包括当月承保及之前月份承保未核发佣金的保单);二、保单在次月XX日(含)前回访成功;三、保单在次月XX日(含)前完成《委托协议书》及《客户告知书》的签署;四、保单在次月XX日(含)前为非犹豫期退保状态;五、依据当地监管要求,保单在下月XX日(含)前完成质检;"))
                .build();

   
//该信息为虚拟信息,不能产生任何价值也不代表任何利益相关,纯粹是虚拟构建
        Document doc13 = Document.newBuilder()
                .withId("test0013")
                .addDocField(new DocField("chapterName","产品名称:XX保意外险"))
                .addDocField(new DocField("pageNo",45))
                .addDocField(new DocField("chapterNo",76))
                .addDocField(new DocField("parentChapterNo",1))
                .addDocField(new DocField("lawText","商品编码:rbywx\t\n" +
                        "产品名称:xXX保意外险\n" +
                        "保司简称:XXX保财险\n" +
                        "长短险标志:长险\n" +
                        "险种标志:意外\n" +
                        "等待期天数:30\n" +
                        "犹豫期天数:30\n" +
                        "宽限期天数:60\n" +
                        "一句话卖点:全面升级,保障更加多元\n" +
                        "产品卖点:[\"意外伤害保额最高XX万\",\"因为意外情况住院不会限制社保的报销范围\",\"因为意外住院享受住院津贴,因为意外骨折后后相关保障计划\"]\n" +
                        "最低保费描述:XX元起\n" +
                        "最高保费:XX\n" +
                        "职业范围描述:1-6类\n" +
                        "投保最小年龄限制(岁):X2\n" +
                        "投保最大年龄限制(岁):X1\n" +
                        "健康告知及注意事项:常见健康告知xxxxxx\n"))
                .build();

        InsertParam insertParam = InsertParam.newBuilder()
                .addDocument(doc1)
                .addDocument(doc13)
                .withBuildIndex(true)
                .build();
        AffectRes affectRes = collection.upsert(insertParam);
        if(Objects.equals(affectRes.getCode(),0)){
            log.info("VectorTestController  initCollection collectionUpsert -----------成功 , affectRes = {}", affectRes);
        }else {
            log.info("VectorTestController   initCollection collectionUpsert -----------失败 , insertParam = {} ,affectRes = {}", JsonUtil.getJsonString(insertParam),JsonUtil.getJsonString(affectRes));
        }
        return ResponseUtil.makeSuccess(Boolean.TRUE);
    }

清除指定构建的数据

java 复制代码
/**
     * 清空指定集合
     * @return 初始化数据与否
     */
    @RequestMapping("test/cleanXXX")
    public com.shuidihuzhu.sdb.models.Response<Boolean> cleanCollection(@RequestParam(name = "databaseName",required = true) String databaseName,
                                                                        @RequestParam(name = "collectionName",required = true) String collectionName){
        SdbCommonAssert.notBlank(databaseName, ErrorCode.PARAMS_IS_NULL);
        SdbCommonAssert.notBlank(collectionName, ErrorCode.PARAMS_IS_NULL);
        List<String> stringList = CLIENT.listDatabase();
        Boolean clientBuildFlag = Boolean.FALSE;
        for (String database : stringList){
            if(Objects.equals(database,databaseName)){
                clientBuildFlag = Boolean.TRUE;
            }
        }
        Database db = null;
        if(!clientBuildFlag){
            db = this.buildDatabase(databaseName);
        }else {
            db = CLIENT.database(databaseName);
        }
        AffectRes affectRes = db.truncateCollections(collectionName);
        log.info("cleanCollection result, affectRes = {}",JsonUtil.getJsonString(affectRes));
        return ResponseUtil.makeSuccess(Objects.equals(affectRes.getCode(),0));
    }

GPT交互接口

1、请求体

这里是请求GPT交互接口的请求体

java 复制代码
/**
 * @author chao
 * @date 2024/3/14
 **/
@Getter
@Setter
@Accessors(chain = true)
@FieldDefaults(level = AccessLevel.PRIVATE)
public class MsgDto {

    /**
     * databaseName  数据库名称
     */
    private String databaseName;
    /**
     * collectionName 集合名称
     */
    private String collectionName;

    /**
     * appCode
     */
    private String appCode;

    /**
     * 子模型
     */
    private String aiModel = "gpt-3.5-turbo";


    /**
     * 会话内容-把会话内容信息存到一起,可为空
     * 如果想持续获取内容,建议在初次生成后获取并存入
     */
    private String sessionId;

    /**
     * 消息体内容
     */
    private String prompt;

    /**
     * token数,可为空,默认300
     */
    private Integer maxTokens;


    /**
     * 调节信息 ,可为空,默认0.0
     */
    private Double temperature;


    /**
     * 输出Json ,默认True
     */
    private Boolean outputJsonFlag = Boolean.TRUE;

    /**
     * 排名分数阈值(建议0.75)
     */
    private Double scoreFlag = 0.77;

}

2、GPT请求接口

这里是构建GPT会话信息属于公共方法。
相关GPT的请求类和消息体类请自己根据官方文档进行包装,这里没有进行包装。

java 复制代码
/**
     * 构建GPT请求
     * @param sessionId 会话内容
     * @param appCode 租户编号
     * @param body 消息提提
     * @return
     */
    private ChatCompletionResponseV2 completionBuild(String sessionId,String appCode, ChatCompletionBodyV2 body){
        SdbCommonAssert.notBlank(sessionId,ErrorCode.PARAMS_IS_NULL,"sessionId value not null");
        SdbCommonAssert.notBlank(appCode,ErrorCode.PARAMS_IS_NULL,"appCode value not null");
        SdbCommonAssert.notNull(body,ErrorCode.PARAMS_IS_NULL,"body value not null");
        ChatCompletionRequestV2 chatRequest = new ChatCompletionRequestV2();
        chatRequest.setAppCode(appCode);
        chatRequest.setChatCompletionBody(body);

        log.info("innerChatCompletionsV2 chatRequest sessionId = {}, appCode = {}, chatRequest = {}",
                sessionId,JsonUtil.getJsonString(appCode),JsonUtil.getJsonString(chatRequest));
        Response<ChatCompletionResponseV2> gptResponse = chatGptOverseaClient.innerChatCompletionsV2(chatRequest);
        if(!Objects.equals(gptResponse.getCode(),0)
                || Objects.isNull(gptResponse.getData())){
            log.error("innerChatCompletionsV2 gptResponse value is null, sessionId = {}, chatRequest = {} , gptResponse = {}"
                    ,sessionId,JsonUtil.getJsonString(chatRequest),JsonUtil.getJsonString(gptResponse));
            return null;
        }
        List<ChoiceV2> choices = gptResponse.getData().getChoices();
        if(CollectionUtils.isEmpty(choices)){
            log.error("innerChatCompletionsV2 choices value is empty, sessionId = {}, chatRequest = {} , gptResponse = {}"
                    ,sessionId,JsonUtil.getJsonString(chatRequest),JsonUtil.getJsonString(gptResponse));
            return null;
        }
        //检查内容 默认 TRUE 正确
        Boolean checkChoice = Boolean.TRUE;
        for (ChoiceV2 choice : choices){
            if(Objects.isNull(choice)
                    || Objects.isNull(choice.getMessage())){
                log.error("innerChatCompletionsV2 choice value is null, sessionId = {}, chatRequest = {} , gptResponse = {}"
                        ,sessionId,JsonUtil.getJsonString(chatRequest),JsonUtil.getJsonString(gptResponse));
                checkChoice = Boolean.FALSE;
                continue;
            }
            ChoiceV2.ResMessage message = choice.getMessage();
            if(StringUtils.isBlank(message.getContent())
                    && CollectionUtils.isEmpty(message.getTool_calls())){
                log.error("innerChatCompletionsV2 choice value is null, sessionId = {}, chatRequest = {} , gptResponse = {}"
                        ,sessionId,JsonUtil.getJsonString(chatRequest),JsonUtil.getJsonString(gptResponse));
                checkChoice = Boolean.FALSE;
            }
        }
        if(!checkChoice){
            log.error("innerChatCompletionsV2 choice value is null, sessionId = {}, chatRequest = {} , gptResponse = {}"
                    ,sessionId,JsonUtil.getJsonString(chatRequest),JsonUtil.getJsonString(gptResponse));
            return null;
        }
        return gptResponse.getData();
    }

3、GPT交互接口

真实的GPT交互接口

java 复制代码
    /**
     * GPT交互接口
     * @param msgDto
     * @return
     */
    @RequestMapping("test/gptXXX")
    public com.shuidihuzhu.sdb.models.Response<MsgResponseDto> innerChatCompletionsV2(@RequestBody(required = true) MsgDto msgDto){
        SdbCommonAssert.notNull(msgDto, ErrorCode.PARAMS_IS_NULL);
        SdbCommonAssert.notBlank(msgDto.getDatabaseName(),ErrorCode.PARAMS_IS_NULL);
        SdbCommonAssert.notBlank(msgDto.getCollectionName(),ErrorCode.PARAMS_IS_NULL);
        SdbCommonAssert.notBlank(msgDto.getAppCode(),ErrorCode.PARAMS_IS_NULL);
        SdbCommonAssert.notBlank(msgDto.getAiModel(),ErrorCode.PARAMS_IS_NULL);
        SdbCommonAssert.notBlank(msgDto.getPrompt(),ErrorCode.PARAMS_IS_NULL);
        String sessionId = msgDto.getSessionId();
        if(StringUtils.isBlank(sessionId)){
        //唯一串生成代码,请替换成自己的或使用UUID
            sessionId = uniqueCodeComponent.getUniqueCode();
            msgDto.setSessionId(sessionId);
        }

        Database db = CLIENT.database(msgDto.getDatabaseName());
        Collection collection = db.collection(msgDto.getCollectionName());

        String prompt = msgDto.getPrompt();
        SearchByEmbeddingItemsParam searchByEmbeddingItemsParam = SearchByEmbeddingItemsParam.newBuilder()
                .withEmbeddingItems(Collections.singletonList(prompt))
                // 若使用 HNSW 索引,则需要指定参数 ef,ef 越大,召回率越高,但也会影响检索速度
                .withParams(new HNSWSearchParams(200))
                // 设置标量字段的 Filter 表达式,过滤所需查询的文档
                .withRetrieveVector(false)
                // 指定 Top K 的 K 值
                .withLimit(3)
                // 使用 filter 过滤数据
//                .withFilter(new Filter(Filter.in("bookName", Arrays.asList("三国演义","西游记"))))
                // 指定返回的 fields
                .withOutputFields(Arrays.asList("chapterName",  "lawText"))
                .build();
        SearchRes searchRes = collection.searchByEmbeddingItems(searchByEmbeddingItemsParam);
        AtomicReference searchFlag = new AtomicReference(Boolean.FALSE);
        if(Objects.equals(searchRes.getCode(),0) && CollectionUtils.isNotEmpty(searchRes.getDocuments())){
            log.info("VectorTestController  innerChatCompletionsV2 searchByEmbeddingItems -----------成功");
            StringBuilder promptBuilder = new StringBuilder();
            promptBuilder.append("提供的资料以\"...\"开头和结尾,请以提供的资料为参考进行问题的解答,如果提供的资料无法回答再根据用户实际问题进行谨慎回答。");
            promptBuilder.append("...开始\n");
            List<List<Document>> documentArray = searchRes.getDocuments();
            documentArray.forEach(documents -> {
                documents.forEach(document -> {
                    if(document.getScore() < msgDto.getScoreFlag()){
                        return;
                    }
                    document.getDocFields().forEach(docField -> {
                        promptBuilder.append(docField.getValue());
                        promptBuilder.append("\n");
                        searchFlag.set(Boolean.TRUE);
                    });
                });
            });
            promptBuilder.append("...结束\n");
            promptBuilder.append("用户问题\n:");
            promptBuilder.append(prompt);
            promptBuilder.append("\n");
            if((Boolean)searchFlag.get()){
                prompt = promptBuilder.toString();
            }else {
                prompt = "在保险行业中," + prompt;
            }
        }else {
            prompt = "在保险行业中," + prompt;
            log.info("VectorTestController  innerChatCompletionsV2 searchByEmbeddingItems -----------失败,searchRes = {}, searchByEmbeddingItemsParam = {}", JsonUtil.getJsonString(searchRes),JsonUtil.getJsonString(searchByEmbeddingItemsParam));
        }
        log.info("innerChatCompletionsV2 sessionId = {}, msgDto = {}",sessionId,JsonUtil.getJsonString(msgDto));
        LinkedList<MessageV2> msgLinkedList = SESSION_MSG_MAP.get(sessionId);
        if(CollectionUtils.isEmpty(msgLinkedList)){
            msgLinkedList = new LinkedList<>();
            MessageV2 systemMessage = new MessageV2();
            systemMessage.setRole("system");
            String newSysMsg = sysMsgStr + "";
            systemMessage.setContent(newSysMsg);
            msgLinkedList.add(systemMessage);

            MessageV2 userMessage = new MessageV2();
            userMessage.setRole("user");
            userMessage.setContent(prompt);
            msgLinkedList.add(userMessage);

            SESSION_MSG_MAP.put(sessionId,msgLinkedList);
        }else{
            MessageV2 userMessage = new MessageV2();
            userMessage.setRole("user");
            userMessage.setContent(prompt);
            msgLinkedList.add(userMessage);
        }
        ChatCompletionBodyV2 body = new ChatCompletionBodyV2();
        body.setLogit_bias(new HashMap<>());
        body.setMessages(new ArrayList<>(msgLinkedList));
        body.setModel(msgDto.getAiModel());
        body.setN(1);
        if(Objects.nonNull(msgDto.getTemperature())){
            body.setTemperature(msgDto.getTemperature());
        }else {
            body.setTemperature(0.0);
        }
        if(Objects.nonNull(msgDto.getMaxTokens())){
            body.setMax_tokens(msgDto.getMaxTokens());
        }else {
            body.setMax_tokens(300);
        }

        body.setStream(Boolean.FALSE);
//        if (msgDto.getOutputJsonFlag()) {
//            ResponseFormat responseFormat = new ResponseFormat();
//            responseFormat.setType("json_object");
//            body.setResponse_format(responseFormat);
//        }
        body.setTool_choice("auto");
        List<Tool> toolList = new ArrayList<>(1);
        Tool tool = new Tool();
        toolList.add(tool);
        tool.setType("function");
        Tool.ToolFunction toolFunction = new Tool.ToolFunction();
        toolFunction.setName("buyInsuranceProduct");
        toolFunction.setDescription("向这个接口传入保险产品编码或者保险产品名称,可以获得该保险产品的下单链接以及相关宣传信息");
        JSONObject jsonObject = new JSONObject();
        toolFunction.setParameters(jsonObject);
        jsonObject.put("type","object");
        JSONObject propertiesObject = new JSONObject();
        jsonObject.put("properties",propertiesObject);
        jsonObject.put("required", new JSONArray(List.of("searchKey")));

        JSONObject searchKeyParam = new JSONObject();
        propertiesObject.put("searchKey",searchKeyParam);
        searchKeyParam.put("type","string");
        searchKeyParam.put("description","保险产品名称或者保险产品编码");
        tool.setFunction(toolFunction);

        body.setTools(toolList);

        //构建GPT请求
        ChatCompletionResponseV2 gptResponse = this.completionBuild(sessionId, msgDto.getAppCode(), body);
        MsgResponseDto msgResponse = new MsgResponseDto();
        if(Objects.nonNull(gptResponse)){
            List<ChoiceV2> choices = gptResponse.getChoices();
            for (ChoiceV2 choice : choices){
                ChoiceV2.ResMessage message = choice.getMessage();
                MessageV2 assistantMessage = new MessageV2();
                assistantMessage.setRole(message.getRole());
                if(StringUtils.isNotBlank(message.getContent())){
                    assistantMessage.setContent(message.getContent());
                }
                msgLinkedList.add(assistantMessage);
                if(CollectionUtils.isNotEmpty(message.getTool_calls())){
                    List<ChoiceV2.ResToolCall> resToolCalls = message.getTool_calls();
                    List<MessageV2.ToolCall> toolCalls = new ArrayList<>(resToolCalls.size());
                    resToolCalls.forEach(callFunction -> {
                        MessageV2.Function function = callFunction.getFunction();
//                        assistantMessage.setName(function.getName());
//                        assistantMessage.setTool_call_id(callFunction.getId());
                        MessageV2.ToolCall toolCall = new MessageV2.ToolCall();
                        toolCall.setId(callFunction.getId());
                        toolCall.setType(callFunction.getType());
                        toolCall.setFunction(function);
                        toolCalls.add(toolCall);
                    });
                    assistantMessage.setTool_calls(toolCalls);
                    for(ChoiceV2.ResToolCall toolCall : resToolCalls){
                        MessageV2.Function function = toolCall.getFunction();
                        if(Objects.nonNull(function)
                                && StringUtils.isNotBlank(function.getName())
                                && StringUtils.isNotBlank(function.getArguments())){
                            String functionName = function.getName();
                            if(Objects.equals(functionName,"buyInsuranceProduct")){
                                String functionArguments = function.getArguments();
                                //arguments value :{"searchKey":"XXX医疗险(家庭版)"}
                                JSONObject param = JSONObject.parseObject(functionArguments);
                                String insuranceProductInfo = this.getInsuranceProductInfo(param.getString("searchKey"));
                                MessageV2 functionReqMessage = new MessageV2();
                                functionReqMessage.setRole("tool");
                                functionReqMessage.setContent(insuranceProductInfo);
                                functionReqMessage.setTool_call_id(toolCall.getId());
                                functionReqMessage.setName(functionName);
                                msgLinkedList.add(functionReqMessage);
                            }
                        }
                    }
                    body.setMessages(new ArrayList<>(msgLinkedList));
                    //构建GPT请求
                    ChatCompletionResponseV2 functionGptResponse = this.completionBuild(sessionId, msgDto.getAppCode(), body);
                    if(Objects.nonNull(functionGptResponse)){
                        gptResponse = functionGptResponse;
                        List<ChoiceV2> functionChoices = functionGptResponse.getChoices();
                        for (ChoiceV2 functionChoice : functionChoices){
                            ChoiceV2.ResMessage functionResMessage = functionChoice.getMessage();
                            MessageV2 functionAssistantResMessage = new MessageV2();
                            functionAssistantResMessage.setRole(functionResMessage.getRole());
                            functionAssistantResMessage.setContent(functionResMessage.getContent());
                            msgLinkedList.add(functionAssistantResMessage);
                        }
                    }else{
                        log.error("innerChatCompletionsV2 gptResponse value is null sessionId = {}, msgDto = {} , gptResponse = {}"
                                ,sessionId,JsonUtil.getJsonString(msgDto),JsonUtil.getJsonString(gptResponse));
                        MessageV2 errorAssistantMessage = new MessageV2();
                        errorAssistantMessage.setRole("assistant");
                        errorAssistantMessage.setContent("信息好像丢失了,请更详细的描述您的要求并重试!");
                        msgLinkedList.add(errorAssistantMessage);
                    }
                }
            }
            log.info("innerChatCompletionsV2 ResponseBody sessionId = {}, msgDto = {} , msgResponse = {}"
                    ,sessionId,JsonUtil.getJsonString(msgDto),JsonUtil.getJsonString(msgResponse));
        } else{
            log.error("innerChatCompletionsV2 gptResponse value is null sessionId = {}, msgDto = {} , gptResponse = {}"
                    ,sessionId,JsonUtil.getJsonString(msgDto),JsonUtil.getJsonString(gptResponse));
            MessageV2 errorAssistantMessage = new MessageV2();
            errorAssistantMessage.setRole("assistant");
            errorAssistantMessage.setContent("信息好像丢失了,请更详细的描述您的要求并重试!");
            msgLinkedList.add(errorAssistantMessage);
        }
        msgResponse.setRequestMsg(msgDto);
        msgResponse.setSessionId(sessionId);
        msgResponse.setMsgLinkedList(msgLinkedList);
        msgResponse.setResponseMsg(gptResponse);
        //保证顺序为 user|assistant  交替进行
        MessageV2 last = msgLinkedList.getLast();
        MessageV2 messageV2 = msgLinkedList.get(msgLinkedList.size() - 2);
        if(Objects.equals(last.getRole(),"user") && Objects.equals(messageV2.getRole(),"assistant")){
            msgLinkedList.removeLast();
        }else if(Objects.equals(last.getRole(),"user") && Objects.equals(messageV2.getRole(),"system")){
            msgLinkedList.removeLast();
        }else if(Objects.equals(last.getRole(),"user") && Objects.equals(messageV2.getRole(),"function")){
            msgLinkedList.removeLast();
        }
        log.info("innerChatCompletionsV2 SESSION_MSG_MAP = {}", JsonUtil.getJsonString(SESSION_MSG_MAP));
        return ResponseUtil.makeSuccess(msgResponse);
    }

4、获取产品信息

这里模拟得数查询数据库信息后续可进行替换

java 复制代码
    /**
     * 获取产品下单信息
     * @param productSearchKey 产品名称或者产品编码
     * @return
     */
    private String getInsuranceProductInfo(String productSearchKey){
        log.info("innerChatCompletionsV2 getInsuranceProductInfo param,productSearchKey = {} ", productSearchKey);


        JSONObject rbdjJsonObject = new JSONObject();
        rbdjJsonObject.put("productName","xXX保意外险");
        rbdjJsonObject.put("productDesc","这是xXX保意外险的产品描述");
        rbdjJsonObject.put("productOrderUrl","www.baidu.com/XXX_XXYWX_XXYWX");


        JSONObject ygrsJsonObject = new JSONObject();
        ygrsJsonObject.put("productName","SDFSDF人寿SDFFD高端SDFSDF保险");
        ygrsJsonObject.put("productDesc","这是SDFSDF人寿SDFFD高端SDFSDF保险的产品描述");
        ygrsJsonObject.put("productOrderUrl","www.baidu.com/SDF_SDSDFrs_SDDFSFFSDFSDlbx");

        JSONObject ygrszzJsonObject = new JSONObject();
        ygrszzJsonObject.put("productName","阳光XSDSDSXX臻享XXDSDX高端XXSDSSDDX保险");
        ygrszzJsonObject.put("productDesc","这是阳光XXDX臻享XXSDDX高端XSDSDXX保险的产品描述");
        ygrszzJsonObject.put("productOrderUrl","www.baidu.com/XX_ygXXXs_zzSADSFADFgdylbx");

        JSONObject lybJsonObject = new JSONObject();
        lybJsonObject.put("productName","XXX·XX医疗险(XXX版)");
        lybJsonObject.put("productDesc","这是XXX·XX医疗险(XXX版)的产品描述");
        lybJsonObject.put("productOrderUrl","www.baidu.com/fXX_lXASDXXcqXXXSDFXlx_jXXtXXXb");

        JSONObject sdhsjJsonObject = new JSONObject();
        sdhsjJsonObject.put("productName","XXX护身甲XXX意外险");
        sdhsjJsonObject.put("productDesc","这是XASDXX护身甲XXASX意外险的产品描述");
        sdhsjJsonObject.put("productOrderUrl","www.baidu.com/zXXXDSAXx_XDASXhsXFDGjXXX");

        JSONArray array = new JSONArray();
        array.add(rbdjJsonObject);
        array.add(ygrsJsonObject);
        array.add(ygrszzJsonObject);
        array.add(lybJsonObject);
        array.add(sdhsjJsonObject);
        log.info("innerChatCompletionsV2 getInsuranceProductInfo result,array = {} ", array);
        return array.toString();
    }

5、返回的消息体
相关GPT的请求类和消息体类请自己根据官方文档进行包装,这里没有进行包装。

java 复制代码
/**
 * @author chao
 * @date 2024/3/14
 **/
@Getter
@Setter
@Accessors(chain = true)
@FieldDefaults(level = AccessLevel.PRIVATE)
public class MsgResponseDto {
    /**
     * 传入的消息体
     */
    private MsgDto requestMsg;

    /**
     * 返回的内容-
     */
    private ChatCompletionResponseV2 responseMsg;


    /**
     * 生成或者传入的消息体ID
     */
    private String sessionId;

    /**
     * 目前该SessionId下存储的消息内容
     */
    private LinkedList<MessageV2> msgLinkedList;
}
相关推荐
csudata27 分钟前
绿色便携版PostgreSQL发行版重磅发布
数据库·postgresql
乱世刀疤33 分钟前
OpenCode在Windows上的安装与使用入门 | 保姆级教程
ai编程
阳光九叶草LXGZXJ1 小时前
达梦数据库-学习-48-DmDrs控制台命令(同步之Manager、CPT模块)
linux·运维·数据库·sql·学习
DisonTangor1 小时前
DeepSeek-OCR 2: 视觉因果流
人工智能·开源·aigc·ocr·deepseek
薛定谔的猫19821 小时前
二十一、基于 Hugging Face Transformers 实现中文情感分析情感分析
人工智能·自然语言处理·大模型 训练 调优
发哥来了1 小时前
《AI视频生成技术原理剖析及金管道·图生视频的应用实践》
人工智能
我科绝伦(Huanhuan Zhou)1 小时前
脚本再升级,兼容Oracle 26ai一键安装
数据库·oracle
数智联AI团队2 小时前
AI搜索引领开源大模型新浪潮,技术创新重塑信息检索未来格局
人工智能·开源
不懒不懒2 小时前
【线性 VS 逻辑回归:一篇讲透两种核心回归模型】
人工智能·机器学习
野生绿箭侠2 小时前
Ncos 2.3.2 版本集成达梦数据库
数据库