1. 项目简介

Transformers.js是一个强大的JavaScript库,允许在浏览器和Node.js环境中运行预训练的Transformer模型。它基于ONNX Runtime,提供了与Hugging Face Transformers库类似的API,使开发者能够在前端应用中直接使用先进的NLP模型,无需服务器端依赖。

1.1 核心功能

  • 浏览器端运行:在浏览器中直接运行Transformer模型,无需服务器后端
  • Node.js支持:也可以在Node.js环境中使用
  • 多种预训练模型:支持Hugging Face上的多种预训练模型
  • ONNX格式:使用ONNX格式的模型,提高推理效率
  • 与Hugging Face兼容:API设计与Hugging Face Transformers库类似

1.2 项目特点

  • 无需服务器依赖:模型在客户端运行,保护用户隐私
  • 轻量级:优化的模型加载和推理
  • 易于集成:简单的API接口,易于集成到现有项目
  • 跨平台:支持浏览器和Node.js环境
  • 持续更新:不断添加新模型和功能

2. 安装与配置

2.1 在浏览器中使用

<!-- 通过CDN引入 -->
<script src="https://cdn.jsdelivr.net/npm/@xenova/transformers@2.17.0"></script>

<!-- 或者通过npm安装后使用 -->
<!-- npm install @xenova/transformers -->

2.2 在Node.js中使用

# 安装依赖
npm install @xenova/transformers

# 验证安装
node -e "require('@xenova/transformers'); console.log('Transformers.js installed successfully');"

3. 核心概念

3.1 模型加载

Transformers.js使用pipeline函数加载和使用预训练模型。模型会自动从Hugging Face Hub下载并缓存到本地。

3.2 管道(Pipeline)

管道是Transformers.js的核心概念,它封装了模型的加载和推理过程,提供了简单的API接口。支持多种任务类型,如文本分类、命名实体识别、翻译等。

3.3 模型缓存

Transformers.js会自动缓存下载的模型,避免重复下载,提高性能。缓存位置在浏览器中为IndexedDB,在Node.js中为本地文件系统。

3.4 ONNX Runtime

Transformers.js基于ONNX Runtime运行模型,提供高效的推理性能。ONNX Runtime针对不同硬件和平台进行了优化。

4. 基本用法

4.1 文本分类

// 在浏览器中
async function runTextClassification() {
    // 加载文本分类管道
    const classifier = await pipeline('sentiment-analysis');
    
    // 分类文本
    const result = await classifier('I love Transformers.js!');
    console.log(result);
    // 输出: [{ label: 'POSITIVE', score: 0.9998 }]
}

runTextClassification();

// 在Node.js中
const { pipeline } = require('@xenova/transformers');

async function runTextClassification() {
    const classifier = await pipeline('sentiment-analysis');
    const result = await classifier('I love Transformers.js!');
    console.log(result);
}

runTextClassification();

4.2 命名实体识别

async function runNER() {
    // 加载命名实体识别管道
    const ner = await pipeline('ner');
    
    // 识别实体
    const result = await ner('My name is John and I live in New York.');
    console.log(result);
    /* 输出:
    [
        { entity: 'PER', score: 0.9995, index: 3, word: 'John', start: 11, end: 15 },
        { entity: 'LOC', score: 0.9996, index: 7, word: 'New', start: 25, end: 28 },
        { entity: 'LOC', score: 0.9998, index: 8, word: 'York', start: 29, end: 33 }
    ]
    */
}

runNER();

4.3 文本生成

async function runTextGeneration() {
    // 加载文本生成管道
    const generator = await pipeline('text-generation');
    
    // 生成文本
    const result = await generator('Once upon a time', {
        max_new_tokens: 50,
        temperature: 0.7
    });
    console.log(result[0].generated_text);
    // 输出: 生成的文本内容
}

runTextGeneration();

4.4 翻译

