跟月影学前端智能体开发
月影
波波熊科技联合创始人
1804 人已学习
新⼈⾸单¥59
跟月影学前端智能体开发
15
15
1.0x
00:00/00:00
登录|注册

13|深度剖析(下):Ling框架的底层实现

你好,我是月影。给假期还在学习的你点个赞。
上一节课我们介绍了 Ling 框架的底层 Adapter 模块。这一节课我们继续讲解 Ling 框架非常核心的另外两个模块—— Bot 和 Tube。

Bot 子模块

Bot 子模块是 Ling 框架大模型工作流节点的主体,它的完整代码如下:
import EventEmitter from 'node:events';
import { Tube } from "../tube";
import nunjucks from 'nunjucks';
import { getChatCompletions } from "../adapter/openai";
import { getChatCompletions as getCozeChatCompletions } from "../adapter/coze";
import type { ChatConfig, ChatOptions } from "../types";
import type { ChatCompletionAssistantMessageParam, ChatCompletionSystemMessageParam, ChatCompletionUserMessageParam, ChatCompletionContentPart } from "openai/resources/index";
type ChatCompletionMessageParam = ChatCompletionSystemMessageParam | ChatCompletionAssistantMessageParam | ChatCompletionUserMessageParam;
export enum WorkState {
INIT = 'init',
WORKING = 'chatting',
INFERENCE_DONE = 'inference-done',
FINISHED = 'finished',
ERROR = 'error',
}
export abstract class Bot extends EventEmitter {
abstract get state(): WorkState;
}
export class ChatBot extends Bot {
private prompts: ChatCompletionSystemMessageParam[] = [];
private history: ChatCompletionMessageParam[] = [];
private customParams: Record<string, string> = {};
private chatState = WorkState.INIT;
private config: ChatConfig;
private options: ChatOptions;
constructor(private tube: Tube, config: ChatConfig, options: ChatOptions = {}) {
super();
this.config = { ...config };
this.options = { ...options };
}
isJSONFormat() {
return this.options.response_format?.type === 'json_object';
}
get root() {
return this.options.response_format?.root;
}
setJSONRoot(root: string | null) {
if(!this.options.response_format) {
this.options.response_format = { type: 'json_object', root };
} else {
this.options.response_format.root = root;
}
}
setCustomParams(params: Record<string, string>) {
this.customParams = {...params};
}
addPrompt(promptTpl: string, promptData: Record<string, any> = {}) {
const promptText = nunjucks.renderString(promptTpl, { chatConfig: this.config, chatOptions: this.options, ...this.customParams, ...promptData, });
this.prompts.push({ role: "system", content: promptText });
}
setPrompt(promptTpl: string, promptData: Record<string, string> = {}) {
this.prompts = [];
this.addPrompt(promptTpl, promptData);
}
addHistory(messages: ChatCompletionMessageParam []) {
this.history.push(...messages);
}
setHistory(messages: ChatCompletionMessageParam []) {
this.history = messages;
}
addFilter(filter: ((data: unknown) => boolean) | string | RegExp) {
this.tube.addFilter(filter);
}
clearFilters() {
this.tube.clearFilters();
}
userMessage(message: string): ChatCompletionUserMessageParam {
return { role: "user", content: message };
}
botMessage(message: string): ChatCompletionAssistantMessageParam {
return { role: "assistant", content: message };
}
async chat(message: string | ChatCompletionContentPart[]) {
try {
this.chatState = WorkState.WORKING;
const isJSONFormat = this.isJSONFormat();
const prompts = this.prompts.length > 0 ? [...this.prompts] : [];
if(this.prompts.length === 0 && isJSONFormat) {
prompts.push({
role: 'system',
content: `[Output]\nOutput with json format, starts with '{'\n[Example]\n{"answer": "My answer"}`,
});
}
const messages = [...prompts, ...this.history, { role: "user", content: message }];
if(this.config.model_name.startsWith('coze:')) {
return await getCozeChatCompletions(this.tube, messages, this.config, {...this.options, custom_variables: this.customParams},
(content) => { // on complete
this.chatState = WorkState.FINISHED;
this.emit('response', content);
}, (content) => { // on string response
this.emit('string-response', content);
}, (content) => { // on object response
this.emit('object-response', content);
}).then((content) => { // on inference done
this.chatState = WorkState.INFERENCE_DONE;
this.emit('inference-done', content);
});
}
return await getChatCompletions(this.tube, messages, this.config, this.options,
(content) => { // on complete
this.chatState = WorkState.FINISHED;
this.emit('response', content);
}, (content) => { // on string response
this.emit('string-response', content);
}, (content) => { // on object response
this.emit('object-response', content);
}).then((content) => { // on inference done
this.chatState = WorkState.INFERENCE_DONE;
this.emit('inference-done', content);
});
} catch(ex: any) {
console.error(ex);
this.chatState = WorkState.ERROR;
// 不主动发error给客户端
// this.tube.enqueue({event: 'error', data: ex.message});
this.emit('error', ex.message);
// this.tube.cancel();
}
}
finish() {
this.emit('inference-done', 'null');
this.emit('response', 'null');
this.chatState = WorkState.FINISHED;
}
get state() {
return this.chatState;
}
}
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
  • 解释
  • 总结

