Просмотр исходного кода

feat: streamfake web control support (#350)

* feat: streamfake web control support

* fix: show stream fake plugin enable in plugin info
zijiren 4 месяцев назад
Родитель
Сommit
5d39705f7e

+ 6 - 0
web/public/locales/en/translation.json

@@ -175,6 +175,7 @@
     "cachePlugin": "Cache",
     "webSearchPlugin": "Web Search",
     "thinkSplitPlugin": "Think Split",
+    "streamFakePlugin": "Stream Fake",
     "accessibleSets": "Accessible Sets",
     "loading": "Loading...",
     "noChannel": "No available channels",
@@ -260,6 +261,11 @@
         "title": "Think Split Plugin",
         "description": "Split complex thinking into structured responses",
         "enable": "Enable Think Split"
+      },
+      "streamFakePlugin": {
+        "title": "Stream Fake Plugin",
+        "description": "Convert non-streaming requests to streaming responses for better user experience",
+        "enable": "Enable Stream Fake"
       }
     },
     "deleteDialog": {

+ 6 - 0
web/public/locales/zh/translation.json

@@ -175,6 +175,7 @@
     "cachePlugin": "缓存",
     "webSearchPlugin": "网络搜索",
     "thinkSplitPlugin": "思考拆分",
+    "streamFakePlugin": "流式伪装",
     "accessibleSets": "可访问组",
     "loading": "加载中...",
     "noChannel": "无可用渠道",
@@ -259,6 +260,11 @@
         "title": "思考拆分插件",
         "description": "将复杂思考拆分为结构化响应",
         "enable": "启用思考拆分"
+      },
+      "streamFakePlugin": {
+        "title": "流式伪装插件",
+        "description": "将非流式请求转换为流式处理,提供更好的用户体验",
+        "enable": "启用流式伪装"
       }
     },
     "deleteDialog": {

+ 36 - 0
web/src/feature/model/components/ModelForm.tsx

@@ -101,6 +101,7 @@ export function ModelForm({
                 cache: { enable: false, ...defaultValues.plugin?.cache },
                 "web-search": { enable: false, search_from: [], ...defaultValues.plugin?.["web-search"] },
                 "think-split": { enable: false, ...defaultValues.plugin?.["think-split"] },
+                "stream-fake": { enable: false, ...defaultValues.plugin?.["stream-fake"] },
             }
         },
     })
@@ -271,6 +272,15 @@ export function ModelForm({
             })
         }
 
+        // Stream fake plugin - 如果开启,必须有 enable 字段
+        if (data.plugin?.["stream-fake"]?.enable) {
+            Object.assign(pluginData, {
+                "stream-fake": {
+                    enable: true
+                }
+            })
+        }
+
         // Prepare data for API - 如果没有启用的插件,则不传递 plugin 字段
         const formData: { 
             model?: string; 
@@ -831,6 +841,32 @@ export function ModelForm({
                                 </div>
                             </div>
                         </div>
+
+                        <hr className="border-border" />
+
+                        {/* Stream Fake Plugin */}
+                        <div className="flex items-center justify-between py-2">
+                            <div className="flex items-center space-x-3">
+                                <FormField
+                                    control={form.control}
+                                    name="plugin.stream-fake.enable"
+                                    render={({ field }) => (
+                                        <FormItem className="flex items-center space-x-2">
+                                            <FormControl>
+                                                <Switch
+                                                    checked={field.value}
+                                                    onCheckedChange={field.onChange}
+                                                />
+                                            </FormControl>
+                                        </FormItem>
+                                    )}
+                                />
+                                <div>
+                                    <Label className="text-sm font-medium">{t("model.dialog.streamFakePlugin.title")}</Label>
+                                    <p className="text-xs text-muted-foreground">{t("model.dialog.streamFakePlugin.description")}</p>
+                                </div>
+                            </div>
+                        </div>
                     </div>
 
                     {/* Submit button */}

+ 4 - 0
web/src/feature/model/components/ModelTable.tsx

@@ -200,6 +200,10 @@ export function ModelTable() {
           enabledPlugins.push(t("model.thinkSplitPlugin"));
         }
 
+        if (plugin["stream-fake"]?.enable) {
+          enabledPlugins.push(t("model.streamFakePlugin"));
+        }
+
         if (enabledPlugins.length === 0) {
           return (
             <div className="text-muted-foreground text-sm">

+ 6 - 0
web/src/types/model.ts

@@ -48,6 +48,7 @@ type Plugin = {
     cache: CachePlugin // 缓存插件
     "web-search": WebSearchPlugin // 网络搜索插件
     "think-split": ThinkSplitPlugin // 思考拆分插件
+    "stream-fake": StreamFakePlugin // 流式伪装插件
 }
 
 type CachePlugin = {
@@ -82,6 +83,10 @@ type ThinkSplitPlugin = {
     enable: boolean
 }
 
+type StreamFakePlugin = {
+    enable: boolean
+}
+
 type EngineConfig = {
     type: 'bing' | 'google' | 'arxiv' | 'searchxng'
     max_results?: number
@@ -115,6 +120,7 @@ export type {
     CachePlugin,
     WebSearchPlugin,
     ThinkSplitPlugin,
+    StreamFakePlugin,
     EngineConfig,
     GoogleSpec,
     BingSpec,

+ 3 - 0
web/src/validation/model.ts

@@ -64,6 +64,9 @@ const pluginSchema = z.object({
     "think-split": z.object({
         enable: z.boolean(),
     }).optional(),
+    "stream-fake": z.object({
+        enable: z.boolean(),
+    }).optional(),
 }).optional()
 
 export const modelCreateSchema = z.object({