async function runTranslation() {
    // 加载翻译管道(英语到法语)
    const translator = await pipeline('translation', 'Xenova/opus-mt-en-fr');
    
    // 翻译文本
    const result = await translator('Hello, how are you?');
    console.log(result[0].translation_text);
    // 输出: 'Bonjour, comment allez-vous?'
}

runTranslation();

5. 高级特性

5.1 自定义模型

async function useCustomModel() {
    // 加载自定义模型
    const classifier = await pipeline('sentiment-analysis', {
        model: 'Xenova/distilbert-base-uncased-finetuned-sst-2-english',
        // 可选配置
        quantized: true, // 使用量化模型减小大小
        cache_dir: './models' // 自定义缓存目录
    });
    
    // 使用模型
    const result = await classifier('I hate this product.');
    console.log(result);
}

useCustomModel();

5.2 模型缓存管理

// 清除缓存
await pipeline('sentiment-analysis', {
    clear_cache: true
});

// 自定义缓存策略
const classifier = await pipeline('sentiment-analysis', {
    cache_dir: './my-models',
    use_cache: true
});

5.3 批量处理

async function batchProcessing() {
    const classifier = await pipeline('sentiment-analysis');
    
    // 批量处理多个文本
    const texts = [
        'I love this movie!',
        'This is the worst film I have ever seen.',
        'The acting was fantastic.'
    ];
    
    const results = await classifier(texts);
    console.log(results);
    /* 输出:
    [
        { label: 'POSITIVE', score: 0.9998 },
        { label: 'NEGATIVE', score: 0.9991 },
        { label: 'POSITIVE', score: 0.9997 }
    ]
    */
}

batchProcessing();

5.4 进度跟踪

async function trackProgress() {
    const classifier = await pipeline('sentiment-analysis', {
        progress_callback: (progress) => {
            console.log(`Model loading progress: ${Math.round(progress * 100)}%`);
        }
    });
    
    // 使用模型
    const result = await classifier('Hello world!');
    console.log(result);
}

trackProgress();

6. 实际应用案例

6.1 情感分析Web应用

场景:创建一个Web应用,允许用户输入文本并分析其情感

步骤

  1. 创建HTML页面
  2. 引入Transformers.js
  3. 实现情感分析功能
  4. 显示结果

代码示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>情感分析应用</title>
    <script src="https://cdn.jsdelivr.net/npm/@xenova/transformers@2.17.0"></script>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }
        .container {
            background-color: #f5f5f5;
            padding: 20px;
            border-radius: 8px;
        }
        textarea {
            width: 100%;
            height: 100px;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 4px;
            resize: vertical;
        }
        button {
            margin-top: 10px;
            padding: 10px 20px;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }
        button:hover {
            background-color: #45a049;
        }
        .result {
            margin-top: 20px;
            padding: 10px;
            border-radius: 4px;
        }
        .positive {
            background-color: #d4edda;
            color: #155724;
        }
        .negative {
            background-color: #f8d7da;
            color: #721c24;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>情感分析应用</h1>
        <p>输入文本,点击分析按钮查看情感分析结果:</p>
        <textarea id="text-input" placeholder="请输入要分析的文本..."></textarea>
        <button onclick="analyzeSentiment()">分析情感</button>
        <div id="result" class="result" style="display: none;"></div>
    </div>

    <script>
        let classifier;

        // 初始化模型
        async function initModel() {
            console.log('正在加载情感分析模型...');
            classifier = await pipeline('sentiment-analysis');
            console.log('模型加载完成!');
        }

        // 分析情感
        async function analyzeSentiment() {
            const text = document.getElementById('text-input').value;
            if (!text.trim()) {
                alert('请输入要分析的文本');
                return;
            }

            if (!classifier) {
                await initModel();
            }

            console.log('正在分析情感...');
            const result = await classifier(text);
            console.log('分析结果:', result);

            // 显示结果
            const resultDiv = document.getElementById('result');
            resultDiv.style.display = 'block';
            resultDiv.className = `result ${result[0].label.toLowerCase()}`;
            resultDiv.innerHTML = `
                <strong>情感分析结果:</strong>${result[0].label}<br>
                <strong>置信度:</strong>${(result[0].score * 100).toFixed(2)}%
            `;
        }

        // 页面加载时初始化模型
        window.onload = initModel;
    </script>
</body>
</html>

6.2 实时聊天机器人

场景:创建一个基于Transformers.js的实时聊天机器人

步骤

  1. 创建HTML页面
  2. 引入Transformers.js
  3. 加载对话模型
  4. 实现聊天功能

代码示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>聊天机器人</title>
    <script src="https://cdn.jsdelivr.net/npm/@xenova/transformers@2.17.0"></script>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }
        .chat-container {
            background-color: #f5f5f5;
            padding: 20px;
            border-radius: 8px;
            height: 400px;
            overflow-y: scroll;
            margin-bottom: 10px;
        }
        .message {
            margin-bottom: 10px;
            padding: 10px;
            border-radius: 4px;
        }
        .user-message {
            background-color: #e3f2fd;
            align-self: flex-end;
            margin-left: 50px;
        }
        .bot-message {
            background-color: #e8f5e8;
            align-self: flex-start;
            margin-right: 50px;
        }
        .input-container {
            display: flex;
        }
        input {
            flex: 1;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 4px 0 0 4px;
        }
        button {
            padding: 10px 20px;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 0 4px 4px 0;
            cursor: pointer;
        }
        button:hover {
            background-color: #45a049;
        }
        .loading {
            font-style: italic;
            color: #666;
        }
    </style>
