Dette scriptet burde ikke installeres direkte. Det er et bibliotek for andre script å inkludere med det nye metadirektivet // @require https://update.greasyfork.org/scripts/555072/1690858/LLMStream.js
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 自动识别以下响应格式:
OpenAI / 通义千问标准格式
{
"choices": [
{
"message": {
"content": "响应内容"
}
}
]
}
简化格式
{
"content": "响应内容"
}
Output 字段
{
"output": {
"content": "响应内容"
}
}
其他支持字段: response, text, result, message
⚠️ 注意事项
- 流式 vs 非流式:在
body.stream 中配置,而非构造函数的 stream 参数
- 打字机效果:仅在非流式模式下生效
- Markdown 渲染:会自动加载
marked.js,无需手动引入
- CORS 问题:确保 API 支持跨域请求
- 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>