原文地址:前端JS接入阿里云通义千问/百炼大模型
前端JS接入阿里云通义千问/百炼大模型
本文仅以阿里云百炼大模型为例,阿里其他大模型如通义千问接入方式类似。
百炼大模型文档地址:help.aliyun.com/document_de…
作者的TS写得比较菜(初学者),不足之处还望多多指正
安装依赖
mitt 不是必需的,可以自行删除相关代码
npm i @microsoft/fetch-event-source mitt
tyqw.ts
/**
* 阿里云通义千问接入 bodyData目前对接的百炼平台,对接通义千问需要修改下bodyData
* @auth chinjiaqing
*/
import {EventSourceMessage, fetchEventSource} from "@microsoft/fetch-event-source";
import mitt, {Emitter, EventType} from "mitt";
// Tyqw事件类型枚举
export enum TyqwEvent {
MESSAGE = 'message',
ERROR = 'error'
}
// 通用事件处理类型
type EmitterEvents = {
[key in EventType]?: (data: any) => void;
}
// 消息类型
interface MessageMap {
[TyqwEvent.MESSAGE]: Message;
[TyqwEvent.ERROR]: Error;
}
// Tyqw事件监听类型
type TyqwEvents = {
[key in TyqwEvent]: key extends keyof MessageMap ? MessageMap[key] : never;
} & EmitterEvents;
interface Message {
output?: {
session_id: string;
text: string;
thoughts?: Array<{
action?: string;
arguments?: string;
[key: string]: any;
}>;
finish_reason: 'null' | 'stop';
};
[key: string]: any;
}
// 请求体数据接口
interface FetchBodyData {
input: {
prompt: string;
session_id: string;
};
parameters?: {
has_thoughts?: boolean;
};
}
// 默认请求体数据
const defaultBodyData: FetchBodyData = {
input: {
prompt: '',
session_id: ''
},
parameters: {
has_thoughts: false
}
};
class Tyqw {
// 应用ID
private readonly appId: string = 'your appid';
// 会话ID键值
private readonly sessionIdKey: string = 'tyqw_sessionId';
// 请求体数据
private bodyData: FetchBodyData = {...defaultBodyData};
// 事件发射器
private emitter: Emitter<TyqwEvents> = mitt<TyqwEvents>();
// 请求的url
private get api(): string {
return `/tyqw/api/v1/apps/${this.appId}/completion`;
}
// 获取会话的sessionId
get sessionId(): string | null {
return localStorage.getItem(this.sessionIdKey);
}
/**
* 获取token, 后续开发应该对接真正的获取token流程
* @private
* @returns {string} token
*/
private getToken(): string {
return 'your token';
}
/**
* 转换请求体数据格式
* @private
* @param {string} text 要发送的文本
* @returns {string} 转换后的请求体数据
*/
private transferBodyData(text: string): string {
this.bodyData.input.prompt = text;
this.bodyData.input.session_id = this.sessionId;
return JSON.stringify(this.bodyData);
}
/**
* 发送消息
* @param {string} text 要发送的文本 不能为空
* @returns Promise
* @example
* tyqw.send('你叫什么名字')
*/
public async send(text: string): Promise<void> {
if (!text || !text.trim()) return;
const {emitter} = this;
const bodyData: string = this.transferBodyData(text);
const controller: AbortController = new AbortController();
return fetchEventSource(this.api, {
method: "POST",
headers: {
"Authorization": `Bearer ${this.getToken()}`,
"Content-Type": "application/json",
},
body: bodyData,
signal: controller.signal,
onmessage: (e: EventSourceMessage) => {
try {
const data: Message = JSON.parse(e.data);
if (data?.output?.session_id) {
this.setSessionId(data.output.session_id);
}
emitter.emit(TyqwEvent.MESSAGE, data);
console.log("on message: ", data);
} catch (err) {
console.error('通义千问 message 解析出错', err);
emitter.emit(TyqwEvent.ERROR, err as Error);
}
},
onclose: () => {
controller.abort();
},
onerror: (err: Error) => {
console.error('通义千问 请求出错', err);
controller.abort();
emitter.emit(TyqwEvent.ERROR, err);
},
});
}
/**
* 设置sessionId
* @param {string} value sessionId
*/
public setSessionId(value: string): void {
localStorage.setItem(this.sessionIdKey, value);
}
/**
* 清除sessionId 用于开启新的对话,清除上下文关系
*/
public clearSessionId(): void {
localStorage.removeItem(this.sessionIdKey);
}
/**
* 事件监听
* @param {T extends TyqwEvent} event 监听的事件类型
* @param {(data: TyqwEvents[T]) => void} callback 回调函数
*/
public on<T extends TyqwEvent>(event: T, callback: (data: TyqwEvents[T]) => void): void {
this.emitter.on(event, callback);
}
/**
* 取消事件监听
* @param {T extends TyqwEvent} event 监听的事件类型
* @param {(data: TyqwEvents[T]) => void} [callback] 回调函数
*/
public off<T extends TyqwEvent>(event: T, callback?: (data: TyqwEvents[T]) => void): void {
this.emitter.off(event, callback);
}
}
export default Tyqw;
使用示例
import Tyqw, { TyqwEvent } from './tyqw.js';
const tyqw = new Tyqw();
tyqw.on(TyqwEvent.MESSAGE, (data) => {
console.log(`on message: `,data)
})
tyqw.on(TyqwEvent.ERROR, (err) => {
console.error('on error: ',err)
})
tyqw.send('你好')