Skip to content

Commit b610b49

Browse files
committed
feat: 新增循环检测、网络代理、OpenAI兼容文档页面
- 新增 LoopDetection.vue: LLM 循环检测(N-gram 算法)文档 - 新增 Proxy.vue: 网络代理(SOCKS5/HTTPS)文档 - 新增 OpenAICompat.vue: OpenAI 兼容 API 文档 - 更新 sidebar/router/locales 配置,新页面加入导航和翻译
1 parent e31551f commit b610b49

8 files changed

Lines changed: 304 additions & 3 deletions

File tree

src/composables/useLocale.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,12 @@ export const SIDEBAR_KEYS = {
3232
providers: 'sidebar.providers',
3333
modelMapping: 'sidebar.modelMapping',
3434
concurrency: 'sidebar.concurrency',
35+
loopDetection: 'sidebar.loopDetection',
36+
proxy: 'sidebar.proxy',
3537
failover: 'sidebar.failover',
3638
monitor: 'sidebar.monitor',
3739
multiKey: 'sidebar.multiKey',
40+
openaiCompat: 'sidebar.openaiCompat',
3841
config: 'sidebar.config',
3942
claudeCode: 'sidebar.claudeCode',
4043
env: 'sidebar.env',

src/config/sidebar.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ export const llmSimpleRouterSidebar: SidebarGroup[] = [
2020
{ titleKey: K.providers, path: '/project/llm-simple-router/guide/features/providers' },
2121
{ titleKey: K.modelMapping, path: '/project/llm-simple-router/guide/features/model-mapping' },
2222
{ titleKey: K.concurrency, path: '/project/llm-simple-router/guide/features/concurrency' },
23+
{ titleKey: K.loopDetection, path: '/project/llm-simple-router/guide/features/loop-detection' },
24+
{ titleKey: K.proxy, path: '/project/llm-simple-router/guide/features/proxy' },
2325
{ titleKey: K.failover, path: '/project/llm-simple-router/guide/features/failover' },
26+
{ titleKey: K.openaiCompat, path: '/project/llm-simple-router/guide/features/openai-compat' },
2427
{ titleKey: K.monitor, path: '/project/llm-simple-router/guide/features/monitor' },
2528
{ titleKey: K.multiKey, path: '/project/llm-simple-router/guide/features/multi-key' },
2629
]},

