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

发布于:2024-03-23 ⋅ 阅读:(35) ⋅ 点赞:(0)

引言

将 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依赖

<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和相关账户请替换成自己的


/**
     * 链接信息
     */
    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、创建腾讯云数据库

/**
     * 创建腾讯云数据库
     * @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、向指定数据库和分区构建初始化数据

/**
     * 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);
    }

清除指定构建的数据

/**
     * 清空指定集合
     * @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交互接口的请求体

/**
 * @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的请求类和消息体类请自己根据官方文档进行包装,这里没有进行包装。

/**
     * 构建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交互接口

    /**
     * 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、获取产品信息
这里模拟得数查询数据库信息后续可进行替换

    /**
     * 获取产品下单信息
     * @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的请求类和消息体类请自己根据官方文档进行包装,这里没有进行包装。

/**
 * @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;
}
本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到