JavaScript AI生态
目录
JavaScript已经成为AI应用开发的重要语言,拥有丰富的AI库、框架和工具链。本文将深入探讨JavaScript AI生态系统,帮助开发者选择合适的工具和技术栈。
JavaScript AI生态概览
生态系统架构
核心AI框架
1. TensorFlow.js
特点
- Google开发的机器学习框架
- 支持浏览器和Node.js
- 预训练模型丰富
- 支持自定义模型训练
核心功能实现
// TensorFlow.js核心功能封装
class TensorFlowManager {
constructor() {
this.models = new Map();
this.backend = 'webgl'; // 默认使用WebGL加速
this.initialized = false;
}
async initialize() {
if (this.initialized) return;
// 设置后端
await tf.setBackend(this.backend);
await tf.ready();
// 检查设备能力
const deviceInfo = this.getDeviceInfo();
console.log('TensorFlow.js initialized:', deviceInfo);
this.initialized = true;
}
getDeviceInfo() {
return {
backend: tf.getBackend(),
memory: tf.memory(),
environment: tf.env(),
flags: tf.env().flags
};
}
// 加载预训练模型
async loadPretrainedModel(modelName, modelUrl) {
if (this.models.has(modelName)) {
return this.models.get(modelName);
}
try {
const model = await tf.loadLayersModel(modelUrl);
this.models.set(modelName, {
model,
metadata: {
loadTime: Date.now(),
inputShape: model.inputs[0].shape,
outputShape: model.outputs[0].shape
}
});
return model;
} catch (error) {
console.error(`Failed to load model ${modelName}:`, error);
throw error;
}
}
// 图像分类示例
async classifyImage(modelName, imageElement) {
const modelInfo = this.models.get(modelName);
if (!modelInfo) {
throw new Error(`Model ${modelName} not loaded`);
}
const { model } = modelInfo;
// 预处理图像
const tensor = tf.browser.fromPixels(imageElement)
.resizeNearestNeighbor([224, 224])
.toFloat()
.div(255.0)
.expandDims();
// 执行推理
const predictions = await model.predict(tensor).data();
// 清理内存
tensor.dispose();
return this.postprocessPredictions(predictions);
}
// 自定义模型训练
async trainCustomModel(trainingData, modelConfig) {
const { inputs, outputs, architecture } = modelConfig;
// 构建模型架构
const model = tf.sequential();
architecture.forEach(layer => {
switch (layer.type) {
case 'dense':
model.add(tf.layers.dense({
units: layer.units,
activation: layer.activation,
inputShape: layer.inputShape
}));
break;
case 'conv2d':
model.add(tf.layers.conv2d({
filters: layer.filters,
kernelSize: layer.kernelSize,
activation: layer.activation
}));
break;
case 'maxPooling2d':
model.add(tf.layers.maxPooling2d({
poolSize: layer.poolSize
}));
break;
case 'flatten':
model.add(tf.layers.flatten());
break;
case 'dropout':
model.add(tf.layers.dropout({
rate: layer.rate
}));
break;
}
});
// 编译模型
model.compile({
optimizer: modelConfig.optimizer || 'adam',
loss: modelConfig.loss || 'categoricalCrossentropy',
metrics: modelConfig.metrics || ['accuracy']
});
// 准备训练数据
const xs = tf.tensor(inputs);
const ys = tf.tensor(outputs);
// 训练模型
const history = await model.fit(xs, ys, {
epochs: modelConfig.epochs || 100,
batchSize: modelConfig.batchSize || 32,
validationSplit: modelConfig.validationSplit || 0.2,
callbacks: {
onEpochEnd: (epoch, logs) => {
console.log(`Epoch ${epoch}: loss = ${logs.loss}, accuracy = ${logs.acc}`);
}
}
});
// 清理内存
xs.dispose();
ys.dispose();
return { model, history };
}
// 模型性能监控
monitorPerformance(modelName, callback) {
const modelInfo = this.models.get(modelName);
if (!modelInfo) return;
const monitor = {
startTime: null,
endTime: null,
memoryBefore: null,
memoryAfter: null
};
return {
start: () => {
monitor.startTime = performance.now();
monitor.memoryBefore = tf.memory();
},
end: () => {
monitor.endTime = performance.now();
monitor.memoryAfter = tf.memory();
const metrics = {
inferenceTime: monitor.endTime - monitor.startTime,
memoryUsage: {
before: monitor.memoryBefore,
after: monitor.memoryAfter,
delta: {
numTensors: monitor.memoryAfter.numTensors - monitor.memoryBefore.numTensors,
numBytes: monitor.memoryAfter.numBytes - monitor.memoryBefore.numBytes
}
}
};
callback(metrics);
}
};
}
}
2. Transformers.js
特点
- Hugging Face的JavaScript实现
- 支持多种预训练模型
- 自然语言处理专用
- 零配置使用
核心功能实现
// Transformers.js功能封装
class TransformersManager {
constructor() {
this.pipelines = new Map();
this.models = new Map();
this.tokenizers = new Map();
}
// 创建处理管道
async createPipeline(task, model = null, options = {}) {
const pipelineKey = `${task}-${model || 'default'}`;
if (this.pipelines.has(pipelineKey)) {
return this.pipelines.get(pipelineKey);
}
try {
const { pipeline } = await import('@xenova/transformers');
const pipe = await pipeline(task, model, {
...options,
progress_callback: (progress) => {
console.log(`Loading ${task} model: ${Math.round(progress.progress * 100)}%`);
}
});
this.pipelines.set(pipelineKey, pipe);
return pipe;
} catch (error) {
console.error(`Failed to create pipeline for ${task}:`, error);
throw error;
}
}
// 文本分类
async classifyText(text, model = 'Xenova/distilbert-base-uncased-finetuned-sst-2-english') {
const classifier = await this.createPipeline('sentiment-analysis', model);
return await classifier(text);
}
// 文本生成
async generateText(prompt, options = {}) {
const generator = await this.createPipeline(
'text-generation',
options.model || 'Xenova/gpt2'
);
return await generator(prompt, {
max_length: options.maxLength || 100,
num_return_sequences: options.numSequences || 1,
temperature: options.temperature || 0.7,
do_sample: options.doSample !== false,
...options
});
}
// 问答系统
async answerQuestion(question, context, model = 'Xenova/distilbert-base-cased-distilled-squad') {
const qa = await this.createPipeline('question-answering', model);
return await qa({
question,
context
});
}
// 文本摘要
async summarizeText(text, options = {}) {
const summarizer = await this.createPipeline(
'summarization',
options.model || 'Xenova/distilbart-cnn-12-6'
);
return await summarizer(text, {
max_length: options.maxLength || 130,
min_length: options.minLength || 30,
do_sample: options.doSample || false,
...options
});
}
// 翻译
async translateText(text, sourceLanguage, targetLanguage) {
const modelName = `Helsinki-NLP/opus-mt-${sourceLanguage}-${targetLanguage}`;
const translator = await this.createPipeline('translation', modelName);
return await translator(text);
}
// 特征提取
async extractFeatures(text, model = 'Xenova/all-MiniLM-L6-v2') {
const extractor = await this.createPipeline('feature-extraction', model);
return await extractor(text, { pooling: 'mean', normalize: true });
}
// 零样本分类
async zeroShotClassify(text, candidateLabels, model = 'Xenova/distilbert-base-uncased-mnli') {
const classifier = await this.createPipeline('zero-shot-classification', model);
return await classifier(text, candidateLabels);
}
// 批量处理
async batchProcess(texts, task, options = {}) {
const pipeline = await this.createPipeline(task, options.model);
const batchSize = options.batchSize || 10;
const results = [];
for (let i = 0; i < texts.length; i += batchSize) {
const batch = texts.slice(i, i + batchSize);
const batchResults = await Promise.all(
batch.map(text => pipeline(text, options))
);
results.push(...batchResults);
// 进度回调
if (options.onProgress) {
options.onProgress({
processed: Math.min(i + batchSize, texts.length),
total: texts.length,
progress: Math.min(i + batchSize, texts.length) / texts.length
});
}
}
return results;
}
}
3. Brain.js
特点
- 轻量级神经网络库
- 易于使用和理解
- 支持多种网络类型
- 适合快速原型开发
核心功能实现
// Brain.js功能封装
class BrainManager {
constructor() {
this.networks = new Map();
this.trainingData = new Map();
}
// 创建神经网络
createNetwork(name, type = 'feedforward', options = {}) {
let network;
switch (type) {
case 'feedforward':
network = new brain.NeuralNetwork({
hiddenLayers: options.hiddenLayers || [3],
activation: options.activation || 'sigmoid',
learningRate: options.learningRate || 0.3,
...options
});
break;
case 'lstm':
network = new brain.recurrent.LSTM({
hiddenLayers: options.hiddenLayers || [20],
learningRate: options.learningRate || 0.01,
...options
});
break;
case 'gru':
network = new brain.recurrent.GRU({
hiddenLayers: options.hiddenLayers || [20],
learningRate: options.learningRate || 0.01,
...options
});
break;
case 'rnn':
network = new brain.recurrent.RNN({
hiddenLayers: options.hiddenLayers || [20],
learningRate: options.learningRate || 0.01,
...options
});
break;
default:
throw new Error(`Unsupported network type: ${type}`);
}
this.networks.set(name, {
network,
type,
options,
trained: false,
createdAt: Date.now()
});
return network;
}
// 训练网络
async trainNetwork(name, trainingData, options = {}) {
const networkInfo = this.networks.get(name);
if (!networkInfo) {
throw new Error(`Network ${name} not found`);
}
const { network } = networkInfo;
// 保存训练数据
this.trainingData.set(name, trainingData);
const trainingOptions = {
iterations: options.iterations || 20000,
errorThresh: options.errorThresh || 0.005,
log: options.log || false,
logPeriod: options.logPeriod || 100,
learningRate: options.learningRate || 0.3,
momentum: options.momentum || 0.1,
callback: options.callback,
callbackPeriod: options.callbackPeriod || 10,
timeout: options.timeout || Infinity,
...options
};
const startTime = Date.now();
return new Promise((resolve, reject) => {
try {
const stats = network.train(trainingData, {
...trainingOptions,
callback: (stats) => {
if (options.onProgress) {
options.onProgress({
iterations: stats.iterations,
error: stats.error,
progress: stats.iterations / trainingOptions.iterations
});
}
if (options.callback) {
options.callback(stats);
}
}
});
networkInfo.trained = true;
networkInfo.trainingStats = {
...stats,
trainingTime: Date.now() - startTime
};
resolve(stats);
} catch (error) {
reject(error);
}
});
}
// 预测
predict(name, input) {
const networkInfo = this.networks.get(name);
if (!networkInfo) {
throw new Error(`Network ${name} not found`);
}
if (!networkInfo.trained) {
console.warn(`Network ${name} has not been trained yet`);
}
return networkInfo.network.run(input);
}
// 文本生成(LSTM示例)
async trainTextGenerator(name, text, options = {}) {
const network = this.createNetwork(name, 'lstm', {
hiddenLayers: options.hiddenLayers || [20],
learningRate: options.learningRate || 0.01
});
// 准备训练数据
const trainingData = this.prepareTextData(text, options.sequenceLength || 10);
await this.trainNetwork(name, trainingData, {
iterations: options.iterations || 2000,
errorThresh: options.errorThresh || 0.011,
log: true,
logPeriod: 100,
onProgress: options.onProgress
});
return network;
}
generateText(name, seed, length = 100) {
const networkInfo = this.networks.get(name);
if (!networkInfo || networkInfo.type !== 'lstm') {
throw new Error(`LSTM network ${name} not found`);
}
return networkInfo.network.run(seed, length);
}
// 时间序列预测
async trainTimeSeriesPredictor(name, data, options = {}) {
const network = this.createNetwork(name, 'lstm', {
hiddenLayers: options.hiddenLayers || [10, 10],
learningRate: options.learningRate || 0.005
});
// 准备时间序列数据
const trainingData = this.prepareTimeSeriesData(
data,
options.windowSize || 10,
options.predictionSteps || 1
);
await this.trainNetwork(name, trainingData, {
iterations: options.iterations || 1000,
errorThresh: options.errorThresh || 0.01,
onProgress: options.onProgress
});
return network;
}
predictTimeSeries(name, inputSequence) {
return this.predict(name, inputSequence);
}
// 数据预处理辅助方法
prepareTextData(text, sequenceLength) {
const data = [];
for (let i = 0; i < text.length - sequenceLength; i++) {
data.push({
input: text.substring(i, i + sequenceLength),
output: text.substring(i + 1, i + sequenceLength + 1)
});
}
return data;
}
prepareTimeSeriesData(data, windowSize, predictionSteps) {
const trainingData = [];
for (let i = 0; i < data.length - windowSize - predictionSteps + 1; i++) {
const input = data.slice(i, i + windowSize);
const output = data.slice(i + windowSize, i + windowSize + predictionSteps);
trainingData.push({ input, output });
}
return trainingData;
}
// 网络序列化
exportNetwork(name) {
const networkInfo = this.networks.get(name);
if (!networkInfo) {
throw new Error(`Network ${name} not found`);
}
return {
json: networkInfo.network.toJSON(),
function: networkInfo.network.toFunction().toString(),
metadata: {
type: networkInfo.type,
options: networkInfo.options,
trained: networkInfo.trained,
trainingStats: networkInfo.trainingStats
}
};
}
// 网络导入
importNetwork(name, exportedData) {
const network = new brain.NeuralNetwork();
network.fromJSON(exportedData.json);
this.networks.set(name, {
network,
type: exportedData.metadata.type,
options: exportedData.metadata.options,
trained: exportedData.metadata.trained,
trainingStats: exportedData.metadata.trainingStats,
importedAt: Date.now()
});
return network;
}
}
AI服务集成SDK
0. Vercel AI SDK(2026 首选)
接 LLM 别再从零封装 fetch/流式/重试了——Vercel AI SDK(ai 包)是 2026 年 JS 生态接大模型的事实标准:统一封装流式、工具调用、结构化输出、多 provider,换模型只改一行。
npm i ai @ai-sdk/openai @ai-sdk/anthropic @ai-sdk/google zod
# 前端额外:npm i @ai-sdk/react streamdown
streamText:服务端流式
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
const result = streamText({
model: openai('gpt-4o-mini'),
prompt: '用一句话解释 RAG',
});
// 服务端:return result.toUIMessageStreamResponse();
// 脚本里:for await (const chunk of result.textStream) process.stdout.write(chunk);
useChat:前端聊天(@ai-sdk/react)
'use client';
import { useChat } from '@ai-sdk/react';
const { messages, sendMessage, status } = useChat();
// messages[i].parts 是结构化数组:text / tool 调用 / source / reasoning
generateObject:Zod 约束的结构化输出
import { generateObject } from 'ai';
import { z } from 'zod';
const { object } = await generateObject({
model: openai('gpt-4o-mini'),
schema: z.object({ sentiment: z.enum(['正', '负']), score: z.number() }),
prompt: '分析「这产品太好用了」',
});
tool():工具调用(多步)
import { tool, streamText, stepCountIs } from 'ai';
import { z } from 'zod';
streamText({
model: openai('gpt-4o'),
stopWhen: stepCountIs(5),
tools: {
getPrice: tool({
description: '查询商品价格',
inputSchema: z.object({ sku: z.string() }),
execute: async ({ sku }) => ({ sku, price: 99 }),
}),
},
messages,
});
配套:流式 Markdown 用 streamdown(自动补全未闭合语法,专为 AI 流式输出设计);Generative UI 让工具结果直接渲染成组件(
message.parts里匹配tool-*part)。换 provider 只需把openai('...')换成anthropic('claude-sonnet-4')或google('gemini-2.5-flash'),业务代码不变。
1. OpenAI SDK
核心功能封装
// OpenAI SDK增强封装
class EnhancedOpenAI {
constructor(apiKey, options = {}) {
this.client = new OpenAI({
apiKey,
...options
});
this.rateLimiter = new RateLimiter({
requestsPerMinute: options.requestsPerMinute || 60,
tokensPerMinute: options.tokensPerMinute || 90000
});
this.cache = new ResponseCache({
ttl: options.cacheTTL || 3600000, // 1小时
maxSize: options.cacheMaxSize || 1000
});
this.retryConfig = {
maxRetries: options.maxRetries || 3,
backoffFactor: options.backoffFactor || 2,
initialDelay: options.initialDelay || 1000
};
}
// 智能聊天完成
async chatCompletion(messages, options = {}) {
const cacheKey = this.generateCacheKey('chat', { messages, ...options });
// 检查缓存
if (options.useCache !== false) {
const cached = await this.cache.get(cacheKey);
if (cached) {
return { ...cached, fromCache: true };
}
}
// 速率限制检查
await this.rateLimiter.checkLimit();
const requestOptions = {
model: options.model || 'gpt-4o-mini', // 2026 默认小模型
messages,
temperature: options.temperature ?? 0.7,
max_tokens: options.maxTokens,
top_p: options.topP,
frequency_penalty: options.frequencyPenalty,
presence_penalty: options.presencePenalty,
stop: options.stop,
stream: options.stream || false,
...options
};
try {
const response = await this.executeWithRetry(async () => {
return await this.client.chat.completions.create(requestOptions);
});
// 缓存响应
if (options.useCache !== false && !options.stream) {
await this.cache.set(cacheKey, response);
}
return response;
} catch (error) {
throw this.handleError(error);
}
}
// 流式聊天
async streamChatCompletion(messages, options = {}, onChunk) {
const stream = await this.chatCompletion(messages, {
...options,
stream: true
});
let fullContent = '';
for await (const chunk of stream) {
const delta = chunk.choices[0]?.delta;
if (delta?.content) {
fullContent += delta.content;
onChunk({
content: delta.content,
fullContent,
chunk,
finished: false
});
}
if (chunk.choices[0]?.finish_reason) {
onChunk({
content: '',
fullContent,
chunk,
finished: true,
finishReason: chunk.choices[0].finish_reason
});
}
}
return fullContent;
}
// 文本嵌入
async createEmbedding(input, options = {}) {
const cacheKey = this.generateCacheKey('embedding', { input, ...options });
if (options.useCache !== false) {
const cached = await this.cache.get(cacheKey);
if (cached) return cached;
}
await this.rateLimiter.checkLimit();
try {
const response = await this.executeWithRetry(async () => {
return await this.client.embeddings.create({
model: options.model || 'text-embedding-3-small', // 2026 推荐,可降维
input,
...options
});
});
if (options.useCache !== false) {
await this.cache.set(cacheKey, response);
}
return response;
} catch (error) {
throw this.handleError(error);
}
}
// 图像生成
async generateImage(prompt, options = {}) {
await this.rateLimiter.checkLimit();
try {
return await this.executeWithRetry(async () => {
return await this.client.images.generate({
prompt,
model: options.model || 'dall-e-3',
n: options.n || 1,
size: options.size || '1024x1024',
quality: options.quality || 'standard',
style: options.style,
response_format: options.responseFormat || 'url',
...options
});
});
} catch (error) {
throw this.handleError(error);
}
}
// 语音转文字
async transcribeAudio(audioFile, options = {}) {
await this.rateLimiter.checkLimit();
try {
return await this.executeWithRetry(async () => {
return await this.client.audio.transcriptions.create({
file: audioFile,
model: options.model || 'whisper-1',
language: options.language,
prompt: options.prompt,
response_format: options.responseFormat || 'json',
temperature: options.temperature,
...options
});
});
} catch (error) {
throw this.handleError(error);
}
}
// 文字转语音
async generateSpeech(text, options = {}) {
await this.rateLimiter.checkLimit();
try {
return await this.executeWithRetry(async () => {
return await this.client.audio.speech.create({
model: options.model || 'tts-1',
input: text,
voice: options.voice || 'alloy',
response_format: options.responseFormat || 'mp3',
speed: options.speed || 1.0,
...options
});
});
} catch (error) {
throw this.handleError(error);
}
}
// 重试机制
async executeWithRetry(operation) {
let lastError;
for (let attempt = 0; attempt <= this.retryConfig.maxRetries; attempt++) {
try {
return await operation();
} catch (error) {
lastError = error;
if (attempt === this.retryConfig.maxRetries) {
break;
}
if (!this.isRetryableError(error)) {
break;
}
const delay = this.retryConfig.initialDelay *
Math.pow(this.retryConfig.backoffFactor, attempt);
await this.sleep(delay);
}
}
throw lastError;
}
isRetryableError(error) {
const retryableStatusCodes = [429, 500, 502, 503, 504];
return retryableStatusCodes.includes(error.status) ||
error.code === 'ECONNRESET' ||
error.code === 'ETIMEDOUT';
}
handleError(error) {
const enhancedError = new Error(error.message);
enhancedError.originalError = error;
enhancedError.status = error.status;
enhancedError.code = error.code;
enhancedError.type = error.type;
// 添加用户友好的错误信息
if (error.status === 429) {
enhancedError.userMessage = '请求过于频繁,请稍后再试';
} else if (error.status === 401) {
enhancedError.userMessage = 'API密钥无效或已过期';
} else if (error.status >= 500) {
enhancedError.userMessage = '服务暂时不可用,请稍后再试';
}
return enhancedError;
}
generateCacheKey(operation, params) {
return `${operation}:${JSON.stringify(params)}`;
}
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
2. LangChain.js
⚠️ 2026 重要变更:废弃 API 已迁移。 LangChain.js 0.1 时代的
RetrievalQAChain、ConversationChain、initializeAgentExecutorWithOptions这些「预制 Chain/Agent」已被官方弃用。新写法是:
- 包结构:核心拆成
@langchain/core(基础抽象 + LCEL 表达式语言)、@langchain/openai等集成包;不再从langchain/chains这种大杂烩导入。- RAG 链 → 用 LCEL(
RunnableSequence/pipe)手动组合prompt | model | parser,而不是RetrievalQAChain.fromLLM。- Agent → 用 LangGraph.js(
@langchain/langgraph的createReactAgent)构建有状态、可循环、可中断的 Agent,取代initializeAgentExecutorWithOptions。LangGraph 也是实现上文 Agentic RAG 的推荐框架。下面先给出现代写法,再保留旧封装作为「演进对照」(旧 API 已不推荐,仅供理解历史)。
现代写法(LCEL + LangGraph.js)
// RAG:用 LCEL 组合,而非 RetrievalQAChain
import { ChatOpenAI, OpenAIEmbeddings } from '@langchain/openai';
import { ChatPromptTemplate } from '@langchain/core/prompts';
import { StringOutputParser } from '@langchain/core/output_parsers';
import { RunnableSequence, RunnablePassthrough } from '@langchain/core/runnables';
const model = new ChatOpenAI({ model: 'gpt-4o-mini' }); // 2026 默认
const embeddings = new OpenAIEmbeddings({ model: 'text-embedding-3-small' });
const retriever = vectorStore.asRetriever({ k: 4 });
const prompt = ChatPromptTemplate.fromTemplate(
`仅根据下面的上下文回答,查不到就说不知道。\n上下文:{context}\n问题:{question}`
);
const formatDocs = (docs) => docs.map(d => d.pageContent).join('\n\n');
// LCEL:用管道把「检索 → 填模板 → 调模型 → 解析」串起来
const ragChain = RunnableSequence.from([
{ context: async (input) => formatDocs(await retriever.invoke(input.question)),
question: new RunnablePassthrough() },
prompt,
model,
new StringOutputParser(),
]);
const answer = await ragChain.invoke({ question: '什么是 RAG?' });
// Agent:用 LangGraph.js 的 createReactAgent,取代 initializeAgentExecutorWithOptions
import { createReactAgent } from '@langchain/langgraph/prebuilt';
import { ChatOpenAI } from '@langchain/openai';
import { tool } from '@langchain/core/tools';
import { z } from 'zod';
const search = tool(async ({ query }) => `「${query}」的检索结果...`, {
name: 'search',
description: '搜索知识库',
schema: z.object({ query: z.string() }),
});
const agent = createReactAgent({
llm: new ChatOpenAI({ model: 'gpt-4o' }),
tools: [search],
});
const res = await agent.invoke({ messages: [{ role: 'user', content: '帮我查下 X' }] });
演进对照:旧版封装(已弃用,仅供理解)
// LangChain.js功能封装(注意:以下 RetrievalQAChain / initializeAgentExecutorWithOptions 等已被官方弃用)
class LangChainManager {
constructor() {
this.chains = new Map();
this.vectorStores = new Map();
this.retrievers = new Map();
this.agents = new Map();
}
// 创建对话链
async createConversationChain(name, llm, options = {}) {
const { ConversationChain } = await import('langchain/chains');
const { BufferMemory } = await import('langchain/memory');
const memory = new BufferMemory({
memoryKey: 'history',
inputKey: 'input',
outputKey: 'response',
...options.memory
});
const chain = new ConversationChain({
llm,
memory,
verbose: options.verbose || false,
...options
});
this.chains.set(name, {
chain,
type: 'conversation',
createdAt: Date.now()
});
return chain;
}
// 创建RAG链
async createRAGChain(name, llm, vectorStore, options = {}) {
const { RetrievalQAChain } = await import('langchain/chains');
const retriever = vectorStore.asRetriever({
k: options.topK || 4,
searchType: options.searchType || 'similarity',
...options.retriever
});
const chain = RetrievalQAChain.fromLLM(llm, retriever, {
returnSourceDocuments: options.returnSourceDocuments || true,
verbose: options.verbose || false,
...options
});
this.chains.set(name, {
chain,
type: 'rag',
retriever,
createdAt: Date.now()
});
return chain;
}
// 创建向量存储
async createVectorStore(name, documents, embeddings, storeType = 'memory') {
let vectorStore;
switch (storeType) {
case 'memory':
const { MemoryVectorStore } = await import('langchain/vectorstores/memory');
vectorStore = await MemoryVectorStore.fromDocuments(documents, embeddings);
break;
case 'chroma':
const { Chroma } = await import('langchain/vectorstores/chroma');
vectorStore = await Chroma.fromDocuments(documents, embeddings, {
collectionName: name
});
break;
case 'pinecone':
const { PineconeStore } = await import('langchain/vectorstores/pinecone');
vectorStore = await PineconeStore.fromDocuments(documents, embeddings, {
pineconeIndex: this.getPineconeIndex(name)
});
break;
default:
throw new Error(`Unsupported vector store type: ${storeType}`);
}
this.vectorStores.set(name, {
store: vectorStore,
type: storeType,
documentCount: documents.length,
createdAt: Date.now()
});
return vectorStore;
}
// 创建智能代理
async createAgent(name, llm, tools, options = {}) {
const { initializeAgentExecutorWithOptions } = await import('langchain/agents');
const executor = await initializeAgentExecutorWithOptions(tools, llm, {
agentType: options.agentType || 'zero-shot-react-description',
verbose: options.verbose || false,
maxIterations: options.maxIterations || 10,
earlyStoppingMethod: options.earlyStoppingMethod || 'generate',
...options
});
this.agents.set(name, {
executor,
tools,
createdAt: Date.now()
});
return executor;
}
// 文档处理和分割
async processDocuments(documents, options = {}) {
const { RecursiveCharacterTextSplitter } = await import('langchain/text_splitter');
const splitter = new RecursiveCharacterTextSplitter({
chunkSize: options.chunkSize || 1000,
chunkOverlap: options.chunkOverlap || 200,
separators: options.separators || ['\n\n', '\n', ' ', ''],
...options
});
const splitDocs = await splitter.splitDocuments(documents);
// 添加元数据
return splitDocs.map((doc, index) => ({
...doc,
metadata: {
...doc.metadata,
chunkIndex: index,
processedAt: Date.now()
}
}));
}
// 执行链
async runChain(name, input, options = {}) {
const chainInfo = this.chains.get(name);
if (!chainInfo) {
throw new Error(`Chain ${name} not found`);
}
const { chain } = chainInfo;
try {
const result = await chain.call(input, options);
// 记录使用统计
this.updateChainStats(name, {
inputTokens: this.estimateTokens(JSON.stringify(input)),
outputTokens: this.estimateTokens(JSON.stringify(result)),
executionTime: Date.now()
});
return result;
} catch (error) {
console.error(`Error running chain ${name}:`, error);
throw error;
}
}
// 批量处理
async batchProcess(chainName, inputs, options = {}) {
const batchSize = options.batchSize || 5;
const results = [];
for (let i = 0; i < inputs.length; i += batchSize) {
const batch = inputs.slice(i, i + batchSize);
const batchPromises = batch.map(input =>
this.runChain(chainName, input, options)
);
const batchResults = await Promise.allSettled(batchPromises);
results.push(...batchResults.map((result, index) => ({
index: i + index,
input: batch[index],
success: result.status === 'fulfilled',
result: result.status === 'fulfilled' ? result.value : null,
error: result.status === 'rejected' ? result.reason : null
})));
// 进度回调
if (options.onProgress) {
options.onProgress({
processed: Math.min(i + batchSize, inputs.length),
total: inputs.length,
progress: Math.min(i + batchSize, inputs.length) / inputs.length
});
}
// 批次间延迟
if (options.batchDelay && i + batchSize < inputs.length) {
await this.sleep(options.batchDelay);
}
}
return results;
}
// 链性能监控
updateChainStats(name, stats) {
const chainInfo = this.chains.get(name);
if (!chainInfo.stats) {
chainInfo.stats = {
totalCalls: 0,
totalInputTokens: 0,
totalOutputTokens: 0,
averageExecutionTime: 0,
lastUsed: null
};
}
const currentStats = chainInfo.stats;
currentStats.totalCalls++;
currentStats.totalInputTokens += stats.inputTokens;
currentStats.totalOutputTokens += stats.outputTokens;
currentStats.averageExecutionTime = (
(currentStats.averageExecutionTime * (currentStats.totalCalls - 1) +
stats.executionTime) / currentStats.totalCalls
);
currentStats.lastUsed = Date.now();
}
// 获取链统计信息
getChainStats(name) {
const chainInfo = this.chains.get(name);
return chainInfo ? chainInfo.stats : null;
}
// 工具方法
estimateTokens(text) {
// 简单的token估算,实际应用中可以使用更精确的方法
return Math.ceil(text.length / 4);
}
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
开发工具链
1. 构建工具配置
Webpack配置
// webpack.config.js for AI applications
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
library: 'AIApp',
libraryTarget: 'umd'
},
resolve: {
fallback: {
"crypto": require.resolve("crypto-browserify"),
"stream": require.resolve("stream-browserify"),
"buffer": require.resolve("buffer"),
"process": require.resolve("process/browser"),
"path": require.resolve("path-browserify"),
"fs": false,
"net": false,
"tls": false
}
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: [
'@babel/plugin-proposal-class-properties',
'@babel/plugin-transform-runtime'
]
}
}
},
{
test: /\.wasm$/,
type: 'webassembly/async'
},
{
test: /\.(bin|onnx)$/,
type: 'asset/resource'
}
]
},
plugins: [
new webpack.ProvidePlugin({
Buffer: ['buffer', 'Buffer'],
process: 'process/browser'
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
})
],
experiments: {
asyncWebAssembly: true,
topLevelAwait: true
},
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
ai: {
test: /[\\/]node_modules[\\/](@tensorflow|@xenova|brain\.js)/,
name: 'ai-libs',
chunks: 'all'
}
}
}
}
};
Vite配置
// vite.config.js for AI applications
import { defineConfig } from 'vite';
import { resolve } from 'path';
export default defineConfig({
define: {
global: 'globalThis'
},
resolve: {
alias: {
'@': resolve(__dirname, 'src')
}
},
optimizeDeps: {
include: [
'@tensorflow/tfjs',
'@xenova/transformers',
'brain.js',
'openai'
],
exclude: [
'@tensorflow/tfjs-node'
]
},
build: {
rollupOptions: {
output: {
manualChunks: {
'ai-core': ['@tensorflow/tfjs', '@xenova/transformers'],
'ai-services': ['openai', 'langchain'],
'ai-utils': ['brain.js', 'ml5']
}
}
},
target: 'esnext',
minify: 'terser'
},
server: {
headers: {
'Cross-Origin-Embedder-Policy': 'require-corp',
'Cross-Origin-Opener-Policy': 'same-origin'
}
}
});
2. 性能监控工具
// AI应用性能监控
class AIPerformanceMonitor {
constructor() {
this.metrics = new Map();
this.observers = [];
this.isMonitoring = false;
}
startMonitoring() {
if (this.isMonitoring) return;
this.isMonitoring = true;
// 监控内存使用
this.memoryObserver = setInterval(() => {
if (performance.memory) {
this.recordMetric('memory', {
used: performance.memory.usedJSHeapSize,
total: performance.memory.totalJSHeapSize,
limit: performance.memory.jsHeapSizeLimit,
timestamp: Date.now()
});
}
}, 1000);
// 监控网络请求
this.setupNetworkMonitoring();
// 监控AI模型性能
this.setupModelMonitoring();
}
recordMetric(category, data) {
if (!this.metrics.has(category)) {
this.metrics.set(category, []);
}
const categoryMetrics = this.metrics.get(category);
categoryMetrics.push(data);
// 保持最近1000条记录
if (categoryMetrics.length > 1000) {
categoryMetrics.shift();
}
// 通知观察者
this.notifyObservers(category, data);
}
getMetrics(category, timeRange = 60000) {
const categoryMetrics = this.metrics.get(category) || [];
const cutoff = Date.now() - timeRange;
return categoryMetrics.filter(metric => metric.timestamp > cutoff);
}
generateReport() {
const report = {
timestamp: Date.now(),
memory: this.analyzeMemoryUsage(),
network: this.analyzeNetworkPerformance(),
models: this.analyzeModelPerformance(),
recommendations: this.generateRecommendations()
};
return report;
}
}
学习检验
理论问题
-
生态系统比较
- 比较TensorFlow.js、Brain.js和ML5.js的优缺点
- 在什么场景下选择客户端AI vs 服务端AI?
- 如何设计混合AI架构?
-
性能优化
- JavaScript AI应用的主要性能瓶颈有哪些?
- 如何优化模型加载和推理性能?
- 设计一个AI应用的缓存策略
-
工具链选择
- 如何为AI项目选择合适的构建工具?
- 不同AI库的打包优化策略
- 如何处理AI库的依赖冲突?
实践练习
-
环境搭建
- 创建一个支持多种AI库的开发环境
- 配置Webpack/Vite支持AI库打包
- 实现AI库的懒加载机制
-
性能对比
- 对比不同AI库在相同任务上的性能
- 测试客户端vs服务端AI的响应时间
- 分析内存使用和优化策略
-
集成开发
- 创建一个统一的AI服务管理器
- 实现多个AI提供商的负载均衡
- 开发AI应用的监控和调试工具
实践项目建议
初级项目
- AI库性能测试工具 - 对比不同AI库的性能表现
- 统一AI接口封装 - 创建统一的AI服务调用接口
- AI应用脚手架 - 快速创建AI应用的项目模板
中级项目
- AI模型管理平台 - 模型版本管理和部署工具
- 多模态AI工具箱 - 集成多种AI能力的工具集
- AI应用性能监控 - 实时监控AI应用性能
高级项目
- AI开发框架 - 完整的AI应用开发框架
- 智能代码生成器 - 基于AI的代码生成工具
- AI应用商店 - AI能力的发现和集成平台
延伸阅读
官方文档
开源项目
社区资源
JavaScript AI生态系统正在快速发展,让我们一起探索这个充满创新的领域!