</head>
<body>
    <h1>聊天机器人</h1>
    <div class="chat-container" id="chat-container">
        <div class="message bot-message">
            你好!我是基于Transformers.js的聊天机器人。有什么我可以帮助你的吗?
        </div>
    </div>
    <div class="input-container">
        <input type="text" id="user-input" placeholder="输入消息..." onkeypress="if(event.key === 'Enter') sendMessage()">
        <button onclick="sendMessage()">发送</button>
    </div>

    <script>
        let generator;

        // 初始化模型
        async function initModel() {
            console.log('正在加载对话模型...');
            generator = await pipeline('text-generation', 'Xenova/distilgpt2');
            console.log('模型加载完成!');
        }

        // 发送消息
        async function sendMessage() {
            const userInput = document.getElementById('user-input').value;
            if (!userInput.trim()) return;

            // 添加用户消息
            addMessage(userInput, 'user');
            document.getElementById('user-input').value = '';

            // 添加加载中消息
            const loadingId = addMessage('正在思考...', 'bot', true);

            if (!generator) {
                await initModel();
            }

            // 生成回复
            const prompt = `User: ${userInput}\nAssistant:`;
            const result = await generator(prompt, {
                max_new_tokens: 100,
                temperature: 0.7,
                stop_sequence: ['User:']
            });

            // 移除加载中消息
            document.getElementById(loadingId).remove();

            // 添加机器人回复
            const response = result[0].generated_text.replace(prompt, '').trim();
            addMessage(response, 'bot');
        }

        // 添加消息到聊天界面
        function addMessage(text, sender, isLoading = false) {
            const chatContainer = document.getElementById('chat-container');
            const messageDiv = document.createElement('div');
            const messageId = `message-${Date.now()}`;
            messageDiv.id = messageId;
            messageDiv.className = `message ${sender}-message ${isLoading ? 'loading' : ''}`;
            messageDiv.textContent = text;
            chatContainer.appendChild(messageDiv);
            chatContainer.scrollTop = chatContainer.scrollHeight;
            return messageId;
        }

        // 页面加载时初始化模型
        window.onload = initModel;
    </script>
</body>
</html>

6.3 多语言翻译应用

场景:创建一个支持多语言翻译的Web应用

