目录
- 1. 项目概述
- 2. 架构设计
- 3. 核心 ORM 模型
- 4. Agent 运行时引擎
- 5. 工具系统
- 6. LLM 多供应商抽象层
- 7. 安全与防护体系
- 8. 记忆系统
- 9. RAG 知识检索
- 10. 用户界面
- 11. API 端点
- 12. 定时任务
- 13. 测试体系
- 14. 关键设计决策
- 15. 实现过程记录
- 16. 文件清单
- 17. 部署指南
1. 项目概述
1.1 背景
Odoo 19 企业版自带 AI 应用,提供基础的 AI Agent 能力(RAG、工具调用、LLM 集成)。但该内置系统存在以下局限:
- 缺乏自主多步骤规划能力
- 无法跨模块编排复杂工作流
- 不支持记忆持久化
- 没有真正的 Agent 行为模式(Reason-Act-Observe 循环)
- 仅限企业版
1.2 目标
构建一个 独立的 Odoo 19 插件模块 (agentic_ai),提供:
- 完全自主的跨模块 Agentic AI 能力
- 三种执行模式:ReAct、Plan-and-Execute、Hybrid(自动选择)
- 覆盖 Sales、Purchase、Inventory、Accounting、HR、Manufacturing 六大模块
- 多 LLM 供应商支持(OpenAI、Gemini、Ollama,可扩展)
- 安全护栏:确认流、速率限制、不可变审计日志
- RAG 知识集成(pgvector + NumPy 降级方案)
- 持久化记忆系统(episodic、semantic、procedural)
- 兼容 Odoo Community Edition,不依赖企业版 AI 模块
1.3 模块标识
| 属性 | 值 |
|---|---|
| 技术名称 | agentic_ai |
| 许可证 | LGPL-3(Community 兼容) |
| 依赖 | base, mail, web |
| Python 依赖 | httpx, numpy |
2. 架构设计
2.1 总体架构
用户消息
|
v
+-----------------------------------------------------------+
| AgentRuntime |
| |
| +----------+ +---------+ +------------------+ |
| | Planner |<-->| LLM |<-->| MemoryManager | |
| | | | Adapter | | | |
| +----+-----+ +---------+ +------------------+ |
| | |
| v |
| +----------+ +----------+ +------------------+ |
| | Executor |--->| Tools |--->| SafetyGuard | |
| | | | (ORM, | | (确认门控, | |
| | |<---| native) |<---| 速率限制) | |
| +----+-----+ +----------+ +------------------+ |
| | |
| v |
| +----------+ +------------------+ |
| | Observer |--->| ExecutionLogger | |
| +----------+ +------------------+ |
+-----------------------------------------------------------+
|
v
Agent 响应
2.2 模块目录结构
agentic_ai/ ├── __init__.py ├── __manifest__.py ├── models/ # 9 个 ORM 模型 │ ├── llm_provider.py # LLM 供应商配置 │ ├── agent.py # 核心 Agent 定义 │ ├── agent_tool.py # 工具注册与 Schema │ ├── agent_thread.py # 会话线程与消息 │ ├── agent_plan.py # 计划与步骤分解 │ ├── agent_memory.py # 持久化记忆 │ ├── agent_execution_log.py # 不可变审计日志 │ ├── agent_knowledge.py # RAG 知识源与分块 │ └── agent_safety_rule.py # 安全规则 ├── engine/ # 6 个运行时组件 │ ├── runtime.py # 主编排器(ReAct + Plan-and-Execute) │ ├── planner.py # 任务分解与规划 │ ├── executor.py # 工具执行调度 │ ├── observer.py # 结果格式化 │ ├── memory_manager.py # 记忆管理 │ └── safety.py # 安全护栏 ├── llm/ # LLM 适配层 │ ├── base.py # 抽象接口 │ ├── openai_adapter.py # OpenAI / Azure │ ├── gemini_adapter.py # Google Gemini │ ├── ollama_adapter.py # Ollama 本地 │ └── token_tracker.py # Token 计量 ├── tools/ # 28 个预置工具 │ ├── orm_tool.py # 通用 CRUD │ ├── sales_tools.py # 销售 (6 工具) │ ├── purchase_tools.py # 采购 (3 工具) │ ├── inventory_tools.py # 库存 (3 工具) │ ├── accounting_tools.py # 财务 (5 工具) │ ├── hr_tools.py # 人力 (3 工具) │ ├── manufacturing_tools.py # 制造 (3 工具) │ └── report_tool.py # 报表 (1 工具) ├── controllers/ # HTTP 端点 │ ├── chat_controller.py # JSON-RPC + SSE 流式 │ └── webhook_controller.py # 外部触发 Webhook ├── wizard/ │ └── agent_confirm_wizard.py # 危险操作确认向导 ├── views/ # 8 个视图文件 ├── security/ # 安全组 + ACL + 记录规则 ├── data/ # 预置数据 ├── static/src/ # OWL 前端组件 └── tests/ # 5 个测试文件
3. 核心 ORM 模型
3.1 agentic.ai.llm.provider -- LLM 供应商配置
文件: models/llm_provider.py
存储 LLM 后端配置。每条记录代表一个已配置的供应商端点。
| 字段 | 类型 | 说明 |
|---|---|---|
| name | Char (必填) | 显示名称 |
| provider_type | Selection | openai / gemini / ollama / anthropic / custom |
| api_base_url | Char | Base URL(ollama/custom 必填) |
| api_key | Char | API 密钥(仅 system 组可见) |
| default_model | Char (必填) | 模型标识,如 "gpt-4o" |
| max_tokens | Integer (默认 4096) | 最大输出 Token |
| temperature | Float (默认 0.1) | 温度参数 |
| supports_tool_calling | Boolean | 是否支持原生工具调用 |
| supports_streaming | Boolean | 是否支持流式响应 |
| cost_per_input_token | Float | 输入 Token 单价(USD) |
| cost_per_output_token | Float | 输出 Token 单价(USD) |
| rate_limit_rpm | Integer | 每分钟请求限制 |
| timeout_seconds | Integer (默认 120) | HTTP 超时 |
关键方法:
- _get_adapter() -- 根据 provider_type 实例化对应的 LLM 适配器
- action_test_connection() -- 测试 API 连通性
- _get_default_base_url() -- 获取/回退默认 URL
实现细节: 创建适配器时自动解析 extra_headers 和 extra_params(JSON 字段),遇到解析失败会优雅降级为空字典。Ollama 和 Custom 类型强制校验 api_base_url(通过 @api.constrains)。
3.2 agentic.ai.agent -- Agent 核心定义
文件: models/agent.py
每条记录定义一个完整的 AI Agent,包含 LLM 绑定、工具集、访问控制、执行策略。
| 字段 | 类型 | 说明 |
|---|---|---|
| name / code | Char | Agent 名称 / 唯一标识 |
| llm_provider_id | Many2one | 主 LLM 供应商 |
| fallback_provider_id | Many2one | 备用供应商 |
| system_prompt | Text | 系统提示词(支持 {current_date} {user_name} {company_name} 模板变量) |
| planning_prompt | Text | 规划专用提示词 |
| execution_mode | Selection | react / plan_and_execute / hybrid |
| max_iterations | Integer (默认 25) | ReAct 循环上限 |
| tool_ids | Many2many | 可用工具集 |
| allowed_model_ids / blocked_model_ids | Many2many | ORM 模型白名单/黑名单 |
| require_confirmation | Selection | never / destructive / always |
| user_ids / group_ids | Many2many | 允许使用的用户/组(空 = 全部) |
| sudo_user_id | Many2one | 以指定用户身份执行 ORM 操作 |
状态机: draft -> active <-> archived
关键方法:
- start_thread(initial_message) -- 创建会话线程
- run(thread_id, user_message) -- 主入口,触发 AgentRuntime
- _check_user_access(user) -- 检查用户是否有权使用此 Agent
- _get_available_tools() -- 解析工具集(含权限过滤)
- _build_system_message() -- 渲染系统提示词模板
- _get_execution_env() -- 获取执行环境(sudo 或用户 env)
3.3 agentic.ai.tool -- 工具注册
文件: models/agent_tool.py
工具注册表。支持四种执行类型:
| tool_type | 说明 | 示例 |
|---|---|---|
| native | 指向 Python 函数的 dotted path | agentic_ai.tools.sales_tools.create_quotation |
| orm_crud | 通用 CRUD 操作 | 通过 orm_tool.py 调度 |
| server_action | 关联 Odoo Server Action | ir.actions.server 记录 |
| python_code | 沙盒 Python 代码 | safe_eval 执行 |
JSON Schema 参数校验: parameter_schema 字段存储 JSON Schema,_validate_params() 方法验证:
- 必填字段检查
- 类型检查(string, integer, number, boolean, array, object)
- 枚举值检查
LLM Schema 转换: to_llm_schema() 生成 LLM 原生工具调用格式:
{
"name": "create_quotation",
"description": "Create a new sales quotation...",
"parameters": {
"type": "object",
"properties": { ... },
"required": [...]
}
}
3.4 agentic.ai.thread + agentic.ai.thread.message -- 会话管理
文件: models/agent_thread.py
线程管理会话生命周期,消息记录完整对话历史。
Thread 状态: active -> executing -> waiting_confirmation -> completed / error
Message 角色: user, assistant, system, tool_call, tool_result, confirmation_request, confirmation_response
关键方法:
- add_user_message() / add_assistant_message() -- 追加消息
- add_tool_result() -- 记录工具调用结果
- get_messages_for_llm() -- 序列化为 LLM 消息数组(含系统提示词注入)
- request_confirmation() -- 触发确认流程,线程暂停
- handle_confirmation(approved) -- 处理用户确认/拒绝
- _process_pending_tasks() -- Cron 任务:处理异步队列中的线程
3.5 agentic.ai.plan + agentic.ai.plan.step -- 执行计划
文件: models/agent_plan.py
Plan-and-Execute 模式下的任务分解。
Plan 状态: planning -> executing <-> replanning -> completed / failed / cancelled
Step 状态: pending -> running -> completed / failed / skipped
关键方法:
- get_current_step() -- 获取下一个待执行步骤
- get_progress_summary() -- 人类可读的进度摘要(含 checkbox 标记)
- is_complete() -- 检查计划是否完成(completed + skipped 均计入)
- progress -- 计算字段,返回完成百分比
3.6 agentic.ai.memory -- 持久化记忆
文件: models/agent_memory.py
三种记忆类型:
- episodic -- 事件记忆(对话摘要)
- semantic -- 语义记忆(用户偏好、业务事实)
- procedural -- 程序记忆(工作流模板)
三种作用域:thread(线程内)、user(用户级)、global(全局)
关键方法:
- store() -- 创建或更新(同 key 覆盖)
- recall() -- 混合关键词匹配 + 重要性 + 时间衰减 的检索
- forget_expired() -- Cron:清理过期记忆
3.7 agentic.ai.execution.log -- 审计日志
文件: models/agent_execution_log.py
不可变审计日志,记录 Agent 的每个动作。
action_type: llm_call, tool_execution, orm_operation, confirmation_request, confirmation_response, error, plan_generated, plan_revised
关键方法:
- log() -- 工厂方法,使用 sudo() 保证写入
- get_thread_timeline() -- 线程完整时间线
- get_cost_report() -- 成本汇总报表
- _cron_purge_old_logs(days) -- 定期清理旧日志
3.8 agentic.ai.knowledge.source + agentic.ai.knowledge.chunk -- RAG 知识
文件: models/agent_knowledge.py
Source 类型: file(PDF/DOCX/TXT/CSV)、url、odoo_model、text
索引管线: _extract_text() -> _chunk_text() -> _embed_chunks()
向量搜索: search_similar() 自动检测 pgvector 扩展,有则使用原生 SQL 余弦相似度,否则降级为 NumPy 计算。
3.9 agentic.ai.safety.rule -- 安全规则
文件: models/agent_safety_rule.py
在 Odoo 原生安全之上的额外权限层:
| 字段 | 说明 |
|---|---|
| rule_type | whitelist(允许) / blacklist(拒绝) |
| scope | model / operation / tool / field |
| model_name | 目标模型(支持 * 通配符) |
| operation | read / create / write / unlink / * |
| tool_name | 特定工具名称 |
| user_ids / group_ids | 规则适用对象(空 = 所有人) |
预装 8 条黑名单规则:禁止删除公司、禁止操作系统参数、禁止模块安装、禁止删除已过账凭证、禁止修改用户密码、禁止修改 Cron、禁止修改 ACL、禁止修改记录规则。
4. Agent 运行时引擎
4.1 AgentRuntime(engine/runtime.py)
主编排器,每次请求实例化。核心方法 run(user_message) 根据 Agent 的 execution_mode 分发到三种模式。
初始化时创建:SafetyGuard、Executor、Observer、Planner、MemoryManager、TokenTracker
4.2 模式一:ReAct(Reason-Act-Observe)
1. 添加用户消息到线程
2. 注入记忆 + RAG 上下文到系统提示词
3. 构建工具 Schema 列表
4. 循环 (最多 max_iterations 次):
a. 调用 LLM(完整消息历史 + 工具 Schema)
b. 若响应为纯文本(无工具调用)-> 返回给用户
c. 若响应包含 tool_call:
i. 查找工具 -> 未知工具则返回错误观察
ii. Executor.execute() -> SafetyGuard -> 执行
iii. 若需确认 -> 暂停线程, 返回确认描述
iv. Observer.observe() -> 格式化结果
v. 记录 tool_call + tool_result 到线程
5. 达到迭代上限 -> 返回"已达处理限制"提示
6. MemoryManager.consolidate() -> 提取长期记忆
4.3 模式二:Plan-and-Execute
1. 记忆 + RAG 上下文 2. Planner.generate_plan() -> 创建计划记录 + 步骤 3. 通知用户计划内容 4. 逐步执行: a. Planner.refine_step() -> 确定精确工具和参数 b. Executor.execute() c. 若需确认 -> 暂停 d. 成功 -> 记录结果, 推进下一步 e. 失败 -> Planner.replan()(最多 max_replanning 次) 5. 完成 -> Planner.synthesize_result() -> LLM 生成总结 6. 部分完成 -> 返回进度摘要
4.4 模式三:Hybrid(推荐默认)
Planner.assess_complexity(user_message) -> 'simple' | 'complex' - 关键词启发式: "and then", "first", "multiple", "batch" 等 -> complex - 消息长度 > 50 词 -> complex - simple -> ReAct - complex -> Plan-and-Execute
4.5 LLM 调用容错
def _call_llm(messages, tool_schemas):
adapters = [primary_adapter, fallback_adapter] # 备用链
for adapter in adapters:
for attempt in range(2): # 每个适配器最多重试 2 次
try:
return adapter.chat_completion(...)
except Exception:
time.sleep(1) # 退避
return None # 全部失败
4.6 Executor(engine/executor.py)
完整执行管线:
validate_params -> safety_check -> sanitize_params -> get_exec_env -> (read_only ? direct : savepoint) -> execute -> log
ExecutionResult 数据类封装结果:success, data, error, duration_ms, confirmation_needed, confirmation_reason
4.7 Observer(engine/observer.py)
将工具执行结果格式化为 LLM 可理解的观察文本:
- 搜索结果:显示前 10 条 + 总数
- 创建结果:Created record: {display_name} (ID: {id})
- 错误结果:含诊断提示(如"记录可能已删除"、"缺少必填字段")
- 自动截断超过 4000 字符的结果
4.8 Planner(engine/planner.py)
- assess_complexity() -- 关键词启发式复杂度评估
- generate_plan() -- LLM 生成 JSON 步骤数组 -> 创建 Plan + Step 记录
- refine_step() -- 执行时 LLM 确定精确工具和参数
- replan() -- 步骤失败后重新规划剩余步骤
- synthesize_result() -- LLM 汇总计划执行结果
- _parse_plan_response() -- 从 LLM 响应中提取 JSON 数组(含降级处理)
4.9 MemoryManager(engine/memory_manager.py)
- inject_memories() -- 检索相关记忆,格式化为上下文块注入系统提示词
- inject_rag_context() -- 嵌入查询 -> 向量搜索 -> 格式化知识块(含关键词搜索降级)
- consolidate() -- 线程完成后 LLM 提取关键事实,存入长期记忆
5. 工具系统
5.1 通用 ORM 工具(tools/orm_tool.py)
5 个通用工具给予 Agent 对任意 Odoo 模型的访问能力:
| 工具 | 参数 | 风险 | 说明 |
|---|---|---|---|
| odoo_search_read | model, domain, fields, limit | low | 搜索记录 |
| odoo_create | model, values | medium | 创建记录 |
| odoo_write | model, record_ids, values | medium | 更新记录 |
| odoo_unlink | model, record_ids | high | 删除记录 |
| odoo_method_call | model, record_ids, method | variable | 调用白名单方法 |
方法白名单(ALLOWED_METHODS):
{
'sale.order': ['action_confirm', 'action_cancel', 'action_draft', 'action_unlock'],
'purchase.order': ['button_confirm', 'button_approve', 'button_cancel', 'button_draft'],
'account.move': ['action_post', 'button_draft', 'button_cancel'],
'stock.picking': ['action_confirm', 'action_assign', 'button_validate'],
'mrp.production': ['action_confirm', 'button_mark_done', 'action_cancel'],
'hr.leave': ['action_approve', 'action_refuse', 'action_draft'],
'crm.lead': ['action_set_won', 'action_set_lost'],
}
另有 odoo_get_model_info(模型字段自省)和 odoo_get_available_models(模型列表查询)用于 Agent 自主探索数据结构。
5.2 领域专用工具
Sales(tools/sales_tools.py)-- 6 个工具
| 工具 | 风险 | 说明 |
|---|---|---|
| create_quotation | medium | 创建报价单(含订单行) |
| confirm_sale_order | high | 确认销售订单 |
| get_customer_history | low | 客户历史:订单数、收入、近期订单 |
| get_sales_pipeline_summary | low | CRM 管道统计(按阶段分组) |
| create_lead | medium | 创建线索/商机 |
| apply_discount | medium | 批量应用折扣 |
Purchase(tools/purchase_tools.py)-- 3 个工具
| 工具 | 风险 | 说明 |
|---|---|---|
| create_purchase_order | medium | 创建采购订单 |
| approve_purchase_order | high | 审批采购订单 |
| get_supplier_pricing | low | 供应商报价查询 |
Inventory(tools/inventory_tools.py)-- 3 个工具
| 工具 | 风险 | 说明 |
|---|---|---|
| check_stock_levels | low | 在手/可用/在途/出库库存 |
| create_internal_transfer | high | 创建内部调拨 |
| get_stock_valuation | low | 库存估值 |
Accounting(tools/accounting_tools.py)-- 5 个工具
| 工具 | 风险 | 说明 |
|---|---|---|
| create_invoice | medium | 创建发票(草稿) |
| post_invoice | high | 过账发票 |
| register_payment | high | 登记付款 |
| get_account_balance | low | 科目余额查询 |
| get_profit_loss | low | 利润表摘要 |
HR(tools/hr_tools.py)-- 3 个工具
| 工具 | 风险 | 说明 |
|---|---|---|
| search_employees | low | 搜索员工 |
| create_leave_request | medium | 创建请假申请 |
| get_attendance_summary | low | 考勤汇总 |
Manufacturing(tools/manufacturing_tools.py)-- 3 个工具
| 工具 | 风险 | 说明 |
|---|---|---|
| create_manufacturing_order | medium | 创建生产订单 |
| check_bom_availability | low | BOM 组件可用性 |
| get_production_schedule | low | 生产计划 |
Report(tools/report_tool.py)-- 1 个工具
| 工具 | 风险 | 说明 |
|---|---|---|
| generate_summary_report | low | 多类型汇总报表 |
6. LLM 多供应商抽象层
6.1 抽象接口(llm/base.py)
class BaseLLMAdapter(ABC):
def chat_completion(messages, tools, ...) -> LLMResponse
def chat_completion_stream(messages, tools) -> Generator[LLMStreamChunk]
def embed(texts: list) -> list[list[float]]
def count_tokens(text: str) -> int
@dataclass
class LLMResponse:
content: str | None
tool_calls: list[ToolCall]
input_tokens: int
output_tokens: int
model: str
finish_reason: str
@dataclass
class ToolCall:
id: str
name: str
arguments: dict
6.2 OpenAI 适配器(llm/openai_adapter.py)
- 基于 httpx 的 Chat Completions API
- 支持 Azure OpenAI(自定义 base_url + api_version)
- tiktoken 精确 Token 计数
- 工具 Schema 转换为 {"type": "function", "function": {...}} 格式
- SSE 流式响应解析
6.3 Gemini 适配器(llm/gemini_adapter.py)
- Google Generative AI REST API
- 消息格式转换:role: assistant -> role: model
- 工具调用:functionDeclarations + functionCall / functionResponse
- 换行分隔 JSON 流式解析
6.4 Ollama 适配器(llm/ollama_adapter.py)
- 通过 OpenAI 兼容 API 调用本地 Ollama 实例
- 非原生工具调用模型降级为提示词工具调用
- 正则解析文本输出中的 <tool_call> 标签
- 嵌入功能不可用时优雅降级
6.5 Token 跟踪(llm/token_tracker.py)
TokenTracker 类累计跟踪 Token 使用和成本:
- track(input_tokens, output_tokens, model) -- 记录单次调用
- get_summary() -- 汇总:total_input_tokens, total_output_tokens, total_cost, call_count
- check_budget(max_cost, max_tokens) -- 预算检查
7. 安全与防护体系
7.1 Odoo 安全组
| 组 | XML ID | 权限 |
|---|---|---|
| AI 用户 | group_agentic_ai_user | 使用 Agent 对话,查看自己的线程 |
| AI 操作员 | group_agentic_ai_operator | 配置 Agent、工具、知识源 |
| AI 管理员 | group_agentic_ai_admin | 管理供应商、安全规则、查看所有日志 |
ACL:30 条模型级别访问控制规则。
记录规则:
- 线程隔离:用户仅看到自己的线程(Operator/Admin 除外)
- 执行日志隔离:用户仅看到自己的日志
- 多公司过滤
7.2 SafetyGuard 检查链(engine/safety.py)
check(tool, params) -> ALLOW | CONFIRM_REQUIRED | DENY 检查顺序: 1. _check_safety_rules() -- 遍历 agentic.ai.safety.rule 记录 2. _check_model_access() -- Agent 级别模型白名单/黑名单 3. _check_rate_limit() -- 每分钟/小时/日成本限制 4. _check_confirmation_needed() -- 工具/Agent 级确认要求
7.3 确认流程
- SafetyGuard 返回 CONFIRM_REQUIRED
- 线程状态变更为 waiting_confirmation
- 前端显示确认卡片:操作描述 + 批准/拒绝按钮
- 批准:恢复执行
- 拒绝:Agent 收到 [CONFIRMATION_REJECTED],推理替代方案
确认向导(wizard/agent_confirm_wizard.py):标准 Odoo TransientModel 表单,显示工具名、参数、风险级别,支持填写拒绝理由。
7.4 事务安全
- 写/删操作包裹在 env.cr.savepoint() 中
- 成功:释放 savepoint
- 失败:回滚到 savepoint
- 审计日志记录 before_snapshot(用于潜在的撤销操作)
7.5 速率限制
| 配置 | 默认值 | 检查方式 |
|---|---|---|
| max_requests_per_minute | 20 | 查询最近 1 分钟日志计数 |
| max_requests_per_hour | 200 | 查询最近 1 小时日志计数 |
| max_cost_per_day | $50 | 汇总最近 24 小时日志成本 |
8. 记忆系统
8.1 三层记忆架构
| 层级 | memory_type | 存储内容 | 生命周期 |
|---|---|---|---|
| 短期 | episodic | 会话摘要、交互事件 | 有 TTL,可过期 |
| 长期 | semantic | 用户偏好、业务事实 | 持久化,重要性衰减 |
| 程序性 | procedural | 工作流模板、操作模式 | 持久化 |
8.2 记忆生命周期
用户对话 -> Agent 执行 -> 线程完成
|
MemoryManager.consolidate()
|
LLM 提取关键事实 (最多 5 条)
|
Memory.store() -> 长期记忆
|
episodic 摘要 -> 事件记忆
8.3 记忆检索
Memory.recall() 混合排序:
- 关键词匹配分数 (0.5 权重)
- 重要性分数 (0.3 权重)
- 按 importance desc, write_date desc 排序
- 自动过滤过期记忆
- 更新访问计数和最后访问时间
9. RAG 知识检索
9.1 索引管线
KnowledgeSource.action_index():
1. _extract_text() -- 根据 source_type 提取文本
- file: base64 解码 -> 按格式解析
- url: httpx + BeautifulSoup
- odoo_model: 查询记录,拼接字段
- text: 直接使用 raw_text
2. _chunk_text() -- 递归字符分割
- 优先在双换行处分割
- 回退到单换行、句号、逗号、空格
- chunk_overlap 实现重叠
3. _embed_chunks() -- 批量嵌入
- 使用关联 Agent 的 LLM Adapter
- 每批 20 条
9.2 向量搜索
# 自动检测 pgvector SELECT 1 FROM pg_extension WHERE extname = 'vector' # pgvector 可用时: SELECT id FROM agentic_ai_knowledge_chunk ORDER BY embedding::vector <=> %s::vector LIMIT %s # 降级为 NumPy: cosine_similarity = dot(query, chunk) / (norm(query) * norm(chunk))
10. 用户界面
10.1 OWL Chat Widget(static/src/js/chat_widget.js)
注册为 agentic_ai.chat_action Client Action,功能包括:
- Agent 选择器下拉框
- 线程历史侧边栏
- 消息气泡(按角色着色):用户蓝色、AI 白色、工具调用灰色、确认黄色
- 确认操作栏(批准/拒绝按钮)
- 执行计划面板(步骤状态图标)
- 输入区域(Enter 发送,Shift+Enter 换行)
- 加载动画(三点跳动 + "Agent is thinking...")
- 流式光标动画
10.2 SSE 流式处理器(static/src/js/streaming_handler.js)
StreamingHandler 类管理 EventSource 连接:
- 事件类型:token, message, tool_call, tool_result, plan_update, confirmation_request, done, error
- 自动重连处理
- 连接关闭回调
10.3 后端视图
| 视图文件 | 模型 | 视图类型 |
|---|---|---|
| llm_provider_views.xml | LLM Provider | tree, form |
| agent_views.xml | Agent | tree, form (含 6 个标签页) |
| agent_tool_views.xml | Tool | tree, form, search |
| agent_thread_views.xml | Thread | tree, form, search |
| agent_plan_views.xml | Plan + Step | tree, form |
| agent_execution_log_views.xml | Execution Log | tree, form, search, pivot, graph |
| agent_knowledge_views.xml | Knowledge + Safety + Memory | tree, form |
| menus.xml | -- | 顶级菜单 + 配置/监控子菜单 |
11. API 端点
11.1 Chat Controller(controllers/chat_controller.py)
| 端点 | 类型 | 认证 | 说明 |
|---|---|---|---|
| /agentic_ai/thread/create | JSON | user | 创建会话线程 |
| /agentic_ai/thread/list | JSON | user | 列出用户线程 |
| /agentic_ai/thread/messages | JSON | user | 获取线程消息 |
| /agentic_ai/chat/send | JSON | user | 发送消息(同步执行) |
| /agentic_ai/chat/send_async | JSON | user | 发送消息(异步队列) |
| /agentic_ai/chat/poll | JSON | user | 轮询新消息 |
| /agentic_ai/chat/stream | HTTP/SSE | user | 流式响应 |
| /agentic_ai/confirm/approve | JSON | user | 批准确认 |
| /agentic_ai/confirm/reject | JSON | user | 拒绝确认 |
| /agentic_ai/agents | JSON | user | 列出可用 Agent |
| /agentic_ai/thread/stats | JSON | user | Token/成本统计 |
| /agentic_ai/thread/plan | JSON | user | 获取执行计划 |
11.2 Webhook Controller(controllers/webhook_controller.py)
| 端点 | 类型 | 认证 | 说明 |
|---|---|---|---|
| /agentic_ai/webhook/trigger | JSON | API Key | 外部触发 Agent |
| /agentic_ai/webhook/status | JSON | API Key | 查询线程状态 |
Webhook 使用 ir.config_parameter 中的 agentic_ai.webhook_api_key 进行 HMAC 安全验证。
12. 定时任务
| Cron | 间隔 | 说明 |
|---|---|---|
| Memory Cleanup | 每天 | 清理过期记忆 |
| Async Task Processor | 每 30 秒 | 处理异步队列中的线程 |
| Knowledge Re-index | 每天(默认禁用) | 重新索引 odoo_model 类型知识源 |
| Log Purge | 每 7 天(默认禁用) | 清理 90 天前的执行日志 |
13. 测试体系
13.1 测试文件结构
| 文件 | 覆盖范围 | 约测试数 |
|---|---|---|
| test_agent_runtime.py | Agent 模型、线程、消息、ReAct 循环 | ~15 |
| test_tool_execution.py | 工具执行管线、Executor、执行日志 | ~10 |
| test_llm_providers.py | 供应商配置、适配器实例化、Token 跟踪 | ~15 |
| test_planner.py | 计划模型、Planner 组件、复杂度评估 | ~10 |
| test_security.py | 安全规则、SafetyGuard、记忆、知识索引 | ~15 |
13.2 测试策略
- 使用 MockLLMAdapter 模拟 LLM 响应(预设 LLMResponse 序列)
- 所有测试基于 Odoo TransactionCase,自动回滚
- 测试覆盖:模型 CRUD、状态转换、参数校验、安全决策、执行管线、确认流程
14. 关键设计决策
| 决策 | 理由 |
|---|---|
| 引擎使用纯 Python 类,非 ORM 方法 | 可测试、解耦。ORM = 状态,引擎 = 行为 |
| Hybrid ReAct + Plan-and-Execute | ReAct 适合简单任务,P&E 适合复杂多步工作流 |
| 工具作为 ORM 记录 + Python 处理器 | UI 可配置、动态发现,加上优化的原生处理器 |
| 默认使用用户 env(不 sudo) | 安全第一:Agent 不能超越用户自身权限 |
| 同步优先 + Cron 异步 | Odoo 不原生支持异步。大多数执行 < 30s,长计划使用 Cron 轮询 |
| pgvector + JSON 降级 | 有 pgvector 时使用生产级向量搜索,无则在任意 PostgreSQL 上工作 |
| 不依赖 Odoo Enterprise AI | 完全独立,兼容 Community Edition,可与 Enterprise 共存 |
| JSON Schema 定义工具参数 | 行业标准,匹配 OpenAI/Gemini 预期格式 |
| 不可变审计日志 | 合规要求:所有 Agent 操作必须可追溯 |
| 多层安全检查 | 安全规则 -> 模型白名单/黑名单 -> 速率限制 -> 确认门控 |
15. 实现过程记录
15.1 实现顺序
实现严格按照依赖关系从底层到上层推进,共 22 个任务:
| 阶段 | 序号 | 任务 | 关键文件 |
|---|---|---|---|
| 基础设施 | 1 | 模块脚手架 | __manifest__.py, __init__.py, 目录结构 |
| 2 | LLM 供应商模型 + OpenAI 适配器 | llm_provider.py, base.py, openai_adapter.py | |
| 核心模型 | 3 | Agent 核心模型 | agent.py |
| 4 | 线程 + 消息模型 | agent_thread.py | |
| 5 | 工具模型 + 通用 ORM 工具 | agent_tool.py, orm_tool.py | |
| 引擎 | 6 | ReAct 运行时引擎 | runtime.py |
| 7 | 安全护栏 + 执行器 + 观察器 | safety.py, executor.py, observer.py | |
| 8 | 计划模型 + Plan-and-Execute | agent_plan.py, planner.py | |
| 记忆与知识 | 9 | 记忆模型 + 记忆管理器 | agent_memory.py, memory_manager.py |
| 10 | RAG 知识模型 + 索引管线 | agent_knowledge.py | |
| 审计与安全 | 11 | 执行日志模型 | agent_execution_log.py |
| 12 | 安全规则模型 | agent_safety_rule.py | |
| 工具 | 13 | 6 大领域工具 | sales_tools.py 等 |
| 适配器 | 14 | Gemini + Ollama 适配器 | gemini_adapter.py, ollama_adapter.py |
| 15 | Token 跟踪器 | token_tracker.py | |
| 安全 | 16 | 安全组、ACL、记录规则 | agentic_ai_security.xml, ir.model.access.csv |
| 数据 | 17 | 预置数据文件 | default_tools_data.xml 等 |
| 接口 | 18 | 控制器端点 | chat_controller.py, webhook_controller.py |
| 视图 | 19 | 全部后端视图 + 菜单 | 8 个 XML 视图文件 |
| 前端 | 20 | OWL Chat Widget + 流式处理 | chat_widget.js, streaming_handler.js, agentic_ai.scss |
| 向导 | 21 | 确认向导 | agent_confirm_wizard.py |
| 测试 | 22 | 5 个测试文件 | test_*.py |
15.2 实现要点
- 渐进式构建: 先实现最小可用的 ReAct 循环(LLM + 工具调用),再逐步添加 Plan-and-Execute、记忆、RAG 等高级能力。
- 安全优先: 安全系统在执行器之前实现,确保从第一天起所有工具执行都经过安全检查。
-
降级设计: 每个组件都有降级方案:
- LLM 调用:主供应商 -> 重试 -> 备用供应商
- 向量搜索:pgvector -> NumPy
- 工具调用:原生函数调用 -> 提示词解析
- 嵌入:API 嵌入 -> 关键词搜索降级 - 无外部运行时依赖: 除 httpx 和 numpy 外,无其他必需 Python 包。Odoo ORM 作为唯一数据层。
15.3 验证结果
- Python 语法: 全部 46 个 .py 文件通过 ast.parse 语法检查
- XML 校验: 全部 15 个 .xml 文件通过 ElementTree.parse 校验
- CSV 校验: ir.model.access.csv 30 行(含表头),每行 8 列,格式正确
16. 文件清单
共 65 个文件(46 Python + 15 XML + 1 CSV + 2 JS + 1 SCSS):
agentic_ai/
├── __init__.py
├── __manifest__.py
├── controllers/
│ ├── __init__.py
│ ├── chat_controller.py
│ └── webhook_controller.py
├── data/
│ ├── cron_data.xml
│ ├── default_agent_data.xml
│ ├── default_tools_data.xml
│ └── safety_rules_data.xml
├── engine/
│ ├── __init__.py
│ ├── executor.py
│ ├── memory_manager.py
│ ├── observer.py
│ ├── planner.py
│ ├── runtime.py
│ └── safety.py
├── llm/
│ ├── __init__.py
│ ├── base.py
│ ├── gemini_adapter.py
│ ├── ollama_adapter.py
│ ├── openai_adapter.py
│ └── token_tracker.py
├── models/
│ ├── __init__.py
│ ├── agent.py
│ ├── agent_execution_log.py
│ ├── agent_knowledge.py
│ ├── agent_memory.py
│ ├── agent_plan.py
│ ├── agent_safety_rule.py
│ ├── agent_thread.py
│ ├── agent_tool.py
│ └── llm_provider.py
├── security/
│ ├── agentic_ai_security.xml
│ └── ir.model.access.csv
├── static/src/
│ ├── js/
│ │ ├── chat_widget.js
│ │ └── streaming_handler.js
│ ├── scss/
│ │ └── agentic_ai.scss
│ └── xml/
│ └── chat_widget.xml
├── tests/
│ ├── __init__.py
│ ├── test_agent_runtime.py
│ ├── test_llm_providers.py
│ ├── test_planner.py
│ ├── test_security.py
│ └── test_tool_execution.py
├── tools/
│ ├── __init__.py
│ ├── accounting_tools.py
│ ├── base_tool.py
│ ├── hr_tools.py
│ ├── inventory_tools.py
│ ├── manufacturing_tools.py
│ ├── orm_tool.py
│ ├── purchase_tools.py
│ ├── report_tool.py
│ └── sales_tools.py
├── views/
│ ├── agent_execution_log_views.xml
│ ├── agent_knowledge_views.xml
│ ├── agent_plan_views.xml
│ ├── agent_thread_views.xml
│ ├── agent_tool_views.xml
│ ├── agent_views.xml
│ ├── llm_provider_views.xml
│ └── menus.xml
└── wizard/
├── __init__.py
├── agent_confirm_wizard.py
└── agent_confirm_wizard_views.xml
17. 部署指南
17.1 安装步骤
- 将 agentic_ai 目录复制到 Odoo 的 addons 路径
- 安装 Python 依赖:
bash pip install httpx numpy - (可选)安装 pgvector 扩展以获得高性能向量搜索:
sql CREATE EXTENSION IF NOT EXISTS vector; - 更新 Odoo 模块列表,安装 "Agentic AI for Odoo"
- 进入 Agentic AI > 配置 > LLM Providers,创建供应商配置
- 创建或激活 Agent,配置工具和访问控制
- 通过顶级菜单或 Chat Widget 开始对话
17.2 最低配置
LLM Provider: name: "OpenAI GPT-4o" provider_type: openai default_model: gpt-4o api_key: sk-... Agent: name: "General ERP Assistant" code: general_assistant execution_mode: hybrid tools: [all default tools] state: active
17.3 安全建议
- 生产环境务必配置 max_cost_per_day 限制
- 使用 require_confirmation: destructive 或 always 防止意外操作
- 定期审查执行日志(Monitoring > Execution Logs)
- Webhook API Key 应为强随机字符串,存储在 ir.config_parameter
- 不建议在 Agent 上启用 sudo_user_id 除非有明确需求