ad5d2fe204
refactor(script): improve UI feedback with styled thinking and response elements docs: add project planning and feature list documents style(script): add visual styling for better user feedback chore: update PRD and README to reflect current project status
109 lines
3.6 KiB
JavaScript
109 lines
3.6 KiB
JavaScript
// main.js - Bella's Brain (v2)
|
|
// This file will contain the core AI logic for Bella, powered by Transformers.js.
|
|
|
|
import { pipeline, env, AutoTokenizer, AutoModelForSpeechSeq2Seq } from '../vendor/transformers.js';
|
|
|
|
|
|
|
|
|
|
// To allow local models, we need to disable the remote model check.
|
|
env.allowLocalModels = true;
|
|
env.useBrowserCache = false;
|
|
env.allowRemoteModels = false;
|
|
|
|
|
|
env.backends.onnx.logLevel = 'verbose';
|
|
// Define the location of the models
|
|
env.localModelPath = './models/';
|
|
|
|
|
|
class BellaAI {
|
|
static instance = null;
|
|
|
|
static async getInstance() {
|
|
if (this.instance === null) {
|
|
this.instance = new BellaAI();
|
|
await this.instance.init();
|
|
}
|
|
return this.instance;
|
|
}
|
|
|
|
async init() {
|
|
try {
|
|
console.log('Initializing Bella\'s core AI...');
|
|
|
|
const modelPath = 'Xenova/whisper-asr';
|
|
|
|
console.log('Loading tokenizer for ASR...');
|
|
const tokenizer = await AutoTokenizer.from_pretrained(modelPath);
|
|
console.log('Tokenizer loaded successfully.');
|
|
|
|
console.log('Loading ASR model...');
|
|
const model = await AutoModelForSpeechSeq2Seq.from_pretrained(modelPath);
|
|
console.log('ASR model loaded successfully.');
|
|
|
|
console.log('Creating ASR pipeline...');
|
|
this.asr = await pipeline('automatic-speech-recognition', model, { tokenizer });
|
|
console.log('ASR pipeline created successfully.');
|
|
|
|
} catch (error) {
|
|
console.error('Error during Bella AI initialization:', error);
|
|
throw error; // Re-throw the error to be caught by the caller
|
|
}
|
|
|
|
console.log('Loading LLM model...');
|
|
this.llm = await pipeline('text2text-generation', 'Xenova/LaMini-Flan-T5-77M');
|
|
console.log('LLM model loaded.');
|
|
|
|
// console.log('Loading TTS model...');
|
|
// this.tts = await pipeline('text-to-speech', 'Xenova/speecht5_tts', { quantized: false, progress_callback: onProgress });
|
|
// console.log('TTS model loaded.');
|
|
|
|
console.log('Bella\'s core AI initialized.');
|
|
}
|
|
|
|
async think(prompt) {
|
|
if (!this.llm) {
|
|
return "我还在学习如何思考,请稍等片刻...";
|
|
}
|
|
|
|
try {
|
|
// 为贝拉添加一些个性化的提示词
|
|
const bellaPrompt = `作为一个温暖、聪明的AI伙伴贝拉,请用简洁、亲切的中文回应:${prompt}`;
|
|
|
|
const result = await this.llm(bellaPrompt, {
|
|
max_new_tokens: 50,
|
|
temperature: 0.8,
|
|
top_k: 40,
|
|
do_sample: true,
|
|
});
|
|
|
|
// 清理生成的文本,移除重复的提示词部分
|
|
let response = result[0].generated_text;
|
|
if (response.includes(bellaPrompt)) {
|
|
response = response.replace(bellaPrompt, '').trim();
|
|
}
|
|
|
|
return response || "我需要再想想...";
|
|
} catch (error) {
|
|
console.error('思考过程中出现错误:', error);
|
|
return "抱歉,我现在有点困惑,让我重新整理一下思路...";
|
|
}
|
|
}
|
|
|
|
async listen(audioData) {
|
|
const result = await this.asr(audioData);
|
|
return result.text;
|
|
}
|
|
|
|
async speak(text) {
|
|
// We need speaker embeddings for SpeechT5
|
|
const speaker_embeddings = 'models/Xenova/speecht5_tts/speaker_embeddings.bin';
|
|
const result = await this.tts(text, {
|
|
speaker_embeddings,
|
|
});
|
|
return result.audio;
|
|
}
|
|
}
|
|
|
|
export default BellaAI; |