windows 建网站,网站推广互联网推广,北京网站设计公司youx成都柚米科技15,广东建设厅的工程造价网站前言
最近写的开源项目核心功能跑通了#xff0c;前两天突发奇想。关于项目可否介入大模型来辅助用户使用平台#xff0c;就跑去研究了最近比较活火的国内大模型–讯飞星火大模型。
大模型api获取
控制台登录
地址#xff1a;https://console.xfyun.cn/app/myapp 新建应…前言
最近写的开源项目核心功能跑通了前两天突发奇想。关于项目可否介入大模型来辅助用户使用平台就跑去研究了最近比较活火的国内大模型–讯飞星火大模型。
大模型api获取
控制台登录
地址https://console.xfyun.cn/app/myapp 新建应用后点进去
获取api地址和其key 左侧选用大模型版本右侧圈起来的地方就是咱api要调用的数据了 如果没有正常的token或key可能没有实名认证需要先实名认证下 下面有关于web的调用接口这是咱们后面要调用的api接口地址
技术栈 react hooks TypeScript semi-ui组件库可选 下载工具包 npm i crypto-js base-64 -d 实现
api和key都获取到了咱就直接开始上代码操作吧
目录 utils工具类
以下工具类getWebsocketUrl方法负责构建api的URL地址具体原因可以查阅对应的官方文档说明
import * as base64 from base-64;
import CryptoJs from crypto-js;
import { requestObj } from ../config;
export const getWebsocketUrl () {return new Promisestring((resovle, reject) {let url ws://spark-api.xf-yun.com/v1.1/chat;let host spark-api.xf-yun.com;let apiKeyName api_key;// let date new Date().toGMTString();let date new Date().toUTCString();let algorithm hmac-sha256;let headers host date request-line;let signatureOrigin host: ${host}\ndate: ${date}\nGET /v1.1/chat HTTP/1.1;let signatureSha CryptoJs.HmacSHA256(signatureOrigin, requestObj.APISecret);let signature CryptoJs.enc.Base64.stringify(signatureSha);let authorizationOrigin ${apiKeyName}${requestObj.APIKey}, algorithm${algorithm}, headers${headers}, signature${signature};let authorization base64.encode(authorizationOrigin);// 将空格编码url ${url}?authorization${authorization}date${encodeURI(date)}host${host};resovle(url);});
};config配置类
前言说的 key 在此处分别填入即可Uid无关紧要
server/AiToolws服务工具
该工具类负责接收父类组件传来的问题并对相关数据信息进行返回。
**forwardRefuseImperativeHandleprops **实现父子通信通过 **getWebsocketUrl **返回url地址构建ws通信**websocket **返回相关ai回应数据并对数据加载状态进行实时通信
import { FC, forwardRef, useImperativeHandle, useState } from react;
import { requestObj } from ../config;
import { getWebsocketUrl } from ../utils;
interface AiToolProps {isText?: boolean;respondHoodle: (result: string) void; //关联数据loadHoodle?: (isLoading: boolean) void; //加载状态errorHoodle?: (isLoading: boolean) void; //失败调用
}interface CropperRef {submitHoodle: (v: any) void; //父类调用
}const AiTool forwardRefCropperRef, AiToolProps(function AiTool({ isText, respondHoodle, loadHoodle, errorHoodle },ref
) {let result: string ;const [historyMessage, setHistoryMessage] useStateany[]([{ role: user, content: 你是谁 }, //# 用户的历史问题{ role: assistant, content: 我是AI助手 }]);useImperativeHandle(ref, () ({submitHoodle: sendMsg}));const sendMsg async (questionText: string) {result ;// 获取请求地址let myUrl await getWebsocketUrl();// 获取输入框中的内容// 每次发送问题 都是一个新的websocket请求let socket new WebSocket(myUrl);// 监听websocket的各阶段事件 并做相应处理socket.addEventListener(open, (event) {if (loadHoodle) loadHoodle(true);// 发送消息let params {header: {app_id: requestObj.APPID,uid: wzz},parameter: {chat: {domain: general,temperature: 0.5,max_tokens: 1024}},payload: {message: {// 如果想获取结合上下文的回答需要开发者每次将历史问答信息一起传给服务端如下示例// 注意text里面的所有content内容加一起的tokens需要控制在8192以内开发者如有较长对话需求需要适当裁剪历史信息text: [...historyMessage,// ....... 省略的历史对话{ role: user, content: questionText } //# 最新的一条问题如无需上下文可只传最新一条问题]}}};socket.send(JSON.stringify(params));});socket.addEventListener(message, (event) {let data JSON.parse(event.data);if (!data.payload) {socket.close();return;}result data.payload.choices.text[0].content;respondHoodle(result);if (data.header.code ! 0) {console.log(出错了, data.header.code, :, data.header.message);// 出错了手动关闭连接socket.close();}if (data.header.code 0) {// 对话已经完成if (data.payload.choices.text data.header.status 2) {setTimeout(() {// 对话完成手动关闭连接socket.close();}, 1000);}}});socket.addEventListener(close, (event) {setHistoryMessage([...historyMessage,{ role: user, content: questionText },{ role: assistant, content: result }]);if (loadHoodle) loadHoodle(false);// 对话完成后socket会关闭将聊天记录换行处理});socket.addEventListener(error, (event) {if (errorHoodle) errorHoodle(true);console.log(连接发送错误, event);});};// return result;return ;
});
export default AiTool;
Chat.tsx(具体组件)
chat组件的具体实现
messageList 记录信息数据submit 发送问题函数overRespond 介绍信息函数**moveY **返回底部
import { memo, useRef, useState } from react;
//type
import type { FC } from react;
import styles from ./index.module.scss;
import { Button, Spin } from douyinfe/semi-ui;
import AiTool from /ai/server/AiTool;
interface IProps {datas?: any[];
}
//usertrue代表用户信息反之ai
interface messageInfo {text: string;user: boolean;
}const Chat: FCIProps () {const [question, setQuestion] useStatestring();// const [result, setResult] useStatestring();let result ;const [isLoading, setIsLoading] useStateboolean(false);const [messageList, setMessageList] useStatemessageInfo[]([]);const ref useRefany(null);const messageContainerRef useRefany(null);const loadingRef useRefany(null);const submit () {setQuestion();console.log(messageList);if (!messageList.length) {setMessageList([{user: true,text: question}]);console.log(messageList);} else {setMessageList([...messageList,{user: true,text: question}]);console.log(messageList);}moveY();if (ref.current) {ref.current.submitHoodle(question);}};const respondHoodle (respond: string) {result respond;loadingRef.current.innerText result;moveY();// loadingRef.current};const overRespond (v: boolean) {if (!v) {setMessageList((prevList) [...prevList, { user: false, text: result }]);console.log(messageList);moveY();}setIsLoading(v);};const handleSendMessage (e: any) {e.preventDefault();};const handleKeyPress (e: any) {if (e.keyCode 13) {submit();}};//返回底部const moveY () {const h messageContainerRef.current.scrollHeight;messageContainerRef.current.scrollTop h 20;};return (div className{styles.chat}div className{styles.chat__main}header className{styles.chat__mainHeader}p欢迎使用青邮AI助手/pdivButton onClick{moveY} style{{ marginRight: 4 }}返回底部/ButtonButton typedanger themesolid onClick{() setMessageList([])}清除聊天记录/Button/div/header{/* 显示你发送消息的内容 */}div className{styles.message__container} ref{messageContainerRef}{messageList.map((item, index) {return item.user ? (div key{item.user.toString() index} className{styles.message__chats}p className{styles.sender__name}You/pdiv className{styles.message__sender}p{item.text}/p/div/div) : (div className{styles.message__chats}pAi/pdiv className{styles.message__recipient}p{item.text}/p/div/div);})}{isLoading ? (div className{styles.message__chats}pAi/pdiv className{styles.message__recipient}p ref{loadingRef}{result}/pSpin //div/div) : ()}/divdiv className{styles.chat__footer}form classNameform onSubmit{handleSendMessage}inputtypetextplaceholder编写消息className{styles.message}value{question}onChange{(e) setQuestion(e.target.value)}onKeyUp{handleKeyPress}/Button onClick{submit} typeprimary themesolid className{styles.sendBtn}发送/Button/form/divAiTool loadHoodle{overRespond} respondHoodle{respondHoodle} ref{ref} //div/div);
};export default memo(Chat); scss就不v了如需要可以在评论区喊我 结果
效果图 后言
关于使用server的AiTool.tsx工具其实还能产生不少其他的扩展接下来着重研究下加油加油