Add dynamic variable support to Assistant model and related components
- Introduce dynamic variable definitions in AssistantConfig and Assistant models, allowing for flexible prompt customization. - Implement validation for dynamic variable names and types in the schema. - Update backend services and routes to handle dynamic variables in assistant configurations and runtime processing. - Enhance frontend components to support dynamic variable definitions, including a new editor for managing variables. - Add tests to ensure proper functionality and validation of dynamic variables in various scenarios.
This commit is contained in:
@@ -8,6 +8,7 @@ JSON 用 camelCase(modelId/interfaceType/apiUrl/apiKey),Python 内部用 snake_c
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
import re
|
||||
from typing import Annotated, Any, Literal, Union
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
||||
@@ -22,6 +23,7 @@ ToolType = Literal["end_call", "http"]
|
||||
ToolStatus = Literal["active", "archived", "draft"]
|
||||
ToolParameterType = Literal["string", "number", "integer", "boolean", "object", "array"]
|
||||
ToolParameterLocation = Literal["path", "query", "body", "header"]
|
||||
DynamicVariableType = Literal["string", "number", "boolean"]
|
||||
|
||||
# 外部应用类型:其 config.apiKey 是该助手私有密钥,读时打码 / 写时哨兵
|
||||
EXTERNAL_TYPES = {"dify", "fastgpt", "opencode"}
|
||||
@@ -106,12 +108,28 @@ class AssistantUpsert(CamelModel):
|
||||
|
||||
# 瘦类型专属(真列);按 type 取用,无关字段写入时清零
|
||||
prompt: str = ""
|
||||
dynamic_variable_definitions: dict[str, "DynamicVariableDefinition"] = Field(
|
||||
default_factory=dict
|
||||
)
|
||||
api_url: str = ""
|
||||
api_key: str = "" # 写时:占位符/空 → 保留旧(哨兵)
|
||||
app_id: str = ""
|
||||
# workflow 专属:图
|
||||
graph: dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
@field_validator("dynamic_variable_definitions")
|
||||
@classmethod
|
||||
def validate_dynamic_variable_names(cls, value):
|
||||
if len(value) > 50:
|
||||
raise ValueError("动态变量最多允许 50 个")
|
||||
for name in value:
|
||||
if (
|
||||
not re.fullmatch(r"[A-Za-z][A-Za-z0-9_]{0,63}", name)
|
||||
or name.startswith(("system__", "secret__"))
|
||||
):
|
||||
raise ValueError(f"动态变量名称不合法: {name}")
|
||||
return value
|
||||
|
||||
@model_validator(mode="after")
|
||||
def _strip_irrelevant_fields(self):
|
||||
allowed = ALLOWED_FIELDS[self.type]
|
||||
@@ -122,6 +140,7 @@ class AssistantUpsert(CamelModel):
|
||||
self.graph = {}
|
||||
if self.type != "prompt":
|
||||
self.tool_ids = []
|
||||
self.dynamic_variable_definitions = {}
|
||||
# 外部托管大脑只能 cascade,拦住不兼容的 realtime
|
||||
if self.runtime_mode == "realtime" and self.type not in REALTIME_CAPABLE_TYPES:
|
||||
raise ValueError(f"类型 {self.type} 不支持 realtime 运行模式")
|
||||
@@ -133,6 +152,29 @@ class AssistantOut(AssistantUpsert):
|
||||
updated_at: str | None = None
|
||||
|
||||
|
||||
class DynamicVariableDefinition(CamelModel):
|
||||
type: DynamicVariableType = "string"
|
||||
required: bool = False
|
||||
default: str | int | float | bool | None = None
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_default_type(self):
|
||||
if self.default is None:
|
||||
return self
|
||||
valid = (
|
||||
(self.type == "string" and isinstance(self.default, str))
|
||||
or (
|
||||
self.type == "number"
|
||||
and isinstance(self.default, (int, float))
|
||||
and not isinstance(self.default, bool)
|
||||
)
|
||||
or (self.type == "boolean" and isinstance(self.default, bool))
|
||||
)
|
||||
if not valid:
|
||||
raise ValueError(f"默认值类型应为 {self.type}")
|
||||
return self
|
||||
|
||||
|
||||
# ---------- 可复用工具 ----------
|
||||
class ToolParameter(CamelModel):
|
||||
name: str
|
||||
@@ -155,6 +197,7 @@ class HttpToolConfig(CamelModel):
|
||||
headers: dict[str, str] = Field(default_factory=dict)
|
||||
parameters: list[ToolParameter] = Field(default_factory=list)
|
||||
body: dict[str, Any] = Field(default_factory=dict)
|
||||
dynamic_variable_assignments: dict[str, str] = Field(default_factory=dict)
|
||||
|
||||
@field_validator("url")
|
||||
@classmethod
|
||||
|
||||
Reference in New Issue
Block a user