LLMStream

LLMStream 是一个轻量级的大模型请求和 Markdown 实时渲染库,支持流式/非流式响应、打字机效果、自动 Markdown 渲染等功能。

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.cn-greasyfork.org/scripts/555072/1690858/LLMStream.js

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

作者
wish king
版本
0.0.1.20251107044450
建立日期
2025-11-07
更新日期
2025-11-07
尺寸
9.9 KB
授權條款
未知

LLMStream 使用文档(by Claude Sonnet4.5)

LLMStream 是一个轻量级的大模型请求和 Markdown 实时渲染库,支持流式/非流式响应、打字机效果、自动 Markdown 渲染等功能。


📦 快速开始

引入库

<!-- 在 HTML 中引入 -->
<script src="path/to/llmstream.js"></script>

<!-- 如果需要 Markdown 渲染,会自动加载 marked.js -->
<!-- 可选:引入代码高亮库 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/github.min.css">

基础用法

const stream = new LLMStream({
  url: 'https://your-api-endpoint.com/v1/chat/completions',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: {
    model: "your-model-name",
    messages: [
      { role: "user", content: "你好" }
    ],
    stream: true
  },
  target: '#output',
  markdown: true
});

stream.start();

🎯 配置选项

构造函数参数

参数 类型 必填 默认值 说明
url String - API 请求地址
method String 'POST' HTTP 请求方法
headers Object {} 请求头(如 Authorization)
body Object {} 请求体(包含 model、messages 等)
target String/Element - 渲染目标元素(CSS 选择器或 DOM 元素)
markdown Boolean true 是否启用 Markdown 渲染
stream Boolean true 是否使用流式请求(已废弃,请在 body 中配置)
typewriterEffect Boolean false 是否启用打字机效果(仅非流式)
typewriterSpeed Number 30 打字机效果速度(毫秒/字符)
onStart Function - 请求开始时的回调
onChunk Function - 接收到数据块时的回调 (chunk, fullContent)
onComplete Function - 请求完成时的回调 (fullContent)
onError Function - 请求出错时的回调 (error)

📖 使用示例

1️⃣ 流式请求(实时渲染)

流式请求会实时显示 AI 生成的内容,适合需要即时反馈的场景。

const stream = new LLMStream({
  url: 'https://api-inference.modelscope.cn/v1/chat/completions',
  method: 'POST',
  headers: {
    'Authorization': 'Bearer yourtoken',
    'Content-Type': 'application/json'
  },
  body: {
    model: "Qwen/Qwen3-Coder-480B-A35B-Instruct",
    messages: [
      { role: "user", content: "请用 Markdown 写一个快速排序的 Python 实现,并解释步骤。" }
    ],
    stream: true,  // ⚡ 启用流式响应
    temperature: 0.2
  },
  target: '#output',
  markdown: true,
  onChunk: (chunk, fullContent) => {
    console.log('收到数据块:', chunk);
  },
  onComplete: (content) => {
    console.log('✅ 流式传输完成');
  }
});

stream.start();

HTML 结构:

<div id="output" style="white-space: pre-wrap; padding: 20px;"></div>

2️⃣ 非流式请求(一次性显示)

非流式请求会等待完整响应后一次性显示,适合需要完整内容后再处理的场景。

const stream = new LLMStream({
  url: 'https://api-inference.modelscope.cn/v1/chat/completions',
  method: 'POST',
  headers: {
    'Authorization': 'Bearer yourtoken',
    'Content-Type': 'application/json'
  },
  body: {
    model: "Qwen/Qwen3-Coder-480B-A35B-Instruct",
    messages: [
      { role: "user", content: "介绍一下 Python" }
    ],
    stream: false,  // 🔒 关闭流式响应
    temperature: 0.7
  },
  target: '#output',
  markdown: true,
  onComplete: (content) => {
    console.log('✅ 内容已完整显示:', content);
  }
});

stream.start();

3️⃣ 非流式 + 打字机效果

结合非流式请求和打字机效果,可以实现更流畅的视觉体验。

const stream = new LLMStream({
  url: 'https://api-inference.modelscope.cn/v1/chat/completions',
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: {
    model: "your-model",
    messages: [
      { role: "user", content: "写一首关于春天的诗" }
    ],
    stream: false  // 非流式
  },
  target: '#output',
  markdown: true,
  typewriterEffect: true,  // ⌨️ 启用打字机效果
  typewriterSpeed: 50,     // 每个字符延迟 50ms
  onChunk: (char, fullContent) => {
    // 每输出一个字符都会触发
    console.log('打字机输出:', char);
  },
  onComplete: (content) => {
    console.log('✅ 打字机效果完成');
  }
});

stream.start();

4️⃣ 多轮对话示例

const conversationHistory = [];

function sendMessage(userMessage) {
  // 添加用户消息到历史
  conversationHistory.push({
    role: "user",
    content: userMessage
  });

  const stream = new LLMStream({
    url: 'https://your-api-endpoint.com/v1/chat/completions',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: {
      model: "your-model",
      messages: conversationHistory,
      stream: true
    },
    target: '#chat-output',
    markdown: true,
    onComplete: (content) => {
      // 添加助手回复到历史
      conversationHistory.push({
        role: "assistant",
        content: content
      });
    }
  });

  stream.start();
}

