一、需求
公司想要在页面中加入AI智能对话功能,故查找免费gpt接口,最终决定百度千帆大模型(进入官网、官方文档中心);
二、主要功能列举
- AI智能对话;
- 记录上下文回答环境;
- 折叠/展开窗口;
- 可提前中止回答;
- 回答内容逐字展示并语音播报;
三、效果图
四、技术选型
1、前端环境
- node(14.21.3)
- VueCli 2
- element-ui(^2.15.14)
- axios
- node-sass(^4.14.1)
- sass-loader(^7.3.1)
- js-md5(^0.8.3)
2、后端环境
- JDK8
- springboot
五、声明
- 本文章以及源码纯粹自己写着玩,等于是个demo,有许多需要完善和优化的地方,仅供大家参考,有错误的地方欢迎大家批评指正~~
- 本菜其实是java,前端代码中如果看到神奇的地方,多多包涵,哈哈哈哈
四、百度千帆大模型应用创建
1、访问官网,注册账号并登录;
2、选择“应用接入”-“创建应用”
进去填一个应用名及描述即可,服务默认全勾选上;
3、保存后返回应用列表,获取api key和secret key
PS:
百度提供的大模型服务有好多种,我此处是白嫖的其中一个免费的,如下图:
其中ERNIE开头的是百度自己的,文心一言用的就是这种,其他有些是三方大模型;
具体不同服务之间有什么区别可以看官方介绍,个人觉得免费的几个主要在于轻量等级、响应速度、回答内容复杂程度、可保存的上下文大小等几个方面;
五、部分后台代码
1、官网下载java sdk或者引入百度千帆pom
官放文档地址:https://cloud.baidu.com/doc/WENXINWORKSHOP/s/7ltgucw50
java SDK地址:https://github.com/baidubce/bce-qianfan-sdk/tree/main/java
maven仓库地址:https://mvnrepository.com/artifact/com.baidubce/qianfan
POM:
<!-- https://mvnrepository.com/artifact/com.baidubce/qianfan -->
<dependency>
<groupId>com.baidubce</groupId>
<artifactId>qianfan</artifactId>
<version>0.0.4</version>
</dependency>
2、创建springboot项目,并导入sdk或引入千帆pom
此处是把sdk导入到工程中;
3、项目代码结构如下
pom.xml :
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baidu</groupId>
<artifactId>aichat</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>aichat</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.9</version>
</parent>
<dependencies>
<!-- SpringBoot的依赖配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.13.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.3.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.1.RELEASE</version>
<configuration>
<fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<warName>${project.artifactId}</warName>
</configuration>
</plugin>
</plugins>
<finalName>${project.artifactId}</finalName>
</build>
</project>
AiChatController.java:
package com.baidubce.controller;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.baidubce.qianfan.Qianfan;
import com.baidubce.qianfan.core.builder.ChatBuilder;
import com.baidubce.qianfan.model.chat.ChatResponse;
import com.baidubce.qianfan.model.chat.Message;
import com.baidubce.utils.JsonUtils;
import com.baidubce.utils.SecUtils;
@RestController
public class AiChatController {
private static final String accessKey = "你创建的应用的API Key";
private static final String secretKey = "你创建的应用的Secret Key";
private static Qianfan qianfan = new Qianfan("OAuth", accessKey, secretKey);
/**
* 参数:
* messages: 对话记录,role:user是用户,assistant是AI,如:[{"role":"user","content":"1"},{"role":"assistant","content":"“1”是一个数字。"},{"role":"user","content":"你是"},{"role":"assistant","content":""}]
* timestamp:请求毫秒值,1717742825695
* signature: 签名,4bc9c3b8dbe4de5bc924b6fa0506c606
* @author x轩
* @version 2024年6月7日 下午2:46:32
*/
@PostMapping("/sendMsg")
public String sendMsg(@RequestBody Map<String, Object> params) {
// 验签,我自己加的,防止恶意调用,作用不大,提高门槛而已
if(!checkSign(params)) {
return "签名不正确!";
}
String result = null;
try {
result = chat(String.valueOf(params.get("messages")));
} catch (Exception e) {
e.printStackTrace();
return "接口繁忙,请稍后再试!";
}
return result;
}
/**
* 参数:
* messages: 业务参数
* timestamp:请求毫秒值
* signature: 签名
*
* 加签规则:
* 要求1:timestamp和当前系统时间不能超过5秒钟
* 要求2:MYCHAT|timestamp|messages拼接后MD53次加密
*
* @author x轩
* @version 2024年6月6日 下午4:13:03
*/
private boolean checkSign(Map<String, Object> params) {
String timestamp = String.valueOf(params.get("timestamp"));
String messages = String.valueOf(params.get("messages"));
String signature = String.valueOf(params.get("signature"));
if(StringUtils.isAnyBlank(timestamp, messages, signature)) {
return false;
}
// 1.判断时间
if((System.currentTimeMillis()- Long.valueOf(timestamp))>5000) {
// 过期
return false;
}
// 2.验签
String p = "MYCHAT|"+timestamp+"|"+messages;
String md5of3 = SecUtils.encoderByMd5With32Bit(SecUtils.encoderByMd5With32Bit(