当前位置: 首页 > news >正文

Spring Boot3批式访问Dify聊天助手接口

Spring Boot3批式访问Dify聊天助手接口

前言

之前已经配置好Dify1.4.1及LM Studio集成:

https://lizhiyong.blog.csdn.net/article/details/148607462

现在就可以借助Spring Boot3去访问Dify的后端接口,让前端展示大模型的返回内容。这是我等大数据资深学徒工们久经验证,在实际生产环境的正确使用方法,较直接调用大模型接口,使用聊天助手、工作流等方式做一层中间件包装后更安全、可控,可观测性也很好便于大数据平台开发攻城狮们查找到不良租户。

Dify聊天助手配置

为了防止超时,笔者配置的是DeepSeek14b小模型:

在这里插入图片描述

配置聊天助手时需要开启Think模式:

在这里插入图片描述

此时验证下:

在这里插入图片描述

可以正确调用LLM了!!!更新、发布、生成Token素质三联!!!

Dify接口文档

访问API即可看到接口文档,主要内容:

接口地址:

http://localhost/v1Authorization: Bearer {API_KEY}

批式访问的请求报文:

curl -X POST 'http://localhost/v1/chat-messages' \
--header 'Authorization: Bearer {api_key}' \
--header 'Content-Type: application/json' \
--data-raw '{"inputs": {},"query": "What are the specs of the iPhone 13 Pro Max?","response_mode": "streaming","conversation_id": "","user": "abc-123","files": [{"type": "image","transfer_method": "remote_url","url": "https://cloud.dify.ai/logo/logo-site.png"}]
}'

批式访问的响应报文:

{"event": "message","task_id": "c3800678-a077-43df-a102-53f23ed20b88", "id": "9da23599-e713-473b-982c-4328d4f5c78a","message_id": "9da23599-e713-473b-982c-4328d4f5c78a","conversation_id": "45701982-8118-4bc5-8e9b-64562b4555f2","mode": "chat","answer": "iPhone 13 Pro Max specs are listed here:...","metadata": {"usage": {"prompt_tokens": 1033,"prompt_unit_price": "0.001","prompt_price_unit": "0.001","prompt_price": "0.0010330","completion_tokens": 128,"completion_unit_price": "0.002","completion_price_unit": "0.001","completion_price": "0.0002560","total_tokens": 1161,"total_price": "0.0012890","currency": "USD","latency": 0.7682376249867957},"retriever_resources": [{"position": 1,"dataset_id": "101b4c97-fc2e-463c-90b1-5261a4cdcafb","dataset_name": "iPhone","document_id": "8dd1ad74-0b5f-4175-b735-7d98bbbb4e00","document_name": "iPhone List","segment_id": "ed599c7f-2766-4294-9d1d-e5235a61270a","score": 0.98457545,"content": "\"Model\",\"Release Date\",\"Display Size\",\"Resolution\",\"Processor\",\"RAM\",\"Storage\",\"Camera\",\"Battery\",\"Operating System\"\n\"iPhone 13 Pro Max\",\"September 24, 2021\",\"6.7 inch\",\"1284 x 2778\",\"Hexa-core (2x3.23 GHz Avalanche + 4x1.82 GHz Blizzard)\",\"6 GB\",\"128, 256, 512 GB, 1TB\",\"12 MP\",\"4352 mAh\",\"iOS 15\""}]},"created_at": 1705407629
}

就是常规的Post+Json模式!!!

Spring Boot3编码实现

依赖

简单配置一些依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.4.6</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.zhiyong</groupId><artifactId>spring.study</artifactId><version>0.0.1-SNAPSHOT</version><name>spring.study</name><description>Demo project for Spring Boot</description><url/><licenses><license/></licenses><developers><developer/></developers><scm><connection/><developerConnection/><tag/><url/></scm><properties><java.version>17</java.version><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><maven.test.skip>true</maven.test.skip><fastjson.version>1.2.83</fastjson.version><log4j2.version>2.20.0</log4j2.version><disruptor.version>3.4.2</disruptor.version><mybatis-plus.version>3.5.12</mybatis-plus.version><druid.version>1.2.23</druid.version><mysql-connector.version>8.0.33</mysql-connector.version><hutool.version>5.8.11</hutool.version><mapstruct.version>1.5.5.Final</mapstruct.version><xxl.job.version>2.4.0</xxl.job.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-api</artifactId><version>${log4j2.version}</version></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>${log4j2.version}</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-3-starter</artifactId><version>${druid.version}</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>${fastjson.version}</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.4</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.9</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.36</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter-test</artifactId><version>3.0.4</version><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><annotationProcessorPaths><path><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></path><path><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId></path></annotationProcessorPaths></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>

配置文件

spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverdruid:url: jdbc:mysql://127.0.0.1:3306/library_1?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=trueusername: rootpassword: 123456initial-size: 5min-idle: 15max-active: 30remove-abandoned-timeout: 180max-wait: 300000time-between-eviction-runs-millis: 60000min-evictable-idle-time-millis: 300000max-evictable-idle-time-millis: 900000stat-view-servlet:enabled: trueloginUsername: adminloginPassword: 123456allow:web-stat-filter:enabled: truesession-stat-enable: truesession-stat-max-count: 1000url-pattern: /*filters: stat,wall,slf4jfilter:stat:enabled: truedb-type: mysqllog-slow-sql: trueslow-sql-millis: 2000Dify:token: app-TNwXhtAMGxq3HfYPUCINeImgurl: http://localhost/v1/chat-messagesuser: CSDN@HBaseIsNotFish

Controller

package com.zhiyong.spring.study.controller;import com.zhiyong.spring.study.service.DifyLlmService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;import java.util.Map;@RestController
@RequestMapping("/Dify")
@Slf4j
public class DifyController {@AutowiredDifyLlmService difyLlmService;@PostMapping("/get/llm/solution")public Map<String,Object> getAnswerByQueryBatch(@RequestHeader("UserId") String UserId, @RequestParam("query") String query) {log.info("入参query={}", query);Map<String,Object> result= difyLlmService.getAnswerByQueryBatch(query);
//        result.put("llmSolution", query);
//        result.put("thinkProcess", "思考中"+System.currentTimeMillis());return result;}
}

后续可以PostMan通过调用该接口验证可行性

Service

package com.zhiyong.spring.study.service;import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;import java.util.Map;public interface DifyLlmService {Map<String, Object> getAnswerByQueryBatch(String query);
}

用于封装接口

Impl

package com.zhiyong.spring.study.service.Impl;import com.alibaba.fastjson.JSONObject;
import com.zhiyong.spring.study.Obj.Entity.DifyBatchReqMessage;
import com.zhiyong.spring.study.Obj.Entity.DifyBatchResMessage;
import com.zhiyong.spring.study.Obj.Entity.DifyStreamReqMessage;
import com.zhiyong.spring.study.service.DifyLlmService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;@Service
@Slf4j
public class DifyLlmServiceImpl implements DifyLlmService {@Value("${Dify.token}")private String difyToken;@Value("${Dify.url}")private String difyUrl;@Value("${Dify.user}")private String difyUser;@Autowiredprivate RestTemplate restTemplate;private String getQuery(String queryInput) {return "有个问题," + queryInput + "?";}private String getReqMessageBatch(String queryInput) {String query = getQuery(queryInput);String reqMessage = "";DifyBatchReqMessage batchReqMessage = new DifyBatchReqMessage();batchReqMessage.setUser(difyUser);batchReqMessage.setQuery(query);reqMessage = JSONObject.toJSONString(batchReqMessage);return reqMessage;}@Overridepublic Map<String, Object> getAnswerByQueryBatch(String query) {String answer = "";String reqMessage = getReqMessageBatch(query);HttpHeaders httpHeaders = new HttpHeaders();httpHeaders.setContentType(MediaType.APPLICATION_JSON);httpHeaders.setBearerAuth(difyToken);HttpEntity<String> batchResMessageHttpEntity = new HttpEntity<>(reqMessage, httpHeaders);try {ResponseEntity<DifyBatchResMessage> entity = restTemplate.postForEntity(difyUrl, batchResMessageHttpEntity, DifyBatchResMessage.class);if (!entity.getStatusCode().is2xxSuccessful()) {log.error("调用Dify接口失败{}", entity.getStatusCode().value());}answer = entity.getBody().getAnswer();log.info("answer={}", answer);} catch (Exception e) {log.error("调用Dify接口出现异常,{}", e.getMessage());}Map<String, Object> result = new HashMap<>();String[] split = answer.split("</think>");String[] split1 = split[0].split("<think>");log.info("llmSolution,{}", split[1]);log.info("thinkProcess,{}", split1);result.put("llmSolution", split[1]);result.put("thinkProcess", split1);return result;}
}

Entity

package com.zhiyong.spring.study.Obj.Entity;import lombok.Data;import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;@Data
public class DifyBatchReqMessage {Map<String, Object> inputs = new HashMap<>();String query = "";String mode = "chat";String conversation_id = "";String user = "";List<Map<String, String>> files = new LinkedList<>();
}

批式请求的实体主要是这种格式

package com.zhiyong.spring.study.Obj.Entity;import lombok.Data;import java.util.HashMap;
import java.util.Map;@Data
public class DifyBatchResMessage {String event = "";String task_id = "";String id = "";String message_id = "";String conversation_id = "";String mode = "";String answer = "";Map<String, Object> metadata = new HashMap<>();String created_at = "";
}

批式请求的响应实体主要是这种格式

接口验证

http://127.0.0.1:9999/Dify/get/llm/solution

在这里插入图片描述

填写必要的请求头和请求参数后,接口在90s以后返回了内容:

{"llmSolution": "虎鲸是鱼吗?\n\n**结论:虎鲸不是鱼,而是哺乳动物。**\n\n解释:\n\n1. **分类基础**:\n   - 鱼类和哺乳动物都属于脊椎动物,但它们有不同的特征。\n\n2. **鱼类的特征**:\n   - 用鳃呼吸。\n   - 大多为卵生或卵胎生。\n\n3. **哺乳动物的特征**:\n   - 用肺呼吸。\n   - 胎生,通过哺乳喂养幼崽。\n\n4. **虎鲸的分类**:\n   - 属于鲸鱼,是哺乳动物。\n   - 尽管生活在海洋中,但它们符合哺乳动物的定义,因此不是鱼类。\n\n总结:虎鲸虽然是水生生物,但属于哺乳动物,而不是鱼。","thinkProcess": ["","\n嗯,今天老师布置了一个问题,问虎鲸是不是鱼。这个问题听起来简单,但我觉得可能有些同学会有一些不同的看法。让我仔细想想。\n\n首先,我知道虎鲸是一种海洋生物,它生活在海里,应该和鱼一样在水里游动。那它们到底是不是鱼呢?我记得以前学过鱼类的定义,可能有帮助。鱼类通常有什么特征呢?\n\n我记得鱼是脊椎动物,有鳃,没有皮肤覆盖全身,身体两侧有一对鳍。比如,鲤鱼、鲨鱼这些都是鱼。那么虎鲸呢?它属于鲸鱼,鲸鱼是不是和鱼一样?\n\n然后,我想到鲸鱼其实不是鱼,而是哺乳动物。它们在哺乳动物的分类里,对吧?那为什么它们被称为鲸鱼,而没有叫鲸兽或者其他什么名字?\n\n再想想,鲸鱼的特点。它们是生活在海洋中的哺乳动物,用肺呼吸,生 baby是通过胎生的,对吗?比如,虎鲸就是其中一种鲸鱼,所以它应该属于哺乳动物,而不是鱼。\n\n那为什么有时候人们会说鲸鱼呢?可能是因为它们在水里生活,和鱼一样,但其实分类上它们有不同的特征。所以,虽然虎鲸生活在海里,但它还是哺乳动物,不是鱼。\n\n总结一下,鱼类和哺乳动物都是脊椎动物,但哺乳动物有胎生、用肺呼吸等特征,而鱼类则用鳃呼吸,卵生或卵胎生。因此,虎鲸作为鲸鱼,属于哺乳动物,所以它不是鱼。\n"]
}

至此,获取到后端返回的内容来展示就是前端攻城狮的事情啦!!!

Dify后台观测

在这里插入图片描述

可以看到耗时93s花销了498个Token!!!

在这里插入图片描述

7840HS的780M核显跑14b小模型能到11个Token/s还不错!!!

转载请注明出处:https://lizhiyong.blog.csdn.net/article/details/148607578

在这里插入图片描述

http://www.xdnf.cn/news/1006183.html

相关文章:

