diff --git a/design/call/convert.md b/design/call/convert.md new file mode 100644 index 0000000000000000000000000000000000000000..6420d4af8ee0bc73543bbe4bc7aaedbd9f51ca25 --- /dev/null +++ b/design/call/convert.md @@ -0,0 +1,392 @@ +# Convert模块文档 + +## 1. 模块概述 + +Convert模块是欧拉助手框架中的一个核心工具,主要用于对生成的文字信息和原始数据进行格式化处理。该模块基于Jinja2模板引擎,支持灵活的模板语法,可以将各种数据转换为特定格式的文本或结构化数据,为系统中的数据展示和传递提供了强大的支持。 + +**主要功能特性:** +- 支持Jinja2模板语法的文本格式化 +- 支持JSON数据的模板渲染和解析 +- 提供多语言的工具名称和描述信息 +- 采用异步编程模式,支持流式输出 +- 集成了丰富的上下文变量,如时间、历史记录、问题等 + +## 2. 代码结构 + +Convert模块位于 `apps/scheduler/call/convert/` 目录下,包含以下三个主要文件: + +```text +apps/scheduler/call/convert/ +├── __init__.py # 模块初始化文件 +├── convert.py # 核心实现代码 +└── schema.py # 输入输出数据结构定义 +``` + +## 3. 核心类与方法 + +### 3.1 Convert类 + +`Convert` 类是模块的核心,继承自 `CoreCall` 基类,实现了模板转换的核心逻辑。 + +```python +class Convert(CoreCall, input_model=ConvertInput, output_model=ConvertOutput): + """Convert 工具,用于对生成的文字信息和原始数据进行格式化""" + text_template: str | None = Field(description="自然语言信息的格式化模板,jinja2语法", default=None) + data_template: str | None = Field(description="原始数据的格式化模板,jinja2语法", default=None) +``` + +### 3.2 主要属性 + +| 属性名 | 类型 | 默认值 | 描述 | +|--------|------|--------|------| +| `text_template` | str \| None | None | 自然语言信息的格式化模板,使用Jinja2语法 | +| `data_template` | str \| None | None | 原始数据的格式化模板,使用Jinja2语法 | + +### 3.3 主要方法 + +#### 3.3.1 info方法 + +**功能描述**:提供Convert工具的名称和描述信息,支持多语言国际化。 + +**主要特点**: +- 支持中英文两种语言切换 +- 返回标准的CallInfo对象,包含工具名称和功能描述 +- 中文版本名称为"模板转换",英文版本名称为"Convert" +- 描述信息说明了工具的核心功能:使用Jinja2语法格式化自然语言信息和原始数据 + +```python +@classmethod +def info(cls, language: LanguageType = LanguageType.CHINESE) -> CallInfo: + """返回Call的名称和描述""" + i18n_info = { + LanguageType.CHINESE: CallInfo( + name="模板转换", + description="使用jinja2语法将自然语言信息和原始数据进行格式化。", + ), + LanguageType.ENGLISH: CallInfo( + name="Convert", + description="Use jinja2 syntax to format natural language information and original data.", + ), + } + return i18n_info[language] +``` + +#### 3.3.2 _init方法 + +**功能描述**:初始化Convert工具,准备模板渲染所需的环境和变量。 + +**主要特点**: +- 继承自CoreCall基类并进行扩展 +- 创建SandboxedEnvironment环境以安全地执行模板 +- 收集和准备模板渲染所需的额外变量(如时间、历史记录、问题等) + +```python +async def _init(self, call_vars: CallVars) -> ConvertInput: + """初始化工具""" + await super()._init(call_vars) + + self._history = call_vars.step_data + self._question = call_vars.question + self._env = SandboxedEnvironment( + loader=BaseLoader(), + autoescape=False, + trim_blocks=True, + lstrip_blocks=True, + ) + + # 获取当前时间 + time = datetime.now(tz=pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S") + # 返回空的ConvertInput,因为输入数据来自上一步的输出 + self._extras = { + "time": time, + "history": self._history, + "question": self._question, + "background": self._sys_vars.background, + "ids": self._sys_vars.ids, + } + return ConvertInput( + text_template=self.text_template, + data_template=self.data_template, + extras=self._extras, + ) +``` + +#### 3.3.3 _exec方法 + +**功能描述**:执行模板转换操作,处理文本模板和数据模板,并流式返回结果。 + +**主要特点**: +- 分别处理文本模板和数据模板 +- 对模板渲染过程中的异常进行捕获和处理 +- 支持流式输出,分别返回文本和数据两种类型的结果 + +```python +async def _exec(self) -> AsyncGenerator[CallOutputChunk, None]: + """调用Convert工具""" + # 处理文本模板 + result_message = "" + if self.text_template is not None: + try: + text_template = self._env.from_string(self.text_template) + result_message = text_template.render(**self._extras) + except Exception as e: + raise CallError( + message=f"文本模板渲染错误: {e!s}", + data={ + "template": self.text_template, + "error": str(e), + }, + ) from e + else: + result_message = "未提供文本模板" + + # 处理数据模板 + result_data = {} + if self.data_template is not None: + try: + data_template = self._env.from_string(self.data_template) + rendered_data_str = data_template.render(**self._extras) + # 尝试解析为JSON对象 + result_data = json.loads(rendered_data_str) + except Exception as e: + raise CallError( + message=f"数据模板渲染错误: {e!s}", + data={ + "template": self.data_template, + "error": str(e), + }, + ) from e + else: + result_data = {"message": "未提供数据模板"} + + # 返回文本和数据两个部分 + yield CallOutputChunk( + type=CallOutputType.TEXT, + content=result_message, + ) + yield CallOutputChunk( + type=CallOutputType.DATA, + content=result_data, + ) +``` + +## 4. 数据结构 + +### 4.1 核心数据结构关系 + +```mermaid +classDiagram + class CoreCall { + +input_model + +output_model + +info() + +_init() + +_exec() + } + + class Convert { + +text_template: str | None + +data_template: str | None + +info() + +_init() + +_exec() + } + + class ConvertInput { + +text_template: str | None + +data_template: str | None + +extras: dict[str, Any] + } + + class ConvertOutput { + +text: str + +data: dict + } + + class CallVars { + +language: LanguageType + +ids: CallIds + +question: str + +step_data: dict[str, ExecutorHistory] + +step_order: list[str] + +background: ExecutorBackground + +thinking: str + } + + class CallOutputChunk { + +type: CallOutputType + +content: Any + } + + class SandboxedEnvironment { + +from_string() + } + + Convert --> CoreCall + Convert --> ConvertInput + Convert --> ConvertOutput + Convert --> CallVars + Convert --> CallOutputChunk + Convert --> SandboxedEnvironment + CallOutputChunk --> CallOutputType +``` + +### 4.2 详细字段说明 + +#### 4.2.1 ConvertInput 输入数据结构 + +| 字段名 | 类型 | 必需 | 说明 | 示例值 | +|--------|------|------|------|--------| +| `text_template` | `str \| None` | 否 | 自然语言信息的格式化模板,Jinja2语法 | `"当前时间:{{ time }}"` | +| `data_template` | `str \| None` | 否 | 原始数据的格式化模板,Jinja2语法 | `"{\"question\": \"{{ question }}\", \"time\": \"{{ time }}\"}"` | +| `extras` | `dict[str, Any]` | 是 | 模板渲染的额外变量 | `{"time": "2023-01-01 12:00:00", "question": "你好"}` | + +#### 4.2.2 ConvertOutput 输出数据结构 + +| 字段名 | 类型 | 必需 | 说明 | 示例值 | +|--------|------|------|------|--------| +| `text` | `str` | 是 | 格式化后的文字信息 | `"当前时间:2023-01-01 12:00:00"` | +| `data` | `dict` | 是 | 格式化后的结果数据 | `{"question": "你好", "time": "2023-01-01 12:00:00"}` | + +#### 4.2.3 CallVars 系统变量结构 + +| 字段名 | 类型 | 必需 | 说明 | 示例值 | +|--------|------|------|------|--------| +| `thinking` | `str` | 是 | 上下文思考信息 | `"用户想了解当前时间,我需要调用时间工具获取信息。"` | +| `question` | `str` | 是 | 改写后的用户输入问题 | `"现在几点了?"` | +| `step_data` | `dict[str, ExecutorHistory]` | 是 | 历史工具的结构化数据 | `{"time_tool": ExecutorHistory(...)` | +| `step_order` | `list[str]` | 是 | 历史工具的执行顺序 | `["time_tool", "llm"]` | +| `background` | `ExecutorBackground` | 是 | 执行器的背景信息 | `ExecutorBackground(...)` | +| `ids` | `CallIds` | 是 | 调用相关的ID信息 | `CallIds(...)` | +| `language` | `LanguageType` | 是 | 当前使用的语言类型 | `LanguageType.CHINESE` | + +## 5. 流程图与时序图 + +### 5.1 模块工作流程图 + +```mermaid +flowchart TD + A[开始] --> B[初始化Convert工具] + B --> C{是否提供文本模板?} + C -- 是 --> D[渲染文本模板] + C -- 否 --> E[设置默认文本] + D --> F{是否提供数据模板?} + E --> F + F -- 是 --> G[渲染数据模板] + F -- 否 --> H[设置默认数据] + G --> I[流式输出结果] + H --> I + I --> J[结束] + + subgraph 异常处理 + D -- 渲染错误 --> K[抛出文本模板错误] + G -- 渲染错误 --> L[抛出数据模板错误] + K --> M[返回错误信息] + L --> M + M --> J + end +``` + +### 5.2 模块调用时序图 + +```mermaid +sequenceDiagram + participant Executor as 执行器 + participant Convert as Convert模块 + participant Jinja2 as Jinja2模板引擎 + + Executor ->> Convert: 初始化工具(_init) + Convert -->> Executor: 返回ConvertInput + Executor ->> Convert: 执行工具(_exec) + + par 文本模板处理 + Convert ->> Jinja2: 创建文本模板(from_string) + Jinja2 -->> Convert: 返回模板对象 + Convert ->> Jinja2: 渲染模板(render) + Jinja2 -->> Convert: 返回渲染结果 + and 数据模板处理 + Convert ->> Jinja2: 创建数据模板(from_string) + Jinja2 -->> Convert: 返回模板对象 + Convert ->> Jinja2: 渲染模板(render) + Jinja2 -->> Convert: 返回渲染结果 + Convert ->> Convert: 解析JSON数据(json.loads) + end + + Convert -->> Executor: 流式返回文本结果(CallOutputChunk) + Convert -->> Executor: 流式返回数据结果(CallOutputChunk) +``` + +## 6. 输入输出示例 + +### 6.1 文本模板示例 + +**配置参数:** +```json +{ + "text_template": "用户的问题是:{{ question }}\n当前时间:{{ time }}\n历史步骤数:{{ history | length }}" +} +``` + +**输入数据(CallVars):** +```json +{ + "question": "什么是欧拉助手?", + "time": "2023-01-01 12:00:00", + "history": {"step1": {"result": "数据1"}, "step2": {"result": "数据2"}} +} +``` + +**输出结果(文本部分):** +``` +用户的问题是:什么是欧拉助手? +当前时间:2023-01-01 12:00:00 +历史步骤数:2 +``` + +### 6.2 数据模板示例 + +**配置参数:** +```json +{ + "data_template": "{\"question\": \"{{ question }}\", \"timestamp\": \"{{ time }}\", \"history_count\": {{ history | length }} }" +} +``` + +**输入数据(CallVars):** +```json +{ + "question": "什么是欧拉助手?", + "time": "2023-01-01 12:00:00", + "history": {"step1": {"result": "数据1"}, "step2": {"result": "数据2"}} +} +``` + +**输出结果(数据部分):** +```json +{ + "question": "什么是欧拉助手?", + "timestamp": "2023-01-01 12:00:00", + "history_count": 2 +} +``` + +## 7. 错误处理 + +Convert模块包含完善的错误处理机制,主要针对以下两种错误情况: + +1. **文本模板渲染错误**:当文本模板语法错误或渲染过程中出现异常时,会抛出包含详细错误信息的CallError异常。 +2. **数据模板渲染错误**:当数据模板语法错误、渲染过程中出现异常或渲染结果无法解析为JSON时,会抛出包含详细错误信息的CallError异常。 + +错误信息包含错误描述和相关上下文数据,有助于快速定位和解决问题。 + +## 8. 代码优化建议 + +1. **模板缓存机制**:对于频繁使用的模板,可以考虑添加缓存机制,避免重复解析模板字符串,提高性能。 + +2. **模板语法检查**:在初始化阶段,可以先对模板语法进行预检查,提前发现并报告语法错误,提高用户体验。 + +3. **数据类型安全**:在解析JSON数据时,可以添加更严格的数据类型验证,确保输出数据符合预期的格式和类型。 + +4. **自定义过滤器扩展**:可以考虑扩展Jinja2环境,添加自定义过滤器,提供更多数据处理和格式化能力。 + +5. **国际化支持增强**:当前的默认提示信息仅支持中文,可以考虑将其纳入多语言支持体系,根据系统语言自动切换。 \ No newline at end of file diff --git a/design/call/facts.md b/design/call/facts.md new file mode 100644 index 0000000000000000000000000000000000000000..d7a19483f473ca2dd7ba8e2d1e34c647c7dceafe --- /dev/null +++ b/design/call/facts.md @@ -0,0 +1,265 @@ +# Facts模块文档 + +## 概述 + +Facts模块是一个用于从对话上下文和文档片段中提取事实信息的工具。该模块通过分析用户与助手的对话内容,提取关键事实信息并生成用户画像标签,为推荐系统提供数据支持。 + +## 模块架构 + +```mermaid +graph TB + A[FactsCall] --> B[FactsInput] + A --> C[FactsOutput] + A --> D[CoreCall基类] + + B --> E[用户ID] + B --> F[对话消息] + + C --> G[提取的事实] + C --> H[领域标签] + + D --> I[LLM调用] + D --> J[模板渲染] + + A --> K[FactsGen] + A --> L[DomainGen] + + K --> M[事实列表] + L --> N[关键词列表] + + A --> O[UserTagManager] + O --> P[用户画像更新] +``` + +## 核心组件 + +### 1. FactsCall类 + +继承自`CoreCall`基类,是facts模块的核心实现类。 + +**主要属性:** + +- `answer: str` - 用户输入的回答内容 +- `input_model: FactsInput` - 输入数据模型 +- `output_model: FactsOutput` - 输出数据模型 + +**核心方法:** + +- `info()` - 返回模块的名称和描述(支持中英文) +- `instance()` - 创建模块实例 +- `_init()` - 初始化模块,组装输入数据 +- `_exec()` - 执行事实提取逻辑 +- `exec()` - 公共执行接口,处理输出格式 + +### 2. 数据结构 + +```mermaid +classDiagram + class DataBase { + <> + } + + class FactsInput { + +str user_sub + +list~dict~ message + } + + class FactsOutput { + +list~str~ facts + +list~str~ domain + } + + class FactsGen { + +list~str~ facts + } + + class DomainGen { + +list~str~ keywords + } + + DataBase <|-- FactsInput + DataBase <|-- FactsOutput + FactsGen -- FactsOutput : 生成 + DomainGen -- FactsOutput : 生成 + + note for FactsInput "用户ID和对话消息列表" + note for FactsOutput "包含提取的事实和领域标签" + note for FactsGen "LLM生成的事实条目" + note for DomainGen "LLM生成的关键词标签" +``` + +### 3. 提示词模板 + +#### 事实提取提示词 (FACTS_PROMPT) + +从对话中提取关键信息并组织成独特的事实条目: + +- **关注信息类型**:实体、偏好、关系、动作 +- **提取要求**:准确、清晰、简洁(少于30字) +- **输出格式**:JSON格式的事实列表 +- **语言支持**:中文/英文双语模板 + +#### 领域提取提示词 (DOMAIN_PROMPT) + +提取推荐系统所需的关键词标签: + +- **包含内容**:实体名词、技术术语、时间范围、地点、产品等 +- **标签要求**:精简、不重复、不超过10字 +- **输出格式**:JSON格式的关键词列表 +- **语言支持**:中文/英文双语模板 + +## 执行流程 + +```mermaid +sequenceDiagram + participant E as StepExecutor + participant F as FactsCall + participant L as LLM + participant U as UserTagManager + participant D as Database + + E->>F: 创建实例 + F->>F: 初始化输入数据 + F->>L: 调用事实提取 + L-->>F: 返回事实列表 + F->>L: 调用领域提取 + L-->>F: 返回关键词列表 + F->>U: 更新用户画像 + U->>D: 保存标签数据 + F-->>E: 返回提取结果 +``` + +## 处理逻辑 + +```mermaid +flowchart TD + A[开始] --> B[接收对话消息] + B --> C[创建Jinja2环境] + C --> D[渲染事实提取提示词] + D --> E[调用LLM提取事实] + E --> F[验证FactsGen结果] + F --> G[渲染领域提取提示词] + G --> H[调用LLM提取关键词] + H --> I[验证DomainGen结果] + I --> J[更新用户标签] + J --> K[组装输出数据] + K --> L[返回结果] + L --> M[结束] + + E --> N[LLM错误处理] + H --> O[LLM错误处理] + N --> M + O --> M +``` + +## 数据流图 + +```mermaid +graph LR + A[用户对话] --> B[FactsInput] + B --> C[消息处理] + C --> D[事实提取LLM] + C --> E[领域提取LLM] + + D --> F[FactsGen] + E --> G[DomainGen] + + F --> H[事实列表] + G --> I[关键词列表] + + H --> J[FactsOutput] + I --> J + I --> K[UserTagManager] + + K --> L[用户画像更新] + J --> M[任务运行时] + + subgraph "数据库" + N[Tag表] + O[UserTag表] + end + + K --> N + K --> O +``` + +## 用户画像更新机制 + +```mermaid +graph TB + A[提取关键词] --> B[查找Tag表] + B --> C{标签存在?} + C -->|是| D[查找UserTag记录] + C -->|否| E[记录错误日志] + + D --> F{用户标签记录存在?} + F -->|是| G[增加计数+1] + F -->|否| H[创建新记录count=1] + + G --> I[更新数据库] + H --> I + E --> J[跳过该标签] + + I --> K[完成] + J --> K +``` + +## 配置和依赖 + +### 依赖组件 + +- `CoreCall` - 基础调用框架 +- `UserTagManager` - 用户标签管理服务 +- `LLM` - 大语言模型服务 +- `Jinja2` - 模板渲染引擎 + +### 配置参数 + +- `language` - 语言类型(中文/英文) +- `autoescape` - 模板自动转义(false) +- `trim_blocks` - 去除块空白(true) +- `lstrip_blocks` - 去除行空白(true) + +## 使用示例 + +### 输入示例 + +```python +input_data = { + "user_sub": "user123", + "message": [ + {"role": "user", "content": "北京天气如何?"}, + {"role": "assistant", "content": "北京今天晴天,温度25度。"} + ] +} +``` + +### 输出示例 + +```python +output = { + "facts": ["北京今天天气晴朗", "北京今日温度25度"], + "domain": ["北京", "天气"] +} +``` + +## 错误处理 + +1. **LLM调用失败** - 记录错误日志,返回空结果 +2. **数据验证失败** - 抛出类型错误异常 +3. **标签不存在** - 记录错误日志,跳过该标签 +4. **数据库操作失败** - 抛出相应异常 + +## 性能考虑 + +- 使用异步生成器模式,支持流式输出 +- 模板渲染缓存,提高重复调用效率 +- 批量数据库操作,减少I/O开销 +- 错误恢复机制,保证系统稳定性 + +## 扩展性 + +- 支持多语言提示词模板 +- 可配置的事实提取规则 +- 可扩展的用户画像维度 +- 支持自定义输出格式 diff --git a/design/call/llm.md b/design/call/llm.md new file mode 100644 index 0000000000000000000000000000000000000000..3ac42ae3f270ec5f2c735520a8e54fdbab6fe75f --- /dev/null +++ b/design/call/llm.md @@ -0,0 +1,405 @@ +# LLM调用模块文档 + +## 1. 模块概述 + +LLM(Large Language Model)调用模块是欧拉助手框架中负责与大语言模型交互的核心组件。该模块提供了灵活的大模型调用能力,支持自定义系统提示词、用户提示词、历史对话记录等多种参数配置,可根据上下文信息和用户输入生成适当的大模型调用请求,并流式返回大模型的响应结果。 + +## 2. 代码结构 + +LLM调用模块位于 `apps/scheduler/call/llm/` 目录下,包含以下三个主要文件: + +```text +apps/scheduler/call/llm/ +├── __init__.py # 模块初始化文件 +├── llm.py # 核心实现代码 +├── prompt.py # 提示词模板定义 +└── schema.py # 输入输出数据结构定义 +``` + +## 3. 核心类与方法 + +### 3.1 LLM类 + +`LLM` 类是模块的核心,继承自 `CoreCall` 基类,实现了与大模型的交互逻辑。 + +```python +class LLM(CoreCall, input_model=LLMInput, output_model=LLMOutput): + """大模型调用工具""" + # 配置参数 + to_user: bool = Field(default=True) + temperature: float = Field(description="大模型温度(随机化程度)", default=0.7) + step_history_size: int = Field(description="上下文信息中包含的步骤历史数量", default=3, ge=0, le=10) + history_length: int = Field(description="历史对话记录数量", default=0, ge=0) + system_prompt: str = Field(description="大模型系统提示词", default="You are a helpful assistant.") + user_prompt: str = Field(description="大模型用户提示词", default=LLM_DEFAULT_PROMPT) +``` + +### 3.2 主要方法 + +#### 3.2.1 info方法 + +**功能描述**:提供LLM工具的名称和描述信息,支持多语言国际化。 + +**主要特点**: + +- 支持中英文两种语言切换 +- 返回标准的CallInfo对象,包含工具名称和功能描述 +- 中文版本名称为"大模型",英文版本名称为"LLM" +- 描述信息说明了工具的核心功能:使用指定提示词和上下文信息调用大模型 + +#### 3.2.2 _prepare_message方法 + +**功能描述**:准备输入给大模型的消息列表,是整个LLM调用流程的核心预处理方法。 + +**处理步骤**: + +1. **创建Jinja2模板环境**:用于后续的模板渲染 +2. **提取上下文信息**:从call_vars中获取最近几个步骤的历史数据 +3. **渲染上下文提示词**:使用LLM_CONTEXT_PROMPT模板,将AI思考过程和工具输出信息格式化 +4. **处理历史对话记录**:根据配置的history_length参数提取相关对话历史 +5. **渲染系统提示词**:使用Jinja2模板引擎处理系统提示词 +6. **渲染用户提示词**:将用户问题、上下文信息等参数注入用户提示词模板 +7. **构建消息列表**:按照标准格式组装完整的消息序列 + +**输出格式**:返回包含role和content字段的消息字典列表 + +#### 3.2.3 _init方法 + +**功能描述**:初始化LLM工具,准备调用所需的输入数据。 + +**执行流程**: + +- 接收CallVars参数,包含执行上下文信息 +- 调用_prepare_message方法生成消息列表 +- 将消息列表封装为LLMInput对象 +- 返回准备好的输入数据供后续执行使用 + +#### 3.2.4 _exec方法 + +**功能描述**:执行实际的大模型调用,并以流式方式返回处理结果。 + +**执行过程**: + +1. **数据验证**:将输入数据转换为LLMInput对象 +2. **大模型调用**:通过self._llm方法调用大模型API,启用流式模式 +3. **流式处理**:使用异步生成器逐块接收大模型返回的结果 +4. **结果转换**:将每个结果块封装为CallOutputChunk对象 +5. **异常处理**:捕获调用过程中的异常,并转换为标准的CallError异常 + +**输出特性**: + +- 采用流式输出,提高响应速度和用户体验 +- 每个输出块包含类型标识(TEXT)和内容 +- 自动过滤空结果块,确保输出质量 + +## 4. 提示词模板 + +LLM调用模块使用了两种主要的提示词模板,定义在`prompt.py`文件中: + +### 4.1 LLM_CONTEXT_PROMPT 上下文提示词模板 + +**功能说明**:用于提供AI思考过程和工具调用信息,帮助大模型理解上下文背景。 + +**主要特点**: + +- **多语言支持**:提供中英文两种语言版本 +- **结构化输出**:使用XML标签格式组织信息 +- **动态变量**:通过Jinja2模板引擎注入动态内容 +- **循环渲染**:支持多个工具输出的动态生成 + +**模板结构**: + +1. **思考过程部分**: + - 中文版:`以下是AI处理用户指令时所做的思考,在中给出:` + - 英文版:`The following is the thinking of the AI when processing the user's instruction, given in :` + - 使用 `{{ reasoning }}` 变量插入AI的思考内容 + +2. **工具调用说明部分**: + - 中文版:`你作为AI,在完成用户指令前,需要获取必要的信息。为此,你调用了一些工具,并获得了它们的输出:` + - 英文版:`As an AI, before completing the user's instruction, you need to obtain necessary information. For this purpose, you have called some tools and obtained their outputs:` + +3. **工具数据部分** (``): + - 使用 `{% for tool in context_data %}` 循环渲染多个工具的输出 + - 每个工具包含三个子元素: + - `{{ tool.step_name }}`:工具名称 + - `{{ tool.step_description }}`:工具描述 + - `{{ tool.output_data }}`:工具输出数据 + +### 4.2 LLM_DEFAULT_PROMPT 默认用户提示词模板 + +**功能说明**:默认的用户提示词模板,包含系统指令、用户问题和上下文信息的完整结构。 + +**主要特点**: + +- **角色定义**:明确定义AI助手的角色和行为准则 +- **时间感知**:提供当前时间信息作为时间参照 +- **上下文整合**:将用户问题和背景信息有机结合 +- **输出规范**:明确要求不包含XML标签,不编造信息 + +**模板结构**: + +1. **系统指令部分** (``): + - 定义AI助手的基本角色和职责 + - 提供当前时间信息(通过 `{{ time }}` 变量) + - 说明用户问题和背景信息的来源 + - 明确输出要求和注意事项 + +2. **用户问题部分** (``): + - 使用 `{{ question }}` 变量插入用户的具体问题 + - 提供清晰的问题展示格式 + +3. **上下文背景部分** (``): + - 使用 `{{ context }}` 变量插入相关的背景信息 + - 包含AI思考过程和工具调用结果 + +4. **输出引导**: + - 简洁地引导AI开始输出回答 + +## 5. 数据结构 + +### 5.1 类关系图 + +以下是LLM调用模块中使用的主要数据结构及其关系: + +```mermaid +classDiagram + %% 核心数据结构说明 + class DataBase { + +model_json_schema(override: dict[str, Any] | None = None, **kwargs: Any) -> dict[str, Any] + // 所有Call输入输出的基类,提供动态填充Schema的能力 + } + + class LLMInput { + +message: list[dict[str, str]] + // LLM工具调用的输入数据结构 + } + + class LLMOutput { + // LLM工具调用的输出数据结构(当前为空实现) + } + + class CallVars { + +thinking: str + +question: str + +step_data: dict[str, ExecutorHistory] + +step_order: list[str] + +background: ExecutorBackground + +ids: CallIds + +language: LanguageType + // 由Executor填充的系统变量,包含调用上下文信息 + } + + class ExecutorBackground { + +num: int + +conversation: list[dict[str, str]] + +facts: list[str] + // 执行器的背景信息 + } + + class CallIds { + +task_id: uuid.UUID + +executor_id: str + +session_id: str | None + +app_id: uuid.UUID | None + +user_sub: str + +conversation_id: uuid.UUID | None + // 调用相关的ID信息 + } + + class CallOutputChunk { + +type: CallOutputType + +content: str | dict[str, Any] + // LLM工具的流式输出数据结构 + } + + LLMInput --|> DataBase + LLMOutput --|> DataBase + CallVars --> ExecutorBackground + CallVars --> CallIds + LLM --> LLMInput + LLM --> LLMOutput + LLM --> CallVars + LLM --> CallOutputChunk +``` + +### 5.2 详细字段说明 + +#### 5.2.1 LLMInput 输入数据结构 + +| 字段名 | 类型 | 必需 | 说明 | 示例值 | +|--------|------|------|------|--------| +| `message` | `list[dict[str, str]]` | ✅ | 输入给大模型的消息列表,每条消息包含role和content字段 | `[{"role": "user", "content": "你好"}]` | + +**消息格式说明**: + +- `role`: 消息角色,通常为 `"system"`、`"user"` 或 `"assistant"` +- `content`: 消息内容,包含具体的文本信息 + +#### 5.2.2 CallVars 系统变量结构 + +| 字段名 | 类型 | 必需 | 说明 | 示例值 | +|--------|------|------|------|--------| +| `thinking` | `str` | ✅ | 上下文思考信息,包含AI的推理过程 | `"用户想了解天气情况,我需要调用天气工具获取信息。"` | +| `question` | `str` | ✅ | 改写后的用户输入问题 | `"今天北京的天气怎么样?"` | +| `step_data` | `dict[str, ExecutorHistory]` | ✅ | 历史工具的结构化数据字典,key为工具名称 | `{"weather": ExecutorHistory(...)}` | +| `step_order` | `list[str]` | ✅ | 历史工具的执行顺序列表 | `["weather", "llm"]` | +| `background` | `ExecutorBackground` | ✅ | 执行器的背景信息对象 | `ExecutorBackground(...)` | +| `ids` | `CallIds` | ✅ | 调用相关的ID信息对象 | `CallIds(...)` | +| `language` | `LanguageType` | ✅ | 当前使用的语言类型 | `LanguageType.CHINESE` | + +#### 5.2.3 ExecutorBackground 背景信息结构 + +| 字段名 | 类型 | 必需 | 说明 | 示例值 | +|--------|------|------|------|--------| +| `num` | `int` | ✅ | 对话记录最大数量限制 | `10` | +| `conversation` | `list[dict[str, str]]` | ✅ | 历史对话记录列表,每个元素包含role和content | `[{"role": "user", "content": "你好"}, {"role": "assistant", "content": "你好!有什么可以帮助您的吗?"}]` | +| `facts` | `list[str]` | ✅ | 当前执行器的背景事实信息列表 | `["用户位于北京", "当前时间是2024年"]` | + +#### 5.2.4 CallIds ID信息结构 + +| 字段名 | 类型 | 必需 | 说明 | 示例值 | +|--------|------|------|------|--------| +| `task_id` | `uuid.UUID` | ✅ | 当前任务的唯一标识符 | `123e4567-e89b-12d3-a456-426614174000` | +| `executor_id` | `str` | ✅ | Flow执行器的ID,对应Flow ID | `"flow_001"` | +| `session_id` | `str \| None` | ❌ | 用户会话ID,可能为空 | `"session_123"` 或 `None` | +| `app_id` | `uuid.UUID \| None` | ❌ | 应用ID,可能为空 | `123e4567-e89b-12d3-a456-426614174001` 或 `None` | +| `user_sub` | `str` | ✅ | 用户唯一标识符 | `"user_12345"` | +| `conversation_id` | `uuid.UUID \| None` | ❌ | 对话ID,可能为空 | `123e4567-e89b-12d3-a456-426614174002` 或 `None` | + +#### 5.2.5 CallOutputChunk 输出块结构 + +| 字段名 | 类型 | 必需 | 说明 | 示例值 | +|--------|------|------|------|--------| +| `type` | `CallOutputType` | ✅ | 输出类型枚举,标识输出内容类型 | `CallOutputType.TEXT` | +| `content` | `str \| dict[str, Any]` | ✅ | 输出内容,可以是文本字符串或结构化数据 | `"今天北京天气晴朗"` 或 `{"temperature": 25}` | + +**输出类型说明**: + +- `TEXT`: 文本类型输出 +- `DATA`: 结构化数据输出 +- `ERROR`: 错误信息输出 + +### 5.3 数据类型枚举 + +#### LanguageType 语言类型 + +- `CHINESE`: 中文 +- `ENGLISH`: 英文 + +#### CallOutputType 输出类型 + +- `TEXT`: 文本输出 +- `DATA`: 数据输出 +- `ERROR`: 错误输出 + +## 6. 调用流程图 + +以下是LLM调用模块的核心调用流程图,展示了从初始化到执行再到输出结果的完整过程: + +```mermaid +sequenceDiagram + participant Executor as 执行器 + participant LLM as LLM工具类 + participant Jinja2 as Jinja2模板引擎 + participant LLMProvider as 大模型提供商 + participant User as 用户 + + %% 初始化阶段 + Executor->>LLM: 实例化LLM工具 + LLM->>LLM: _init方法 + LLM->>LLM: _prepare_message方法 + LLM->>Jinja2: 渲染上下文提示词 + Jinja2-->>LLM: 返回渲染后的上下文 + LLM->>Jinja2: 渲染系统提示词 + Jinja2-->>LLM: 返回渲染后的系统提示词 + LLM->>Jinja2: 渲染用户提示词 + Jinja2-->>LLM: 返回渲染后的用户提示词 + LLM-->>Executor: 返回LLMInput + + %% 执行阶段 + Executor->>LLM: 调用exec方法 + LLM->>LLM: _exec方法 + LLM->>LLMProvider: 调用大模型API (streaming=True) + LLMProvider-->>LLM: 流式返回结果块 + + %% 输出阶段 + loop 处理流式输出 + LLM->>Executor: 生成CallOutputChunk + Executor->>User: 返回结果块给用户 + end + + %% 错误处理 + alt 发生错误 + LLM-->>Executor: 抛出CallError异常 + Executor-->>User: 返回错误信息 + end +``` + +## 7. 工作原理详解 + +### 7.1 消息准备流程 + +1. **获取上下文信息**:从`call_vars`中提取最近`step_history_size`个步骤的历史数据 +2. **渲染上下文提示词**:使用`LLM_CONTEXT_PROMPT`模板,插入AI思考过程和工具输出信息 +3. **处理历史对话**:从`background.conversation`中提取最近`history_length`条对话记录 +4. **准备格式化参数**:包括当前时间、上下文信息、用户问题等 +5. **渲染系统提示词和用户提示词**:使用Jinja2模板引擎将格式化参数应用到提示词中 +6. **构建消息列表**:按照历史消息、系统消息、用户消息的顺序构建完整的消息列表 + +### 7.2 大模型调用过程 + +1. **调用初始化**:`_init`方法被调用,准备LLMInput对象 +2. **执行调用**:`_exec`方法被调用,将消息列表发送给大模型 +3. **流式处理结果**:通过异步生成器流式接收大模型返回的结果块 +4. **转换输出格式**:将结果块转换为`CallOutputChunk`格式并输出 +5. **错误处理**:捕获并处理调用过程中可能出现的异常 + +## 8. 配置参数说明 + +| 参数名 | 类型 | 默认值 | 说明 | +|--------|------|--------|------| +| to_user | bool | True | 是否需要将输出返回给用户 | +| temperature | float | 0.7 | 大模型温度(随机化程度) | +| step_history_size | int | 3 | 上下文信息中包含的步骤历史数量(0-10) | +| history_length | int | 0 | 历史对话记录数量 | +| system_prompt | str | "You are a helpful assistant." | 大模型系统提示词 | +| user_prompt | str | LLM_DEFAULT_PROMPT | 大模型用户提示词 | + +## 9. 输入输出示例 + +### 9.1 输入示例 + +```json +{ + "temperature": 0.7, + "step_history_size": 3, + "history_length": 0, + "system_prompt": "You are a helpful assistant.", + "user_prompt": "\n 你是一个乐于助人的智能助手。请结合给出的背景信息, 回答用户的提问。\n 当前时间:{{ time }},可以作为时间参照。\n 用户的问题将在中给出,上下文背景信息将在中给出。\n 注意:输出不要包含任何XML标签,不要编造任何信息。若你认为用户提问与背景信息无关,请忽略背景信息直接作答。\n\n\n\n 今天北京的天气怎么样?\n\n\n\n 用户想了解天气情况,我需要调用天气工具获取信息。\n\n\n现在,输出你的回答:" +} +``` + +### 9.2 输出示例 + +```python +# 初始化后的LLMInput对象(简化表示) +LLMInput( + message=[ + { + "role": "system", + "content": "You are a helpful assistant." + }, + { + "role": "user", + "content": "\n 你是一个乐于助人的智能助手...\n \n \n 今天北京的天气怎么样?\n \n \n 无背景信息。\n \n 现在,输出你的回答:" + } + ] +) + +# 执行调用后,会流式返回类似以下内容 +"今天北京天气晴朗,气温25-32摄氏度,微风..." +``` + +## 10. 总结 + +LLM调用模块是欧拉助手框架中连接应用与大语言模型的关键桥梁。它通过灵活的配置参数和模板系统,支持根据不同场景构建合适的提示词,并以流式方式高效处理大模型的响应结果。该模块的设计使得开发者可以轻松集成各种大语言模型能力,并通过简单的配置定制化调用行为。 diff --git a/design/call/sql.md b/design/call/sql.md new file mode 100644 index 0000000000000000000000000000000000000000..cfcce7c30873fa4e51f716f30d996440e5615691 --- /dev/null +++ b/design/call/sql.md @@ -0,0 +1,287 @@ +# SQL模块文档 + +## 概述 + +SQL模块是Euler Copilot框架中的一个核心调用工具,用于通过自然语言查询生成SQL语句并执行数据库操作。该模块支持多种数据库类型,包括MySQL、MongoDB、PostgreSQL和OpenGauss。 + +## 功能特性 + +- **多数据库支持**: 支持MySQL、MongoDB、PostgreSQL、OpenGauss等多种数据库 +- **自然语言转SQL**: 通过外置的Chat2DB工具API,将用户问题转换为SQL语句 +- **异步执行**: 采用异步编程模式,支持流式输出 +- **错误处理**: 完善的异常处理和错误信息国际化 +- **配置灵活**: 支持动态配置数据库连接参数 + +## 类结构 + +### SQL类 + +继承自`CoreCall`基类,实现了SQL查询的核心功能。 + +#### 主要属性 + +| 属性名 | 类型 | 默认值 | 描述 | +|--------|------|--------|------| +| `database_type` | str | "postgres" | 数据库类型 | +| `host` | str | "localhost" | 数据库地址 | +| `port` | int | 5432 | 数据库端口 | +| `username` | str | "root" | 数据库用户名 | +| `password` | str | "root" | 数据库密码 | +| `database` | str | "postgres" | 数据库名称 | +| `table_name_list` | list[str] | [] | 表名列表 | + +### 数据结构 + +```mermaid +classDiagram + class DataBase { + <> + } + + class SQLInput { + +question: str + +Field(description="用户输入") + } + + class SQLOutput { + +result: list[dict[str, Any]] + +sql: str + +Field(description="SQL工具的执行结果") + +Field(description="SQL语句") + } + + DataBase <|-- SQLInput : 继承 + DataBase <|-- SQLOutput : 继承 + + note for SQLInput "SQL工具的输入数据结构
包含用户查询问题" + note for SQLOutput "SQL工具的输出数据结构
包含执行结果和SQL语句" +``` + +## 执行流程 + +```mermaid +flowchart TD + A[用户输入问题] --> B[初始化SQL工具] + B --> C[组装请求数据] + C --> D[调用Chat2DB API] + D --> E{API调用成功?} + E -->|是| F[解析返回结果] + E -->|否| G[记录错误日志] + F --> H[提取SQL语句和执行结果] + H --> I[构建输出数据] + I --> J[返回结果] + G --> K[抛出CallError异常] + + style A fill:#e1f5fe + style J fill:#c8e6c9 + style K fill:#ffcdd2 +``` + +## 时序图 + +```mermaid +sequenceDiagram + participant User as 用户 + participant StepExecutor as 步骤执行器 + participant SQL as SQL工具 + participant Chat2DB as Chat2DB API + participant DB as 数据库 + + User->>StepExecutor: 提交查询问题 + StepExecutor->>SQL: 创建SQL实例 + SQL->>SQL: 初始化(_init) + SQL->>StepExecutor: 返回SQLInput + + StepExecutor->>SQL: 执行(_exec) + SQL->>SQL: 组装请求数据 + SQL->>Chat2DB: POST /sql/handler + Chat2DB->>DB: 执行SQL查询 + DB-->>Chat2DB: 返回查询结果 + Chat2DB-->>SQL: 返回JSON响应 + + alt 调用成功 + SQL->>SQL: 解析结果数据 + SQL->>SQL: 构建SQLOutput + SQL-->>StepExecutor: 返回CallOutputChunk + StepExecutor-->>User: 返回查询结果 + else 调用失败 + SQL->>SQL: 记录错误日志 + SQL-->>StepExecutor: 抛出CallError + StepExecutor-->>User: 返回错误信息 + end +``` + +## 核心方法 + +### info() 类方法 + +返回Call的名称和描述信息,支持中英文国际化。 + +```python +@classmethod +def info(cls, language: LanguageType = LanguageType.CHINESE) -> CallInfo: + """返回Call的名称和描述""" +``` + +### _init() 方法 + +初始化SQL工具,从CallVars中提取用户问题。 + +```python +async def _init(self, call_vars: CallVars) -> SQLInput: + """初始化SQL工具""" + return SQLInput(question=call_vars.question) +``` + +### _exec() 方法 + +执行SQL查询的核心方法,包含以下步骤: + +1. **数据验证**: 将输入数据转换为SQLInput对象 +2. **请求组装**: 构建发送给Chat2DB API的请求数据 +3. **API调用**: 异步调用Chat2DB的/sql/handler端点 +4. **结果处理**: 解析API返回的JSON数据 +5. **输出构建**: 创建SQLOutput对象并返回 + +```python +async def _exec(self, input_data: dict[str, Any]) -> AsyncGenerator[CallOutputChunk, None]: + """运行SQL工具, 支持MySQL, MongoDB, PostgreSQL, OpenGauss""" +``` + +## API接口规范 + +### 请求格式 + +发送给Chat2DB API的请求数据结构: + +```json +{ + "type": "postgres", + "host": "localhost", + "port": 5432, + "username": "root", + "password": "root", + "database": "postgres", + "goal": "用户问题", + "table_list": ["表名1", "表名2"] +} +``` + +### 响应格式 + +Chat2DB API的响应数据结构: + +```json +{ + "code": 200, + "result": { + "sql": "SELECT * FROM users WHERE id = 1", + "execute_result": [ + {"id": 1, "name": "张三", "email": "zhangsan@example.com"} + ], + "risk": "低风险" + } +} +``` + +## 错误处理 + +### 异常类型 + +- **CallError**: 自定义异常类,用于处理SQL查询失败的情况 +- **httpx异常**: HTTP请求相关的异常 +- **JSON解析异常**: API响应解析失败 + +### 错误消息 + +支持中英文错误消息: + +```python +MESSAGE = { + "fail": { + LanguageType.CHINESE: "SQL查询错误:SQL语句执行失败!", + LanguageType.ENGLISH: "SQL query error: SQL statement execution failed!", + }, +} +``` + +## 配置要求 + +### 环境配置 + +需要在配置文件中设置Chat2DB API的URL: + +```toml +[extra] +sql_url = "http://chat2db-api:8080" +``` + +### 数据库配置 + +SQL工具支持以下数据库配置参数: + +- **数据库类型**: postgres, mysql, mongodb, opengauss +- **连接参数**: host, port, username, password, database +- **表名列表**: 可选的表名列表,用于限制查询范围 + +## 使用示例 + +### 基本用法 + +```python +# 创建SQL工具实例 +sql_tool = SQL( + database_type="postgres", + host="localhost", + port=5432, + username="postgres", + password="password", + database="mydb", + table_name_list=["users", "orders"] +) + +# 执行查询 +input_data = {"question": "查询所有用户信息"} +async for chunk in sql_tool._exec(input_data): + if chunk.type == CallOutputType.DATA: + result = chunk.content + print(f"SQL语句: {result['sql']}") + print(f"查询结果: {result['result']}") +``` + +### 在流程中使用 + +```yaml +steps: + - name: "sql_query" + type: "sql" + description: "查询用户数据" + config: + database_type: "postgres" + host: "db.example.com" + port: 5432 + username: "readonly_user" + password: "secure_password" + database: "analytics" + table_name_list: ["users", "user_profiles"] +``` + +## 性能、扩展性与安全考虑 + +### 性能考虑 + +- **超时设置**: HTTP请求超时时间设置为60秒,适用于大多数SQL查询场景 +- **异步处理**: 采用异步HTTP客户端(httpx.AsyncClient),支持流式输出,提高用户体验 +- **日志记录**: 详细记录SQL语句、执行结果和风险等级,便于问题排查和性能监控 + +### 扩展性 + +- **支持新的数据库类型**: 可以通过修改`database_type`字段支持新的数据库类型,前提是Chat2DB API支持该数据库 +- **自定义输出格式**: 可以通过继承`SQLOutput`类来扩展输出数据结构,添加更多元数据信息 +- **错误处理增强**: 可以在`_exec`方法中添加更细粒度的错误处理逻辑,针对不同类型的错误提供更具体的错误信息 + +### 安全考虑 + +- **SQL注入防护**: 依赖Chat2DB工具进行SQL注入防护,该工具会验证SQL语句的安全性、评估SQL执行的风险等级、提供风险提示信息 +- **数据库权限**: 建议使用具有最小权限的数据库用户,只授予必要的查询权限 +- **密码管理**: 数据库密码应通过安全的方式存储和传递,避免在日志中泄露敏感信息 diff --git a/design/call/summary.md b/design/call/summary.md new file mode 100644 index 0000000000000000000000000000000000000000..0a926b07ab77b60a2ec708937eb49c86f9efb878 --- /dev/null +++ b/design/call/summary.md @@ -0,0 +1,295 @@ +# Summary工具模块文档 + +## 概述 + +Summary工具是一个用于理解对话上下文的智能工具,它通过分析对话记录和关键事实,生成简洁的背景总结,为后续对话提供上下文理解支持。 + +## 功能特性 + +- **上下文理解**:分析对话记录和关键事实,生成三句话以内的背景总结 +- **多语言支持**:支持中文和英文两种语言 +- **模板化提示词**:使用Jinja2模板引擎动态生成提示词 +- **流式输出**:支持实时流式输出总结内容 +- **结构化数据**:基于Pydantic模型进行数据验证和序列化 + +## 核心组件 + +### 1. Summary类 + +Summary工具的核心实现类,继承自`CoreCall`基类。 + +```python +class Summary(CoreCall, input_model=DataBase, output_model=SummaryOutput): + """总结工具""" + + context: ExecutorBackground = Field(description="对话上下文") +``` + +**主要方法:** + +- `info()`: 返回工具的多语言名称和描述 +- `instance()`: 创建工具实例 +- `_init()`: 初始化工具输入 +- `_exec()`: 执行总结生成逻辑 +- `exec()`: 公共执行接口 + +### 2. 数据结构 + +Summary工具涉及多个数据模型,它们之间的关系如下: + +```mermaid +classDiagram + class DataBase { + <> + +model_json_schema() dict + } + + class SummaryOutput { + +summary: str + +Field(description="对问答上下文的总结内容") + } + + class ExecutorBackground { + +num: int + +conversation: list[dict[str, str]] + +facts: list[str] + +Field(description="对话记录最大数量", default=0) + +Field(description="对话记录", default=[]) + +Field(description="当前Executor的背景信息", default=[]) + } + + class Summary { + +context: ExecutorBackground + +Field(description="对话上下文") + +info() CallInfo + +instance() Self + +_init() DataBase + +_exec() AsyncGenerator + +exec() AsyncGenerator + } + + DataBase <|-- SummaryOutput : 继承 + Summary --> ExecutorBackground : 使用 + Summary --> SummaryOutput : 输出 + Summary --> DataBase : 输入 +``` + +#### 数据模型说明 + +- **DataBase**: 所有Call的输入基类,提供通用的数据验证和序列化功能 +- **SummaryOutput**: 继承自DataBase,包含总结内容的输出模型 +- **ExecutorBackground**: 执行器背景信息,包含对话记录和关键事实 +- **Summary**: 主要的工具类,使用ExecutorBackground作为上下文,输出SummaryOutput + +#### 数据流转关系 + +```mermaid +graph LR + A[ExecutorBackground] --> B[Summary工具] + B --> C[SummaryOutput] + C --> D[task.runtime.reasoning] + + subgraph "输入数据" + A1[num: 对话记录数量] + A2[conversation: 对话记录列表] + A3[facts: 关键事实列表] + end + + subgraph "处理过程" + B1[模板渲染] + B2[LLM推理] + end + + subgraph "输出数据" + C1[summary: 总结内容] + end + + A1 --> B1 + A2 --> B1 + A3 --> B1 + B1 --> B2 + B2 --> C1 + C1 --> D +``` + +### 3. 提示词模板 + +Summary工具使用Jinja2模板引擎生成提示词,支持中英文两种语言。模板设计遵循以下原则: + +- **结构化指令**:使用XML标签清晰分隔不同部分 +- **动态内容渲染**:通过Jinja2循环语法动态生成对话记录 +- **多语言适配**:根据系统语言自动选择合适的模板 +- **输出格式控制**:明确指定输出要求和限制 + +#### 提示词模板设计 + +Summary工具提供中英文两种语言的提示词模板,两种模板在结构和功能上保持一致,仅在语言表述上有所差异。模板设计包含以下核心要素: + +1. **任务说明**:明确要求生成三句话背景总结,用于后续对话的上下文理解 +2. **质量要求**:强调突出重要信息点(时间、地点、人物、事件等),确保信息准确性,不得编造信息 +3. **格式约束**:限制输出长度(少于3句话,少于300个字),不包含XML标签 +4. **数据源标识**:清晰标记对话记录和关键事实的来源,使用XML标签进行结构化组织 + +模板使用Jinja2语法进行动态渲染: + +- 通过循环语法动态生成对话记录,每个对话项包含角色和内容信息 +- 关键事实以列表形式呈现,支持多行显示 +- 根据系统语言自动选择合适的模板版本 + +这种设计确保了多语言环境下的正确显示和一致的用户体验。 + +## 工作流程 + +```mermaid +graph TD + A[开始] --> B[接收ExecutorBackground上下文] + B --> C[创建Jinja2模板环境] + C --> D[根据语言选择提示词模板] + D --> E[渲染模板生成完整提示词] + E --> F[调用LLM生成总结] + F --> G[流式输出总结内容] + G --> H[将总结保存到task.runtime.reasoning] + H --> I[结束] + + subgraph "数据流" + J[conversation: 对话记录] + K[facts: 关键事实] + L[language: 语言类型] + end + + J --> E + K --> E + L --> D +``` + +## 执行时序图 + +```mermaid +sequenceDiagram + participant E as StepExecutor + participant S as Summary + participant T as Jinja2Template + participant L as LLM + participant R as Runtime + + E->>S: instance(executor, node) + S->>S: _set_input(executor) + S->>S: _init(call_vars) + + E->>S: exec(executor, input_data) + S->>S: _exec(input_data) + S->>T: 创建SandboxedEnvironment + S->>T: 选择语言模板 + S->>T: render(conversation, facts) + T-->>S: 生成完整提示词 + + S->>L: 调用LLM生成总结 + L-->>S: 流式返回总结内容 + S->>R: 保存到task.runtime.reasoning + S-->>E: 返回CallOutputChunk +``` + +## 数据流图 + +```mermaid +graph LR + subgraph "输入数据" + A[ExecutorBackground] + A1[conversation: 对话记录] + A2[facts: 关键事实] + A3[num: 最大记录数] + end + + subgraph "处理过程" + B[Jinja2模板渲染] + C[LLM推理生成] + end + + subgraph "输出数据" + D[SummaryOutput] + D1[summary: 总结内容] + E[task.runtime.reasoning] + end + + A1 --> B + A2 --> B + A3 --> B + B --> C + C --> D1 + D1 --> E +``` + +## 使用示例 + +### 基本使用 + +```python +# 创建Summary工具实例 +summary_tool = await Summary.instance(executor, node) + +# 执行总结生成 +async for chunk in summary_tool.exec(executor, input_data): + print(chunk.content) # 输出总结内容 +``` + +### 上下文数据示例 + +```python +# ExecutorBackground数据结构示例 +context = ExecutorBackground( + num=10, + conversation=[ + {"role": "user", "content": "你好,我想了解Python编程"}, + {"role": "assistant", "content": "当然可以!Python是一门很受欢迎的编程语言..."}, + {"role": "user", "content": "能给我一些学习建议吗?"} + ], + facts=[ + "用户对Python编程感兴趣", + "用户希望获得学习建议", + "对话发生在2024年" + ] +) +``` + +## 配置参数 + +| 参数 | 类型 | 默认值 | 描述 | +|------|------|--------|------| +| `context` | ExecutorBackground | - | 对话上下文信息 | +| `to_user` | bool | False | 是否将输出返回给用户 | +| `enable_filling` | bool | False | 是否需要进行自动参数填充 | + +## 错误处理 + +Summary工具包含以下错误处理机制: + +1. **输出格式验证**:检查LLM输出是否为字符串格式 +2. **模板渲染错误**:Jinja2模板渲染异常处理 +3. **LLM调用异常**:大模型调用失败处理 + +## 性能与扩展性 + +### 性能考虑 + +Summary工具在性能方面进行了以下优化: + +- **流式输出**:支持实时流式输出,提升用户体验 +- **模板缓存**:Jinja2模板环境复用,减少重复创建开销 +- **内存优化**:及时释放不需要的中间数据 + +### 扩展性设计 + +Summary工具设计具有良好的扩展性: + +1. **多语言支持**:可轻松添加新的语言模板 +2. **模板定制**:支持自定义提示词模板 +3. **输出格式**:可扩展输出数据结构 +4. **集成接口**:基于CoreCall基类,易于集成到调度系统 + +## 依赖关系 + +- `CoreCall`: 基础调用框架 +- `Jinja2`: 模板引擎 +- `Pydantic`: 数据验证和序列化 +- `LLM`: 大语言模型接口 +- `ExecutorBackground`: 执行器背景信息 diff --git a/design/services/activity.md b/design/services/activity.md new file mode 100644 index 0000000000000000000000000000000000000000..6786b006034fb57f7d77cc4199782db74aed798a --- /dev/null +++ b/design/services/activity.md @@ -0,0 +1,317 @@ +# Activity模块设计文档 + +## 概述 + +Activity模块是Euler Copilot框架中的用户活动控制系统,负责管理系统的并发限制和用户限流。该模块实现了双重限流机制:单用户滑动窗口限流和全局并发任务限制,确保系统在高负载情况下的稳定性和公平性。 + +## 核心功能 + +- **全局并发控制**: 限制系统同时执行的任务数量,防止系统过载 +- **单用户限流**: 基于滑动窗口的用户请求频率限制 +- **活动状态管理**: 跟踪和管理用户活动状态 +- **资源保护**: 通过限流机制保护系统资源 + +## 数据模型 + +### SessionActivity实体 + +- **表名**: `framework_session_activity` +- **主键**: `id` (BigInteger, 自增) +- **字段**: + - `userSub`: 用户标识 (String(50), 外键关联framework_user.userSub) + - `timestamp`: 活动时间戳 (DateTime, 时区感知) + +### 相关实体 + +- **User**: 用户基础信息表 (`framework_user`) +- **Session**: 会话管理表 (`framework_session`) + +## 配置常量 + +- `MAX_CONCURRENT_TASKS`: 全局同时运行任务上限 (默认: 30) +- `SLIDE_WINDOW_TIME`: 滑动窗口时间 (默认: 15秒) +- `SLIDE_WINDOW_QUESTION_COUNT`: 滑动窗口内最大请求数 (默认: 5) + +## 服务层 + +### Activity类 + +#### 静态方法 + +- `is_active(user_sub)`: 检查系统是否达到并发上限 +- `set_active(user_sub)`: 设置用户活动状态 +- `remove_active(user_sub)`: 移除用户活动状态 + +## 时序图 + +```mermaid +sequenceDiagram + participant Client as 客户端 + participant Router as 路由层 + participant Activity as Activity服务 + participant DB as 数据库 + + Note over Client, DB: 用户请求处理流程 + Client->>Router: 发起请求 + Router->>Activity: is_active(user_sub) + + Note over Activity, DB: 滑动窗口限流检查 + Activity->>DB: SELECT COUNT(*) FROM framework_session_activity
WHERE userSub=? AND timestamp >= ? + DB-->>Activity: 返回用户窗口内请求数 + Activity->>Activity: 检查是否超过SLIDE_WINDOW_QUESTION_COUNT + + alt 用户请求数超限 + Activity-->>Router: 返回True (限流) + Router-->>Client: 返回429错误 + else 用户请求数正常 + Note over Activity, DB: 全局并发检查 + Activity->>DB: SELECT COUNT(*) FROM framework_session_activity + DB-->>Activity: 返回当前活跃任务数 + Activity->>Activity: 检查是否超过MAX_CONCURRENT_TASKS + + alt 全局并发超限 + Activity-->>Router: 返回True (限流) + Router-->>Client: 返回429错误 + else 系统可处理 + Activity-->>Router: 返回False (允许) + Router->>Activity: set_active(user_sub) + + Note over Activity, DB: 设置活动状态 + Activity->>DB: SELECT COUNT(*) FROM framework_session_activity + DB-->>Activity: 返回当前活跃任务数 + Activity->>Activity: 再次检查并发限制 + + alt 并发检查通过 + Activity->>DB: INSERT INTO framework_session_activity
(userSub, timestamp) + DB-->>Activity: 插入成功 + Activity-->>Router: 设置成功 + Router-->>Client: 处理请求 + + Note over Client, DB: 请求完成后清理 + Client->>Router: 请求完成 + Router->>Activity: remove_active(user_sub) + Activity->>DB: DELETE FROM framework_session_activity
WHERE userSub=? + DB-->>Activity: 删除成功 + Activity-->>Router: 清理完成 + else 并发检查失败 + Activity-->>Router: 抛出ActivityError + Router-->>Client: 返回503错误 + end + end + end +``` + +## ER图 + +```mermaid +erDiagram + User ||--o{ SessionActivity : "用户产生活动" + + User { + BigInteger id PK + string userSub UK "用户标识" + datetime lastLogin "最后登录时间" + boolean isActive "是否活跃" + boolean isWhitelisted "是否白名单" + integer credit "风控分" + string personalToken "个人令牌" + string functionLLM "函数模型ID" + string embeddingLLM "向量模型ID" + boolean autoExecute "自动执行" + } + + SessionActivity { + BigInteger id PK + string userSub FK "用户标识" + datetime timestamp "活动时间戳" + } + + Session { + string id PK "会话ID" + string userSub FK "用户标识" + string ip "IP地址" + string pluginId "插件ID" + string token "Token信息" + datetime validUntil "有效期" + enum sessionType "会话类型" + } +``` + +## 流程图 + +```mermaid +flowchart TD + A[用户请求] --> B[Activity.is_active检查] + + B --> C{滑动窗口限流检查} + C -->|超过限制| D[返回限流状态] + C -->|未超过| E{全局并发检查} + + E -->|超过限制| D + E -->|未超过| F[Activity.set_active] + + F --> G{并发再次检查} + G -->|检查失败| H[抛出ActivityError] + G -->|检查通过| I[插入活动记录] + + I --> J[处理用户请求] + J --> K[请求完成] + K --> L[Activity.remove_active] + L --> M[删除活动记录] + M --> N[释放资源] + + D --> O[返回429错误] + H --> P[返回503错误] + N --> Q[请求处理完成] + + style A fill:#e1f5fe + style Q fill:#c8e6c9 + style O fill:#ffcdd2 + style P fill:#ffcdd2 + style D fill:#fff3e0 + style H fill:#fff3e0 +``` + +## 限流机制详解 + +```mermaid +flowchart LR + subgraph "滑动窗口限流" + A[用户请求] --> B[检查15秒内请求数] + B --> C{请求数 >= 5?} + C -->|是| D[限流] + C -->|否| E[通过] + end + + subgraph "全局并发限流" + F[系统请求] --> G[检查当前活跃任务数] + G --> H{任务数 >= 30?} + H -->|是| I[限流] + H -->|否| J[通过] + end + + subgraph "双重检查机制" + K[set_active调用] --> L[插入前再次检查并发] + L --> M{并发检查通过?} + M -->|是| N[插入记录] + M -->|否| O[抛出异常] + end + + E --> F + J --> K + + style D fill:#ffcdd2 + style I fill:#ffcdd2 + style O fill:#ffcdd2 + style E fill:#c8e6c9 + style J fill:#c8e6c9 + style N fill:#c8e6c9 +``` + +## 数据流转图 + +```mermaid +flowchart LR + subgraph "请求层" + A[用户请求] + B[API调用] + end + + subgraph "控制层" + C[Activity服务] + D[限流检查] + E[并发控制] + end + + subgraph "数据层" + F[PostgreSQL] + G[SessionActivity表] + H[User表] + end + + subgraph "业务层" + I[业务处理] + J[资源释放] + end + + A --> B + B --> C + C --> D + D --> E + E --> F + F --> G + F --> H + + G -.->|活动记录| C + H -.->|用户信息| C + C -.->|限流结果| B + B -.->|处理请求| I + I -.->|完成通知| J + J -.->|清理活动| C + + style A fill:#e3f2fd + style C fill:#f3e5f5 + style F fill:#e8f5e8 + style I fill:#fff8e1 +``` + +## 异常处理 + +### ActivityError异常 + +- **触发条件**: 当系统并发已达上限时调用`set_active`方法 +- **错误信息**: "系统并发已达上限" +- **处理方式**: 向上层抛出异常,由路由层处理 + +## 安全考虑 + +1. **双重限流保护**: 用户级别和系统级别的双重限流机制 +2. **时间窗口控制**: 滑动窗口防止用户短时间内大量请求 +3. **并发限制**: 全局并发控制防止系统过载 +4. **资源及时释放**: 请求完成后及时清理活动记录 + +## 性能优化 + +1. **数据库索引**: userSub字段建立索引,提高查询效率 +2. **异步操作**: 所有数据库操作使用异步方式 +3. **连接池管理**: 使用数据库连接池管理连接 +4. **批量清理**: 可考虑定期清理过期的活动记录 + +## 监控指标 + +1. **并发任务数**: 实时监控当前活跃任务数量 +2. **限流触发次数**: 统计限流机制触发频率 +3. **用户请求频率**: 监控用户请求模式 +4. **系统响应时间**: 监控限流对系统性能的影响 + +## 扩展性 + +1. **动态配置**: 支持运行时调整限流参数 +2. **多级限流**: 可扩展支持更复杂的限流策略 +3. **限流策略**: 可扩展支持令牌桶、漏桶等算法 +4. **分布式限流**: 可扩展支持分布式环境下的限流控制 + +## 配置说明 + +```toml +# 活动控制配置 +MAX_CONCURRENT_TASKS = 30 # 全局并发任务上限 +SLIDE_WINDOW_TIME = 15 # 滑动窗口时间(秒) +SLIDE_WINDOW_QUESTION_COUNT = 5 # 窗口内最大请求数 +``` + +## 使用示例 + +```python +# 检查是否被限流 +if await Activity.is_active(user_sub): + raise HTTPException(status_code=429, detail="请求过于频繁") + +# 设置活动状态 +try: + await Activity.set_active(user_sub) + # 处理业务逻辑 +finally: + # 清理活动状态 + await Activity.remove_active(user_sub) +``` diff --git a/design/services/tag.md b/design/services/tag.md new file mode 100644 index 0000000000000000000000000000000000000000..21af2aa8fb5b8614331c3aaa0893e0e5fd6ba295 --- /dev/null +++ b/design/services/tag.md @@ -0,0 +1,275 @@ +# Tag模块设计文档 + +## 概述 + +Tag模块是Euler Copilot框架中的用户标签管理系统,用于管理用户分类标签的定义、创建、更新和删除操作。该模块支持标签的CRUD操作,并提供用户标签关联功能。 + +## 核心功能 + +- **标签管理**: 创建、查询、更新、删除标签 +- **用户标签关联**: 管理用户与标签的关联关系 +- **标签统计**: 统计标签使用频次 +- **权限控制**: 仅管理员可进行标签管理操作 + +## 数据模型 + +### Tag实体 + +- **表名**: `framework_tag` +- **主键**: `id` (BigInteger, 自增) +- **字段**: + - `name`: 标签名称 (String(255), 唯一索引) + - `definition`: 标签定义 (String(2000)) + - `updatedAt`: 更新时间 (DateTime, 时区感知) + +### UserTag关联实体 + +- **表名**: `framework_user_tag` +- **主键**: `id` (BigInteger, 自增) +- **字段**: + - `userSub`: 用户标识 (String(50), 外键关联framework_user.userSub) + - `tag`: 标签ID (BigInteger, 外键关联framework_tag.id) + - `count`: 标签使用频次 (Integer, 默认0) + +## API接口 + +### 管理接口 (需要管理员权限) + +#### GET /api/admin/tag + +- **功能**: 获取所有标签列表 +- **权限**: 管理员 +- **返回**: 标签信息列表 + +#### POST /api/admin/tag + +- **功能**: 添加或更新标签 +- **权限**: 管理员 +- **请求体**: `PostTagData` + - `tag`: 标签名称 + - `description`: 标签描述 +- **逻辑**: 如果标签不存在则创建,存在则更新 + +#### DELETE /api/admin/tag + +- **功能**: 删除标签 +- **权限**: 管理员 +- **请求体**: `PostTagData` +- **逻辑**: 根据标签名称删除对应标签 + +## 服务层 + +### TagManager类 + +#### 静态方法 + +- `get_all_tag()`: 获取所有标签 +- `get_tag_by_name(name)`: 根据名称获取标签 +- `get_tag_by_user_sub(user_sub)`: 获取用户的所有标签 +- `add_tag(data)`: 添加新标签 +- `update_tag_by_name(data)`: 更新标签定义 +- `delete_tag(data)`: 删除标签 + +## 时序图 + +```mermaid +sequenceDiagram + participant Client as 客户端 + participant Router as 路由层 + participant Service as TagManager + participant DB as 数据库 + + Note over Client, DB: 标签查询流程 + Client->>Router: GET /api/admin/tag + Router->>Service: get_all_tag() + Service->>DB: SELECT * FROM framework_tag + DB-->>Service: 返回标签列表 + Service-->>Router: 返回标签数据 + Router-->>Client: 返回JSON响应 + + Note over Client, DB: 标签创建/更新流程 + Client->>Router: POST /api/admin/tag + Router->>Service: update_tag_by_name(data) + Service->>DB: SELECT * FROM framework_tag WHERE name=? + DB-->>Service: 返回查询结果 + alt 标签不存在 + Service->>DB: INSERT INTO framework_tag + else 标签存在 + Service->>DB: UPDATE framework_tag SET definition=?, updatedAt=? + end + DB-->>Service: 操作完成 + Service-->>Router: 返回操作结果 + Router-->>Client: 返回成功响应 + + Note over Client, DB: 标签删除流程 + Client->>Router: DELETE /api/admin/tag + Router->>Service: delete_tag(data) + Service->>DB: SELECT * FROM framework_tag WHERE name=? + DB-->>Service: 返回查询结果 + alt 标签存在 + Service->>DB: DELETE FROM framework_tag WHERE id=? + DB-->>Service: 删除完成 + Service-->>Router: 删除成功 + else 标签不存在 + Service-->>Router: 抛出异常 + end + Router-->>Client: 返回响应结果 + + Note over Client, DB: 用户标签查询流程 + Client->>Router: GET /api/admin/tag?userSub=xxx + Router->>Service: get_tag_by_user_sub(user_sub) + Service->>DB: SELECT * FROM framework_user_tag WHERE userSub=? + DB-->>Service: 返回用户标签关联 + loop 遍历用户标签 + Service->>DB: SELECT * FROM framework_tag WHERE id=? + DB-->>Service: 返回标签详情 + end + Service-->>Router: 返回用户标签列表 + Router-->>Client: 返回JSON响应 +``` + +## ER图 + +```mermaid +erDiagram + User ||--o{ UserTag : "用户拥有标签" + Tag ||--o{ UserTag : "标签被用户使用" + + User { + BigInteger id PK + string userSub UK "用户标识" + datetime lastLogin "最后登录时间" + boolean isActive "是否活跃" + boolean isWhitelisted "是否白名单" + integer credit "风控分" + string personalToken "个人令牌" + string functionLLM "函数模型ID" + string embeddingLLM "向量模型ID" + boolean autoExecute "自动执行" + } + + Tag { + BigInteger id PK + string name UK "标签名称" + string definition "标签定义" + datetime updatedAt "更新时间" + } + + UserTag { + BigInteger id PK + string userSub FK "用户标识" + BigInteger tag FK "标签ID" + integer count "使用频次" + } +``` + +## 流程图 + +```mermaid +flowchart TD + A[客户端请求] --> B{权限验证} + B -->|验证失败| C[返回403错误] + B -->|验证成功| D{请求类型} + + D -->|GET| E[获取标签列表] + D -->|POST| F[创建/更新标签] + D -->|DELETE| G[删除标签] + + E --> H[TagManager.get_all_tag] + H --> I[查询framework_tag表] + I --> J[返回所有标签] + J --> K[返回JSON响应] + + F --> L[TagManager.update_tag_by_name] + L --> M{标签是否存在} + M -->|不存在| N[创建新标签] + M -->|存在| O[更新标签定义] + N --> P[INSERT操作] + O --> Q[UPDATE操作] + P --> R[返回成功响应] + Q --> R + + G --> S[TagManager.delete_tag] + S --> T{标签是否存在} + T -->|不存在| U[抛出异常] + T -->|存在| V[DELETE操作] + U --> W[返回错误响应] + V --> X[返回成功响应] + + style A fill:#e1f5fe + style K fill:#c8e6c9 + style R fill:#c8e6c9 + style X fill:#c8e6c9 + style C fill:#ffcdd2 + style U fill:#ffcdd2 + style W fill:#ffcdd2 +``` + +## 数据流转图 + +```mermaid +flowchart LR + subgraph "前端层" + A[管理界面] + B[API调用] + end + + subgraph "API层" + C[FastAPI Router] + D[权限验证] + E[请求验证] + end + + subgraph "服务层" + F[TagManager] + G[业务逻辑] + H[数据验证] + end + + subgraph "数据层" + I[PostgreSQL] + J[Tag表] + K[UserTag表] + end + + A --> B + B --> C + C --> D + D --> E + E --> F + F --> G + G --> H + H --> I + I --> J + I --> K + + J -.->|标签信息| K + K -.->|关联数据| F + F -.->|处理结果| C + C -.->|响应数据| A + + style A fill:#e3f2fd + style F fill:#f3e5f5 + style I fill:#e8f5e8 +``` + +## 安全考虑 + +1. **权限控制**: 所有标签管理操作需要管理员权限 +2. **数据验证**: 输入数据长度和格式验证 +3. **错误处理**: 完善的异常处理和错误信息返回 +4. **SQL注入防护**: 使用SQLAlchemy ORM防止SQL注入 + +## 性能优化 + +1. **索引优化**: 标签名称建立唯一索引,提高查询效率 +2. **连接池**: 使用数据库连接池管理连接 +3. **异步操作**: 所有数据库操作使用异步方式 +4. **缓存策略**: 可考虑对频繁查询的标签信息进行缓存 + +## 扩展性 + +1. **标签分类**: 可扩展支持标签分类和层级结构 +2. **标签权限**: 可扩展支持标签级别的权限控制 +3. **标签统计**: 可扩展更丰富的标签使用统计分析 +4. **批量操作**: 可扩展支持批量标签管理操作 diff --git a/manual/.gitignore b/manual/.gitignore deleted file mode 100644 index d16386367f7cd7dd3c1842c484239e9e82a25efc..0000000000000000000000000000000000000000 --- a/manual/.gitignore +++ /dev/null @@ -1 +0,0 @@ -build/ \ No newline at end of file diff --git a/manual/Makefile b/manual/Makefile deleted file mode 100644 index d0c3cbf1020d5c292abdedf27627c6abe25e2293..0000000000000000000000000000000000000000 --- a/manual/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = source -BUILDDIR = build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/manual/make.bat b/manual/make.bat deleted file mode 100644 index dc1312ab09ca6fb0267dee6b28a38e69c253631a..0000000000000000000000000000000000000000 --- a/manual/make.bat +++ /dev/null @@ -1,35 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=source -set BUILDDIR=build - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.https://www.sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "" goto help - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd diff --git a/manual/source/call/core.rst b/manual/source/call/core.rst deleted file mode 100644 index 3f9c339c9fd0180b6ff83042047eca859a3aaa71..0000000000000000000000000000000000000000 --- a/manual/source/call/core.rst +++ /dev/null @@ -1,9 +0,0 @@ -#### -基类 -#### - -.. automodule:: apps.scheduler.call.core - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/manual/source/call/empty.rst b/manual/source/call/empty.rst deleted file mode 100644 index 7e9899b2298c8c18f36332371de3a36b8ebf5563..0000000000000000000000000000000000000000 --- a/manual/source/call/empty.rst +++ /dev/null @@ -1,22 +0,0 @@ -###### -空节点 -###### - - -- 模块位置:``apps.scheduler.call.empty`` -- 模块名称:空白 -- 模块描述:无任何实际流程的工具,用于占位 -- 模块功能:无 -- 是否展示在前端:否 -- 是否存在参数重载:否 - - -**** -逻辑 -**** - -.. automodule:: apps.scheduler.call.empty - :members: - :private-members: - :undoc-members: - :show-inheritance: diff --git a/manual/source/call/index.rst b/manual/source/call/index.rst deleted file mode 100644 index 65484d2c9e3f2a93296822d04150f818a5f1bebd..0000000000000000000000000000000000000000 --- a/manual/source/call/index.rst +++ /dev/null @@ -1,17 +0,0 @@ -#### -工具 -#### - -工具(即 ``apps.scheduler.call`` )定义了工作流中节点的相关逻辑。 - -每一个子文件夹都对应了一个工具种类,均为无状态的Python程序代码。 - -并不是每一个工具都会以节点的形式展示在前端侧边栏内。如 ``slot`` 等工具是系统内部依工作流情况自动使用的工具,用户无法手动调用。 - - -.. toctree:: - :maxdepth: 2 - - core - mcp - empty diff --git a/manual/source/call/mcp.rst b/manual/source/call/mcp.rst deleted file mode 100644 index 383bc4677c1bf0bd35ca2ebdb25f8e477dae79b7..0000000000000000000000000000000000000000 --- a/manual/source/call/mcp.rst +++ /dev/null @@ -1,31 +0,0 @@ -####### -MCP节点 -####### - -- 模块位置:``apps.scheduler.call.mcp`` -- 模块名称:MCP -- 模块描述:调用MCP Server,执行工具 -- 模块功能: - - 调用特定MCP Server中的特定Tool -- 是否展示在前端:是 -- 是否存在参数重载:否 - -**** -逻辑 -**** - -.. automodule:: apps.scheduler.call.mcp.mcp - :members: - :private-members: - :undoc-members: - :show-inheritance: - -******** -输入输出 -******** - -.. automodule:: apps.scheduler.call.mcp.schema - :members: - :private-members: - :undoc-members: - :show-inheritance: diff --git a/manual/source/conf.py b/manual/source/conf.py deleted file mode 100644 index 0505fdb68743cf0cdad74ebdd8982a97aedb4865..0000000000000000000000000000000000000000 --- a/manual/source/conf.py +++ /dev/null @@ -1,34 +0,0 @@ -"""Sphinx configuration file for the openEuler Intelligence Framework.""" - -import sys -from pathlib import Path - -project = "openEuler Intelligence Framework" -copyright = "2025, Huawei Technologies Co., Ltd." # noqa: A001 -author = "sig-intelligence" -release = "0.10.0" - -extensions = [ - "sphinx.ext.autodoc", - "sphinxcontrib.autodoc_pydantic", - "sphinxcontrib.plantuml", -] - -templates_path = ["_templates"] -exclude_patterns = [] - -language = "zh_CN" -html_theme = "sphinx_rtd_theme" -html_static_path = ["_static"] - -autodoc_pydantic_model_show_config_summary = True -autodoc_pydantic_model_show_json = False -autodoc_pydantic_model_show_field_summary = True -autodoc_pydantic_field_show_default = True - -sys.path.insert(0, str(Path(__file__).resolve().parents[2])) - -plantuml_output_format = "svg" -plantuml = ( - r"java -jar C:\Users\ObjectNF\scoop\apps\plantuml\current\plantuml.jar" -) diff --git a/manual/source/index.rst b/manual/source/index.rst deleted file mode 100644 index 62bfa69b30872afe1de372a3808578ecb47345fa..0000000000000000000000000000000000000000 --- a/manual/source/index.rst +++ /dev/null @@ -1,11 +0,0 @@ -##################################### -openEuler Intelligence Framework 文档 -##################################### - -.. toctree:: - :maxdepth: 2 - - pool/index - models/index - call/index - service/index diff --git a/manual/source/models/index.rst b/manual/source/models/index.rst deleted file mode 100644 index f0e0f2cd734f0f23be9ddb34045c82633c11f473..0000000000000000000000000000000000000000 --- a/manual/source/models/index.rst +++ /dev/null @@ -1,13 +0,0 @@ -数据库读写模块 -=============== - -``apps.models`` 模块提供了数据库的读写功能,包括 LanceDB 数据库的读写、MongoDB 数据库的读写。 - -这一模块只包含了连接数据库和操作数据库的底层逻辑,不包含任何业务逻辑,也不包含数据库中数据的结构定义。 - - - -.. toctree:: - :maxdepth: 2 - - mongo diff --git a/manual/source/models/mongo.rst b/manual/source/models/mongo.rst deleted file mode 100644 index f26bd865c221b7e9d96b93292e9c5bbd7f3c98b2..0000000000000000000000000000000000000000 --- a/manual/source/models/mongo.rst +++ /dev/null @@ -1,25 +0,0 @@ -############## -MongoDB 数据库 -############## - -MongoDB是一个NoSQL数据库,以集合(``collection``)和文档(``document``)的形式存储和查询数据。 - -MongoDB有诸多优秀的特性,例如: - -- 轻量化,占用系统资源较少 -- 文档实际上就是JSON,可以动态增删字段 -- 对文档的读写等操作始终原子化 -- 支持丰富多样的查询方式 -- 支持像Redis一样设置数据的过期时间 -- 支持 ``replicaSet`` 模式,可以实现高可用,有一定的事务能力 - - -************** -MongoDB 连接器 -************** - -.. autoclass:: apps.models.mongo.MongoDB - :members: - :undoc-members: - :private-members: - :inherited-members: diff --git a/manual/source/pool/index.rst b/manual/source/pool/index.rst deleted file mode 100644 index 02ea7573e34d59367ef1c7c5305c9e83193fe497..0000000000000000000000000000000000000000 --- a/manual/source/pool/index.rst +++ /dev/null @@ -1,14 +0,0 @@ -###### -载入器 -###### - -载入器(即 ``apps.scheduler.pool.loader`` 模块)是用于从文件系统中加载资源,并将内存中的资源保存在文件系统中的模块。 - -载入器一般会在Framework启动时执行初始化动作。只有初始化全部结束后,Framework才会开始接受请求。 - - -.. toctree:: - :maxdepth: 2 - - mcp - pool diff --git a/manual/source/pool/mcp.rst b/manual/source/pool/mcp.rst deleted file mode 100644 index 0d0579584d8c24df057c7e2d9e345d53daed24fc..0000000000000000000000000000000000000000 --- a/manual/source/pool/mcp.rst +++ /dev/null @@ -1,66 +0,0 @@ -########### -MCP载入器 -########### - -MCP载入器(Loader)根据MCP配置文件(一般为 ``.json`` 格式),自动(或手动)创建MCP Server的运行环境,并启动MCP进程。 - -******** -数据结构 -******** - -.. automodule:: apps.entities.mcp - :members: - :undoc-members: - :show-inheritance: - - -****** -客户端 -****** - -客户端是直接与MCP Server进行交互的模块,负责发送请求和接收响应。 - - -客户端类 -======== - -.. automodule:: apps.scheduler.pool.mcp.client - :members: - :private-members: - :undoc-members: - :show-inheritance: - - -客户端默认值 -============ - -.. automodule:: apps.scheduler.pool.mcp.default - :members: - :private-members: - :undoc-members: - :show-inheritance: - - -客户端自动安装 -============== - -目前仅支持自动安装使用 ``uvx`` 和 ``npx`` 启动的MCP Server。 - -.. automodule:: apps.scheduler.pool.mcp.install - :members: - :private-members: - :undoc-members: - :show-inheritance: - - -****** -加载器 -****** - -加载器是负责加载MCP配置文件并更新数据库条目的模块。 - -.. autoclass:: apps.scheduler.pool.loader.mcp.MCPLoader - :members: - :undoc-members: - :private-members: - :show-inheritance: diff --git a/manual/source/pool/pool.rst b/manual/source/pool/pool.rst deleted file mode 100644 index 314642d64145881113520a1ac116792557500d31..0000000000000000000000000000000000000000 --- a/manual/source/pool/pool.rst +++ /dev/null @@ -1,9 +0,0 @@ -###### -资源池 -###### - -.. autoclass:: apps.scheduler.pool.pool.Pool - :members: - :undoc-members: - :private-members: - :inherited-members: diff --git a/manual/source/service/activity.rst b/manual/source/service/activity.rst deleted file mode 100644 index 0de41d1749950023b570f1532ccc37f8706cfe70..0000000000000000000000000000000000000000 --- a/manual/source/service/activity.rst +++ /dev/null @@ -1,118 +0,0 @@ -############################ -Activity 模块(限流与并发) -############################ - -.. currentmodule:: apps.services.activity - -概述 -==== - -``Activity`` 模块负责用户请求的限流与全局并发控制,提供以下能力: - -- 单用户滑动窗口限流:限制单个用户在指定时间窗口内的请求数量 -- 全局并发限制:控制系统同时执行的任务总数 -- 活动状态管理:提供活跃任务的登记与释放 -- 数据持久化:使用 PostgreSQL 持久化活动记录 - -核心常量 -======== - -以下常量由 ``apps.constants`` 提供,可通过配置调整: - -- ``MAX_CONCURRENT_TASKS``:全局同时运行任务上限(默认 30) -- ``SLIDE_WINDOW_QUESTION_COUNT``:滑动窗口内单用户最大请求数(默认 5) -- ``SLIDE_WINDOW_TIME``:滑动窗口时间(秒,默认 15) - -数据模型 -======== - -使用 ``SessionActivity`` 记录活跃行为: - -- ``id``:主键 ID(自增) -- ``userSub``:用户实体 ID(外键关联) -- ``timestamp``:活动时间戳(UTC) - -API 参考 -======== - -Activity 类 ------------ - -.. autoclass:: Activity - :members: - :undoc-members: - :show-inheritance: - -设计说明 -======== - -- 滑动窗口限流:统计用户在最近 ``SLIDE_WINDOW_TIME`` 秒内的请求数量,超过 ``SLIDE_WINDOW_QUESTION_COUNT`` 即判定限流。 -- 全局并发控制:通过统计 ``SessionActivity`` 的记录数判断是否达到 ``MAX_CONCURRENT_TASKS`` 上限。 -- 并发安全:依赖数据库事务保障登记与释放的原子性。 -- 时间精度:所有时间戳使用 UTC。 - -注意事项 -======== - -1. 在调用活跃登记前应先进行可用性检查。 -2. 任务完成后需及时释放活跃记录以避免占用并发额度。 -3. 合理调整常量以适配不同吞吐需求。 - - - -流程图(is_active) -=================== - -.. uml:: - - @startuml - title Activity.is_active 流程 - start - :获取当前 UTC 时间; - :开启数据库会话; - :统计 userSub 在 [now - SLIDE_WINDOW_TIME, now] 的请求数; - if (count >= SLIDE_WINDOW_QUESTION_COUNT?) then (是) - :返回 True (达到限流); - stop - else (否) - :统计当前活跃任务数量 current_active; - if (current_active >= MAX_CONCURRENT_TASKS?) then (是) - :返回 True (达到并发上限); - else (否) - :返回 False (可执行); - endif - endif - stop - @enduml - - -时序图(set_active/remove_active) -=================================== - -.. uml:: - - @startuml - title 活跃任务登记与释放时序 - actor Client - participant "Activity" as Activity - database "PostgreSQL" as PG - - == set_active == - Client -> Activity: set_active(user_sub) - Activity -> PG: 查询当前活跃数量 - PG --> Activity: current_active - alt 达到并发上限 - Activity -> Client: 抛出 ActivityError - else 未达上限 - Activity -> PG: merge SessionActivity(userSub, timestamp) - Activity -> PG: commit - Activity -> Client: 完成 - end - - == remove_active == - Client -> Activity: remove_active(user_sub) - Activity -> PG: delete SessionActivity where userSub=user_sub - Activity -> PG: commit - Activity -> Client: 完成 - - @enduml diff --git a/manual/source/service/index.rst b/manual/source/service/index.rst deleted file mode 100644 index 5cb76ac3380835b6a2a94b1976f03a4bd0ed5832..0000000000000000000000000000000000000000 --- a/manual/source/service/index.rst +++ /dev/null @@ -1,9 +0,0 @@ -######################## -服务模块文档(Service) -######################## - -.. toctree:: - :maxdepth: 2 - - activity - tag diff --git a/manual/source/service/tag.rst b/manual/source/service/tag.rst deleted file mode 100644 index 6f72c9f07a532fae7f2515f4b267216880bb68cf..0000000000000000000000000000000000000000 --- a/manual/source/service/tag.rst +++ /dev/null @@ -1,130 +0,0 @@ -######################## -Tag 模块(用户标签) -######################## - -.. currentmodule:: apps.services.tag - -概述 -==== - -``Tag`` 模块提供用户标签的增删改查能力,统一通过数据库会话访问 ``Tag`` 与 ``UserTag`` 两类模型,实现: - -- 获取全部标签 -- 按名称查询标签 -- 按用户 ``sub`` 查询其拥有的标签集合 -- 新增标签(若存在则合并) -- 按名称更新标签定义 -- 删除标签 - -依赖 -==== - -- 数据库会话:``apps.common.postgres.postgres.session`` (异步上下文) -- 数据模型:``apps.models.Tag``、``apps.models.UserTag`` -- 入参模型:``apps.schemas.request_data.PostTagData`` (字段:``tag``、``description``) - -API 参考 -======== - -TagManager 类 --------------- - -.. autoclass:: TagManager - :members: - :undoc-members: - :show-inheritance: - -设计说明 -======== - -- 读取路径:查询 ``Tag`` 表,或先查 ``UserTag`` 再关联回 ``Tag`` 表。 -- 写入路径:采用 ``session.merge`` 以便在新增/幂等更新间取得平衡。 -- 时间戳:更新时写入 ``updatedAt = datetime.now(tz=UTC)``。 -- 异常处理:更新/删除时若目标标签不存在,记录错误并抛出 ``ValueError``。 - -流程图(get_tag_by_user_sub) -============================= - -.. uml:: - - @startuml - title 通过 user_sub 查询用户标签流程 - start - :传入 user_sub; - :开启数据库会话; - :查询 UserTag where userSub = user_sub; - if (是否存在 user_tags?) then (是) - :遍历 user_tags; - :按 tag id 逐个查询 Tag; - :若 Tag 存在则加入结果列表; - else (否) - :返回空列表; - stop - endif - :返回标签结果列表; - stop - @enduml - -流程图(add/update/delete) -============================ - -.. uml:: - - @startuml - title 标签写操作流程(add / update / delete) - start - :开启数据库会话; - partition add_tag { - :构造 Tag(name=data.tag, definition=data.description); - :session.merge(tag); - :commit; - } - partition update_tag_by_name { - :按名称查询 Tag; - if (是否存在?) then (否) - :logger.error 并抛出 ValueError; - stop - else (是) - :更新 definition, updatedAt; - :session.merge(tag); - :commit 并返回 tag; - endif - } - partition delete_tag { - :按名称查询 Tag; - if (是否存在?) then (否) - :logger.error 并抛出 ValueError; - stop - else (是) - :session.delete(tag); - :commit; - endif - } - stop - @enduml - -时序图(get_tag_by_name / add_tag) -=================================== - -.. uml:: - - @startuml - title 查询与新增标签时序 - actor Client - participant "TagManager" as TM - database "PostgreSQL" as PG - - == get_tag_by_name == - Client -> TM: get_tag_by_name(name) - TM -> PG: SELECT Tag WHERE name = :name LIMIT 1 - PG --> TM: Tag | None - TM -> Client: 返回 Tag | None - - == add_tag == - Client -> TM: add_tag(PostTagData) - TM -> PG: MERGE Tag(name, definition) - TM -> PG: COMMIT - TM -> Client: 完成 - @enduml - -