src/locales/en.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ export default {
44
quickStart: 'Quick Start', overview: 'Overview', startRouter: 'Starting Router',
55
features: 'Features', autoRetry: 'Auto Retry', providers: 'Multi-Provider Support',
66
modelMapping: 'Model Mapping', concurrency: 'Concurrency Control',
7-
failover: 'Failover', monitor: 'Live Monitor', multiKey: 'Multi-Key Management',
7+
loopDetection: 'Loop Detection', proxy: 'Network Proxy', failover: 'Failover',
8+
monitor: 'Live Monitor', multiKey: 'Multi-Key Management',
9+
openaiCompat: 'OpenAI Compatible',
810
config: 'Configuration', claudeCode: 'Claude Code Setup', env: 'Environment Variables',
911
docker: 'Docker Deployment', architecture: 'Architecture',
1012
systemContext: 'System Context', requestPipeline: 'Request Pipeline',

src/locales/zh.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ export default {
33
sidebar: {
44
quickStart: '快速开始', overview: '概览', startRouter: '启动 Router',
55
features: '功能特性', autoRetry: '自动重试', providers: '多供应商支持',
6-
modelMapping: '模型映射', concurrency: '并发控制', failover: '故障转移',
7-
monitor: '实时监控', multiKey: '多密钥管理',
6+
modelMapping: '模型映射', concurrency: '并发控制', loopDetection: '循环检测',
7+
proxy: '网络代理', failover: '故障转移',
8+
monitor: '实时监控', multiKey: '多密钥管理', openaiCompat: 'OpenAI 兼容',
89
config: '配置指南', claudeCode: 'Claude Code 配置', env: '环境变量',
910
docker: 'Docker 部署', architecture: '架构原理',
1011
systemContext: '系统上下文', requestPipeline: '请求流水线',

src/router/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ const router = createRouter({
6060
path: 'guide/features/concurrency',
6161
component: () => import('../views/project/llm-simple-router/features/Concurrency.vue'),
6262
},
63+
{
64+
path: 'guide/features/loop-detection',
65+
component: () => import('../views/project/llm-simple-router/features/LoopDetection.vue'),
66+
},
67+
{
68+
path: 'guide/features/proxy',
69+
component: () => import('../views/project/llm-simple-router/features/Proxy.vue'),
70+
},
6371
{
6472
path: 'guide/features/failover',
6573
component: () => import('../views/project/llm-simple-router/features/Failover.vue'),
@@ -72,6 +80,10 @@ const router = createRouter({
7280
path: 'guide/features/multi-key',
7381
component: () => import('../views/project/llm-simple-router/features/MultiKey.vue'),
7482
},
83+
{
84+
path: 'guide/features/openai-compat',
85+
component: () => import('../views/project/llm-simple-router/features/OpenAICompat.vue'),
86+
},
7587
{
7688
path: 'guide/config/claude-code',
7789
component: () => import('../views/project/llm-simple-router/config/ClaudeCode.vue'),
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<script setup lang="ts">
2+
import { computed } from 'vue'
3+
import { useI18n } from 'vue-i18n'
4+
const { locale } = useI18n()
5+
const isZh = computed(() => locale.value === 'zh')
6+
</script>
7+
8+
<template>
9+
<div class="prose prose-invert max-w-none">
10+
<template v-if="isZh">
11+
<h1>LLM 循环检测</h1>
12+
<p>
13+
当 LLM 在流式输出中出现重复内容循环时,Router 自动检测并中断,避免浪费 Token 和请求时长。
14+
基于 N-gram 算法,分析输出内容中的重复模式。
15+
</p>
16+
17+
<h2>检测原理</h2>
18+
<div class="not-prose my-4 rounded-lg border border-white/10 bg-surface-50 p-4">
19+
<code class="text-sm font-mono text-gray-300 block leading-loose">
20+
SSE 流式输出 → 实时拼接完整文本<br>
21+
→ 提取 N-gram(连续 N 个 token)<br>
22+
→ 计算重复率(重复 N-gram 占比)<br>
23+
→ 超过阈值 → 判定为循环,中断输出
24+
</code>
25+
</div>
26+
27+
<h2>配置方式</h2>
28+
<p>
29+
在管理后台 <strong>代理增强(实验性)</strong> 菜单中,可以按开关控制循环检测的启用/禁用。
30+
支持配置 N-gram 窗口大小和重复阈值。
31+
</p>
32+
33+
<h2>使用场景</h2>
34+
<ul>
35+
<li>模型在长文本生成时陷入重复(如反复输出相同段落)</li>
36+
<li>工具调用来回循环,模型反复尝试同一操作</li>
37+
<li>代码生成中出现死循环模式</li>
38+
</ul>
39+
40+
<h2>与并发控制的关系</h2>
41+
<p>
42+
循环检测配合并发控制使用效果更佳:循环检测中断后释放并发槽位,避免长时间占用资源。
43+
循环检测和自适应并发控制都已插件化到 <code>@llm-router/core</code> 中,供 pi-extension 使用。
44+
</p>
45+
</template>
46+
47+
<template v-else>
48+
<h1>LLM Loop Detection</h1>
49+
<p>
50+
When an LLM starts repeating content in streaming output, the Router automatically detects and interrupts
51+
the loop to save tokens and request time. Powered by an N-gram algorithm that analyzes repetition patterns.
52+
</p>
53+
54+
<h2>How It Works</h2>
55+
<div class="not-prose my-4 rounded-lg border border-white/10 bg-surface-50 p-4">
56+
<code class="text-sm font-mono text-gray-300 block leading-loose">
57+
SSE stream → Real-time full text assembly<br>
58+
→ Extract N-grams (consecutive N tokens)<br>
59+
→ Calculate repetition ratio (duplicate N-gram percentage)<br>
60+
→ Exceeds threshold → Detect loop, interrupt output
61+
</code>
62+
</div>
63+
64+
<h2>Configuration</h2>
65+
<p>
66+
In the admin panel under <strong>Proxy Enhancement (Experimental)</strong>, toggle loop detection on/off.
67+
Configure N-gram window size and repetition threshold as needed.
68+
</p>
69+
70+
<h2>Use Cases</h2>
71+
<ul>
72+
<li>Model gets stuck repeating the same paragraphs in long text generation</li>
73+
<li>Tool calls looping — model repeatedly attempts the same operation</li>
74+
<li>Infinite loop patterns in code generation</li>
75+
</ul>
76+
77+
<h2>Integration</h2>
78+
<p>
79+
Loop detection and adaptive concurrency have been modularized into <code>@llm-router/core</code>
80+
for use by the pi-extension as reusable building blocks.
81+
</p>
82+
</template>
83+
</div>
84+
</template>
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<script setup lang="ts">
2+
import { computed } from 'vue'
3+
import { useI18n } from 'vue-i18n'
4+
const { locale } = useI18n()
5+
const isZh = computed(() => locale.value === 'zh')
6+
</script>
7+
8+
<template>
9+
<div class="prose prose-invert max-w-none">
10+
<template v-if="isZh">
11+
<h1>OpenAI 兼容 API</h1>
12+
<p>
13+
Router 完整兼容 OpenAI API 格式,支持 <code>/v1/chat/completions</code> 和新增的
14+
<code>/v1/responses</code> 端点。无论使用哪个后端 Provider,客户端都能以标准 OpenAI SDK 进行调用。
15+
</p>
16+
17+
<h2>支持的端点</h2>
18+
<table>
19+
<thead><tr><th>端点</th><th>说明</th></tr></thead>
20+
<tbody>
21+
<tr><td><code>/v1/chat/completions</code></td><td>标准 Chat Completions API(始终支持)</td></tr>
22+
<tr><td><code>/v1/responses</code></td><td>OpenAI Responses API(v0.9.2 新增)</td></tr>
23+
</tbody>
24+
</table>
25+
26+
<h2>Provider Patch 重写</h2>
27+
<p>
28+
Router 内置 Provider Patch 机制,自动将 OpenAI 格式的请求转换为各 Provider 的原生格式,
29+
并将响应转回 OpenAI 兼容格式。支持流式和非流式。
30+
</p>
31+
<div class="not-prose my-4 rounded-lg border border-white/10 bg-surface-50 p-4">
32+
<code class="text-sm font-mono text-gray-300 block leading-loose">
33+
OpenAI SDK 请求 → Router 接收<br>
34+
→ Provider Patch 转换(OpenAI → 供应商原生格式)<br>
35+
→ 发送到供应商<br>
36+
→ 响应 Patch 转换(供应商格式 → OpenAI)<br>
37+
→ 返回给客户端
38+
</code>
39+
</div>
40+
41+
<h2>Response Cleaner</h2>
42+
<p>
43+
自动清理供应商响应中的非标准字段,确保返回的 JSON 结构与 OpenAI 规范一致,避免客户端解析错误。
44+
</p>
45+
46+
<h2>使用方式</h2>
47+
<p>
48+
客户端无需任何修改,将 <code>base_url</code> 指向 Router 即可。
49+
例如:<code>http://localhost:9981/v1</code>。Claude Code、Cursor、OpenAI SDK 等均可直接使用。
50+
</p>
51+
</template>
52+
53+
<template v-else>
54+
<h1>OpenAI Compatible API</h1>
55+
<p>
56+
The Router is fully compatible with OpenAI API format, supporting both
57+
<code>/v1/chat/completions</code> and the new <code>/v1/responses</code> endpoint.
58+
Clients use the standard OpenAI SDK regardless of the backend provider.
59+
</p>
60+
61+
<h2>Supported Endpoints</h2>
62+
<table>
63+
<thead><tr><th>Endpoint</th><th>Description</th></tr></thead>
64+
<tbody>
65+
<tr><td><code>/v1/chat/completions</code></td><td>Standard Chat Completions API (always supported)</td></tr>
66+
<tr><td><code>/v1/responses</code></td><td>OpenAI Responses API (new in v0.9.2)</td></tr>
67+
</tbody>
68+
</table>
69+
70+
<h2>Provider Patch Rewrite</h2>
71+
<p>
72+
The Router has a built-in Provider Patch mechanism that automatically converts
73+
OpenAI-format requests to each Provider's native format, and converts responses back
74+
to OpenAI-compatible format. Both streaming and non-streaming are supported.
75+
</p>
76+
<div class="not-prose my-4 rounded-lg border border-white/10 bg-surface-50 p-4">
77+
<code class="text-sm font-mono text-gray-300 block leading-loose">
78+
OpenAI SDK request → Router receives<br>
79+
→ Provider Patch (OpenAI → Provider native format)<br>
80+
→ Send to Provider<br>
81+
→ Response Patch (Provider format → OpenAI)<br>
82+
→ Return to client
83+
</code>
84+
</div>
85+
86+
<h2>Response Cleaner</h2>
87+
<p>
88+
Automatically strips non-standard fields from provider responses, ensuring
89+
returned JSON matches the OpenAI spec and avoiding client-side parse errors.
90+
</p>
91+
92+
<h2>Usage</h2>
93+
<p>
94+
No client-side changes needed — point <code>base_url</code> to the Router.
95+
Example: <code>http://localhost:9981/v1</code>. Works with Claude Code, Cursor, OpenAI SDK, etc.
96+
</p>
97+
</template>
98+
</div>
99+
</template>
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<script setup lang="ts">
2+
import { computed } from 'vue'
3+
import { useI18n } from 'vue-i18n'
4+
const { locale } = useI18n()
5+
const isZh = computed(() => locale.value === 'zh')
6+
</script>
7+
8+
<template>
9+
<div class="prose prose-invert max-w-none">
10+
<template v-if="isZh">
11+
<h1>网络代理</h1>
12+
<p>
13+
为每个 Provider 独立配置 SOCKS5 或 HTTPS 代理,让 Router 通过代理服务器访问后端 API。
14+
适用于需要通过代理上网的网络环境。
15+
</p>
16+
17+
<h2>工作原理</h2>
18+
<div class="not-prose my-4 rounded-lg border border-white/10 bg-surface-50 p-4">
19+
<code class="text-sm font-mono text-gray-300 block leading-loose">
20+
客户端 → Router → SOCKS5/HTTPS 代理 → 上游 Provider API<br>
21+
支持 socks-proxy-agent / https-proxy-agent 两种代理协议
22+
</code>
23+
</div>
24+
25+
<h2>配置方式</h2>
26+
<p>
27+
在管理后台的 <strong>Provider 编辑弹窗</strong> 中,可以配置代理信息:
28+
</p>
29+
<ul>
30+
<li><strong>代理类型</strong>:SOCKS5 或 HTTPS</li>
31+
<li><strong>代理主机</strong>:代理服务器地址</li>
32+
<li><strong>代理端口</strong>:代理服务器端口</li>
33+
<li><strong>认证信息</strong>:用户名和密码(可选)</li>
34+
</ul>
35+
36+
<h2>数据库支持</h2>
37+
<p>
38+
providers 表增加代理相关字段(migration 041),包括 <code>proxy_type</code>、<code>proxy_host</code>、
39+
<code>proxy_port</code>、<code>proxy_username</code>、<code>proxy_password</code>。
40+
</p>
41+
42+
<h2>使用场景</h2>
43+
<ul>
44+
<li>企业内网需要通过代理访问外网 API</li>
45+
<li>使用 SOCKS5 代理访问受限区域的 API</li>
46+
<li>部分供应商仅支持特定网络出口</li>
47+
</ul>
48+
49+
<h2>依赖</h2>
50+
<p>代理功能依赖 <code>socks-proxy-agent</code> 和 <code>https-proxy-agent</code> 两个 npm 包,安装 Router 时自动包含。</p>
51+
</template>
52+
53+
<template v-else>
54+
<h1>Network Proxy</h1>
55+
<p>
56+
Configure SOCKS5 or HTTPS proxy per Provider, enabling the Router to access backend APIs
57+
through a proxy server. Ideal for network environments that require proxied outbound connections.
58+
</p>
59+
60+
<h2>How It Works</h2>
61+
<div class="not-prose my-4 rounded-lg border border-white/10 bg-surface-50 p-4">
62+
<code class="text-sm font-mono text-gray-300 block leading-loose">
63+
Client → Router → SOCKS5/HTTPS Proxy → Upstream Provider API<br>
64+
Supports both socks-proxy-agent and https-proxy-agent
65+
</code>
66+
</div>
67+
68+
<h2>Configuration</h2>
69+
<p>
70+
In the admin panel's <strong>Provider Edit Dialog</strong>, configure proxy settings:
71+
</p>
72+
<ul>
73+
<li><strong>Proxy Type</strong>: SOCKS5 or HTTPS</li>
74+
<li><strong>Proxy Host</strong>: Proxy server address</li>
75+
<li><strong>Proxy Port</strong>: Proxy server port</li>
76+
<li><strong>Authentication</strong>: Username and password (optional)</li>
77+
</ul>
78+
79+
<h2>Database</h2>
80+
<p>
81+
The providers table includes proxy-related columns (migration 041):
82+
<code>proxy_type</code>, <code>proxy_host</code>, <code>proxy_port</code>,
83+
<code>proxy_username</code>, <code>proxy_password</code>.
84+
</p>
85+
86+
<h2>Use Cases</h2>
87+
<ul>
88+
<li>Corporate networks requiring proxy for external API access</li>
89+
<li>SOCKS5 proxy for accessing region-restricted APIs</li>
90+
<li>Providers that require specific network egress</li>
91+
</ul>
92+
93+
<h2>Dependencies</h2>
94+
<p>Proxy support uses <code>socks-proxy-agent</code> and <code>https-proxy-agent</code> npm packages, included automatically.</p>
95+
</template>
96+
</div>
97+
</template>

0 commit comments

Comments
 (0)