步骤

  1. 创建HTML页面
  2. 引入Transformers.js
  3. 实现翻译功能
  4. 支持多种语言对

代码示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>多语言翻译应用</title>
    <script src="https://cdn.jsdelivr.net/npm/@xenova/transformers@2.17.0"></script>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }
        .container {
            background-color: #f5f5f5;
            padding: 20px;
            border-radius: 8px;
        }
        textarea {
            width: 100%;
            height: 100px;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 4px;
            resize: vertical;
            margin-bottom: 10px;
        }
        .controls {
            margin-bottom: 10px;
        }
        select {
            padding: 8px;
            border: 1px solid #ddd;
            border-radius: 4px;
            margin-right: 10px;
        }
        button {
            padding: 8px 16px;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }
        button:hover {
            background-color: #45a049;
        }
        .result {
            margin-top: 20px;
            padding: 10px;
            border-radius: 4px;
            background-color: #e3f2fd;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>多语言翻译应用</h1>
        <div class="controls">
            <select id="source-lang">
                <option value="en">英语</option>
                <option value="fr">法语</option>
                <option value="de">德语</option>
                <option value="es">西班牙语</option>
            </select>
            <span>→</span>
            <select id="target-lang">
                <option value="fr">法语</option>
                <option value="de">德语</option>
                <option value="es">西班牙语</option>
                <option value="en">英语</option>
            </select>
        </div>
        <textarea id="input-text" placeholder="请输入要翻译的文本..."></textarea>
        <button onclick="translateText()">翻译</button>
        <div id="result" class="result" style="display: none;">
            <h3>翻译结果:</h3>
            <div id="translation-result"></div>
        </div>
    </div>

    <script>
        let translators = {};

        // 翻译文本
        async function translateText() {
            const sourceLang = document.getElementById('source-lang').value;
            const targetLang = document.getElementById('target-lang').value;
            const inputText = document.getElementById('input-text').value;

            if (!inputText.trim()) {
                alert('请输入要翻译的文本');
                return;
            }

            // 生成模型名称
            const modelName = `Xenova/opus-mt-${sourceLang}-${targetLang}`;

            // 加载翻译器
            if (!translators[modelName]) {
                console.log(`正在加载翻译模型: ${modelName}...`);
                translators[modelName] = await pipeline('translation', modelName);
                console.log('模型加载完成!');
            }

            // 执行翻译
            console.log('正在翻译...');
            const result = await translators[modelName](inputText);
            console.log('翻译结果:', result);

            // 显示结果
            const resultDiv = document.getElementById('result');
            const translationDiv = document.getElementById('translation-result');
            resultDiv.style.display = 'block';
            translationDiv.textContent = result[0].translation_text;
        }
    </script>
</body>
</html>

7. 总结与展望

Transformers.js为前端开发者提供了在浏览器和Node.js环境中直接使用Transformer模型的能力,无需服务器后端。它的出现极大地扩展了AI模型的应用场景,使得更多的AI功能可以在客户端实现,保护用户隐私的同时提高响应速度。

7.1 主要优势

  • 客户端运行:模型在客户端运行,无需服务器依赖
  • 易于集成:简单的API接口,易于集成到现有项目
  • 跨平台:支持浏览器和Node.js环境
  • 轻量级:优化的模型加载和推理
  • 与Hugging Face兼容:API设计与Hugging Face Transformers库类似

7.2 未来发展

  • 更多模型支持:持续添加对更多预训练模型的支持
  • 性能优化:进一步提高模型推理速度和内存使用效率
  • 功能扩展:添加更多NLP任务和功能
  • 工具链完善:提供更多开发工具和示例
  • 生态系统建设:构建更丰富的开发者生态

Transformers.js正在改变前端开发的格局,使得AI能力可以更直接地集成到前端应用中。通过掌握Transformers.js,开发者可以创建更加智能、响应迅速且保护用户隐私的Web应用。