  • Vue 中 this.$emit(‘mount‘) 的妙用
  • 如何在 Discourse AI 中设置 Gemini API
  • 多串口卡使用
  • 软件测试BUG
  • 【小工具】-Doxygen01
  • slam--非线性优化
  • BEV和OCC学习-8:mmdet3d 3D分割demo测试
  • 如何利用单细胞转录组进行细胞图谱和疾病机制研究?
  • 爬虫实践:TOP250电影数据
  • 从数学到代码:一文详解埃拉托色尼筛法(埃式筛)
  • 阳台光伏防逆流电表革新者:安科瑞ADL200N-CT/D16-WF
  • ref 应用于对象类型的一个案例
  • CKA考试知识点分享(11)---CRD
  • JavaScript DOM 操作与事件处理全解析
  • BeanUtil.copyProperties()进行属性拷贝时如何忽略NULL值——CopyOptions配置详解
  • 高效管理Python环境:Miniforge、pyenv和Poetry深度对比与应用
  • 建筑业应用:机器人如何改变未来建筑业发展方向
  • 介绍一下 TCP方式程序的通讯,服务器机与客户机
  • 使用 DeepSeek 为 TDengine 创建专属知识库
  • 部署安装maven和mvnd
  • 50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | RandomChoicePicker(标签生成)
  • 西门子PLC读取梅安森风压传感器数据
  • 【2025】深度学习环境搭建记录
  • inet_addr()和inet_aton()函数详解
  • 【log4j2】将运行时变量注入日志、附性能对比与生产案例(动态日志实战)
  • JFLASH 提示license 配置操作 Sorry,no valid license for I-Flash found.
  • Trae重磅升级
  • Python 字典
  • 第六节 工程化与高级特性-TS配置选项解析
  • AUTOSAR图解==>AUTOSAR_TR_InteroperabilityOfAutosarTools