// 使用
sendMessage("你好");
// 等待回复后...
sendMessage("你能做什么?");

🎮 API 方法

start()

开始请求。

stream.start();

stop()

停止请求(取消 HTTP 请求或停止打字机效果)。

stream.stop();

getContent()

获取当前已接收的内容。

const content = stream.getContent();
console.log(content);

clear()

清空内容和目标元素。

stream.clear();

📋 回调函数详解

onStart()

请求开始时触发。

onStart: () => {
  console.log('🚀 请求开始');
  document.getElementById('loading').style.display = 'block';
}

onChunk(chunk, fullContent)

每次接收到数据块时触发(流式或打字机效果)。

onChunk: (chunk, fullContent) => {
  console.log('收到:', chunk);
  console.log('累计内容长度:', fullContent.length);
}

onComplete(fullContent)

请求完成时触发。

onComplete: (content) => {
  console.log('✅ 完成,总字数:', content.length);
  document.getElementById('loading').style.display = 'none';
}

onError(error)

请求出错时触发。

onError: (error) => {
  console.error('❌ 错误:', error);
  alert('请求失败: ' + error.message);
}

🎨 样式建议

/* 输出容器样式 */
#output {
  background: #f5f5f5;
  border: 1px solid #ddd;
  border-radius: 8px;
  padding: 20px;
  min-height: 200px;
  max-height: 600px;
  overflow-y: auto;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  line-height: 1.6;
  white-space: pre-wrap;
  word-wrap: break-word;
}

/* Markdown 代码块样式 */
#output pre {
  background: #282c34;
  color: #abb2bf;
  padding: 15px;
  border-radius: 5px;
  overflow-x: auto;
}

#output code {
  font-family: 'Courier New', Courier, monospace;
  font-size: 14px;
}

/* 行内代码 */
#output p code {
  background: #e8e8e8;
  color: #c7254e;
  padding: 2px 6px;
  border-radius: 3px;
}

🔧 支持的响应格式

LLMStream 自动识别以下响应格式:

  1. OpenAI / 通义千问标准格式

    {
      "choices": [
        {
          "message": {
            "content": "响应内容"
          }
        }
      ]
    }
    
  2. 简化格式

    {
      "content": "响应内容"
    }
    
  3. Output 字段

    {
      "output": {
        "content": "响应内容"
      }
    }
    
  4. 其他支持字段: response, text, result, message


⚠️ 注意事项

  1. 流式 vs 非流式:在 body.stream 中配置,而非构造函数的 stream 参数
  2. 打字机效果:仅在非流式模式下生效
  3. Markdown 渲染:会自动加载 marked.js,无需手动引入
  4. CORS 问题:确保 API 支持跨域请求
  5. API Key 安全:不要在前端代码中硬编码 API Key,建议通过后端代理

📦 完整示例

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>LLMStream Demo</title>
  <style>
    body { font-family: sans-serif; max-width: 800px; margin: 50px auto; }
    #output { 
      background: #f9f9f9; 
      border: 1px solid #ddd; 
      padding: 20px; 
      min-height: 300px;
      white-space: pre-wrap;
    }
    button { padding: 10px 20px; margin: 5px; cursor: pointer; }
  </style>
</head>
<body>
  <h1>LLMStream 演示</h1>
  <button onclick="testStream()">流式请求</button>
  <button onclick="testNormal()">非流式请求</button>
  <button onclick="testTypewriter()">打字机效果</button>
  <button onclick="stream.stop()">停止</button>
  <button onclick="stream.clear()">清空</button>

  <div id="output"></div>

  <script src="llmstream.js"></script>
  <script>
    let stream;

    function testStream() {
      stream = new LLMStream({
        url: 'https://api-inference.modelscope.cn/v1/chat/completions',
        headers: {
          'Authorization': 'Bearer YOUR_API_KEY',
          'Content-Type': 'application/json'
        },
        body: {
          model: "Qwen/Qwen3-Coder-480B-A35B-Instruct",
          messages: [{ role: "user", content: "写一个冒泡排序" }],
          stream: true
        },
        target: '#output',
        markdown: true,
        onComplete: () => alert('完成!')
      });
      stream.start();
    }

    function testNormal() {
      stream = new LLMStream({
        url: 'https://api-inference.modelscope.cn/v1/chat/completions',
        headers: {
          'Authorization': 'Bearer YOUR_API_KEY',
          'Content-Type': 'application/json'
        },
        body: {
          model: "Qwen/Qwen3-Coder-480B-A35B-Instruct",
          messages: [{ role: "user", content: "介绍 JavaScript" }],
          stream: false
        },
        target: '#output',
        markdown: true
      });
      stream.start();
    }

    function testTypewriter() {
      stream = new LLMStream({
        url: 'https://api-inference.modelscope.cn/v1/chat/completions',
        headers: {
          'Authorization': 'Bearer YOUR_API_KEY',
          'Content-Type': 'application/json'
        },
        body: {
          model: "Qwen/Qwen3-Coder-480B-A35B-Instruct",
          messages: [{ role: "user", content: "写一首诗" }],
          stream: false
        },
        target: '#output',
        markdown: true,
        typewriterEffect: true,
        typewriterSpeed: 30
      });
      stream.start();
    }
  </script>
</body>
</html>