1. ChatBot类是Bot子模块的核心,包含关键方法和属性,如isJSONFormat、setCustomParams、addPrompt等,用于设置参数、添加提示词和记录历史聊天记录。 2. ChatBot类中的chat方法是最核心的,根据配置的model_name判断调用Open AI兼容的大模型还是coze,并处理用户消息,发送相应的事件。 3. Bot子模块通过枚举对象定义了Bot节点的工作状态,包括INIT、WORKING、INFERENCE_DONE、FINISHED和ERROR,允许Ling对象监听Bot执行过程中数据和状态的变化。 4. Ling管理模块中的构造器创建了一个Tube对象,并监听其message、finished和canceled事件,将它们转发。 5. Ling管理模块的createBot方法用于创建并托管Bot对象,自动传入Tube对象,并监听bot的error和inference-done事件。 6. Ling管理模块的close方法异步轮询托管的Bot,判断它们的状态是否是FINISHED或ERROR,只有当它们全部结束之后,才会真正将_tube关闭。 7. Ling管理模块的handleTask方法允许给Ling管理器添加外部的异步操作,影响close方法和暴露一个外部属性promise。 8. Ling管理模块的promise属性用于等待Ling的推理结束,然后执行其他的操作,例如:const result = await ling.promise; 9. Ling框架的Bot模块设计了一个抽象类,可以用来扩展其他类型的Bot,例如ImageBot,通过Ling管理起来。 10. Ling框架的下一节课将通过具体实战来进一步深入学习如何用好Ling框架。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《跟月影学前端智能体开发》
新⼈⾸单¥59
立即购买
登录 后留言

精选留言

由作者筛选后的优质留言将会公开显示,欢迎踊跃留言。
收起评论
显示
设置
留言
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部
文章页面操作
MAC
windows
作用
esc
esc
退出沉浸式阅读
shift + f
f11
进入/退出沉浸式
command + ⬆️
home
滚动到页面顶部
command + ⬇️
end
滚动到页面底部
⬅️ (仅针对订阅)
⬅️ (仅针对订阅)
上一篇
➡️ (仅针对订阅)
➡️ (仅针对订阅)
下一篇
command + j
page up
向下滚动一屏
command + k
page down
向上滚动一屏
p
p
音频播放/暂停
j
j
向下滚动一点
k
k
向上滚动一点
空格
空格
向下滚动一屏
播放器操作
MAC
windows
作用
esc
esc
退出全屏
⬅️
⬅️
快退
➡️
➡️
快进
空格
空格
视频播放/暂停(视频全屏时生效)