## 一、需求
[Feature-799460 【算子平台】统一retrieval支持逻辑属性召回](https://devops.aishu.cn/AISHUDevOps/DIP/_workitems/edit/799460/)

## 二、需求分析
### 2.1 需求背景
用户提出**复合问题**时，系统通常先通过检索/查询拿到对象实例的**数据属性**（例如企业列表、主键、部分字段），但用户还希望继续获取这些对象实例的**逻辑属性**（`logic_properties`，包含 metric + operator）。

因此需要一个“逻辑属性值获取能力”，完成两件事：
- **把上下文解析成可执行请求**：基于 `query + object_instances + additional_context + now_ms/timezone` 等信息，为每个逻辑属性生成 `dynamic_params`
- **执行查询并返回结果**：调用底层 `ontology_query_object_proteries`，返回按对象实例对齐的逻辑属性值

典型例子（请保留）：
- “注册资金大于100万人民币的企业有哪些？想知道这些药企的药品上市情况，并且这些企业的健康度怎么样？”
  - 第一步：检索/筛选得到企业列表（含 company_id 等主键，及注册资金等字段）
  - 第二步：对这批企业批量查询逻辑属性：`approved_drug_count`（metric）+ `business_health_score`（operator）

### 2.2目标

在“复合问题”场景下，让上游 Agent 能稳定完成：
1、先得到对象实例数据属性（召回/筛选）
2、再批量补齐这些对象的逻辑属性（metric + operator，本版本都需要支持）

其中 **kn-logic-property-resolver**（隶属于 `kn-context-loader` 工具集）负责：
- 内部拉取对象类定义（模式B）
- 组织上下文与 logic_properties 配置给大模型生成 `dynamic_params`
- 调用底层 `ontology_query_object_proteries` 查询逻辑属性并返回对齐结果

- **目标功能描述**
  - 同时支持 **metric + operator** 两类逻辑属性
  - 支持 **单对象类（ot_id）下多实例（unique_identities）**、一次查询多个 `properties`
  - 任一 property 缺参/失败 → **整体失败**（不做 partial success）
  - 工具内部：拉 `ontology-manager` 获取对象类定义（模式B），调用 Agent 生成 dynamic_params，调用 `ontology-query` 执行查询

- **非目标（暂不做）**
  - data_properties 与 logic_properties 混合查询
  - 跨对象类（多 ot_id）查询
  - dynamic_params 缓存 / object type 定义缓存
  - 规则化语义解析（时间/instant/step/业务参数抽取优先交给 Agent）

## 三、 参与组件与职责

- **Agent（上游编排）**：理解用户意图、确定 kn_id/ot_id、召回对象实例、决定 properties、组织上下文、回填结果；缺参时负责追问用户/补充上下文并重试。
- **kn-logic-property-resolver（工具）**：生成 dynamic_params + 调底层接口；不做代码语义规则识别（先交给大模型）。
- **ontology-manager**：提供对象类定义（logic_properties/parameters）。
- **ontology-query**：底层属性查询接口（输入 unique_identities/properties/dynamic_params）。
- **LLM 服务**：生成 dynamic_params（以及可选的 JSON 修复）。

## 四、实现设计
### 4.1 端到端流程（Hybrid 7步）

1) Agent 接收用户问题（复合问题）
2) Agent 确定 `kn_id`、`ot_id`
3) Agent 召回/筛选对象实例 → 得到 `object_instances` 并构建 `unique_identities`
4) Agent 决定要补齐的逻辑属性 → `properties`
5) Agent 组织上下文 → `query + object_instances + additional_context + now_ms/timezone ...`
6) Agent 调用 kn-logic-property-resolver：
   - kn-logic-property-resolver 内部拉 ontology-manager（模式B）并截取 `properties` 对应的 `logic_properties.parameters`
   - 调用 LLM 生成 `dynamic_params`
   - 调用 `ontology_query_object_proteries` 获取逻辑属性结果
7) Agent 回填并回答：
   - 成功：merge 回 object_instances
   - 缺参：基于缺参清单追问/补上下文 → 重试第6步

### 4.2 接口设计

#### 4.2.1  Endpoint

- `POST /api/kn/logic-property-resolver`

#### 4.2.2 Request Body（最小）
```json
{
  "kn_id": "",
  "ot_id": "",
  "query": "...",
  "unique_identities": [ { "...": "..." } ],
  "properties": [ "approved_drug_count", "business_health_score" ],
  "additional_context": "用途：给 LLM/Agent 补充生成 dynamic_params 所需的上下文（自由文本或 JSON 字符串均可，服务端不解析其结构）。建议至少包含：1) 对象实例关键信息（主键+必要字段）；2) 筛选/约束条件；3) 时间信息（now_ms/timezone/start/end/instant/step）；4) 针对某个 property 的补充说明（如有）。示例：company_id=company_000001，registered_capital=2000000；registered_capital>1000000；now_ms=1762996342241，timezone=Asia/Shanghai；趋势查询step=month/即时查询instant=true。",
  "options": {
    "return_debug": false,
    "max_repair_rounds": 1
  }
}
```

#### 4.2.3 Response

- **成功**：透传底层 `ontology_query_object_proteries` 响应（`datas` 按 unique_identities 对齐）
- **失败（缺参/不合法）**：返回结构化错误（建议格式见第7节）

## 五、 依赖哪些接口（Dependencies）

### 5.1 ontology-manager（对象类定义）

- 用途：获取对象类定义，拿到 `logic_properties`，并按 `properties` 截取对应的 `parameters`
- 接口（示例，按你们现有文档口径）：`GET /api/ontology-manager/in/v1/knowledge-networks/{kn_id}/object-types/{ot_id}`
- 缓存策略：**暂不缓存，每次请求都获取**（后续可按需优化为按 kn_id+ot_id 缓存，配置 TTL）

### 5.2 ontology-query（底层逻辑属性值查询）

- 用途：实际执行逻辑属性值查询
- 接口：`POST /api/ontology-query/in/v1/knowledge-networks/{kn_id}/object-types/{ot_id}/properties`
- Header：`x-http-method-override: GET`、`x-account-id`、`x-account-type`
- Body：`{ unique_identities, properties, dynamic_params }`

### 5.3 LLM（动态参数生成，按类型/按属性并发）

- 用途：生成 `dynamic_params`
- 方式：
  - **按类型**：metric/operator 分别用各自提示词生成 dynamic_params
  - **按属性并发**：每个 property 独立生成（更利于并发与最小上下文）
- 说明：需要支持并发、失败重试与 JSON 修复

### 5.4 operator 服务（可选：用于 schema/示例，提升 operator 参数生成准确率）

> 说明：逻辑属性值的“执行”仍然走 `ontology-query` 的 properties 接口；operator 服务依赖主要用于**拿到算子入参 schema/openapi 元数据**，让 LLM 更准确生成复杂 Body/数组/对象参数。

- 获取算子详情（含 openapi 元数据、参数 schema、示例等）：
  - `GET /api/agent-operator-integration/internal-v1/operator/market/{operator_id}`
- 代理执行算子（通常**不需要**由本工具直接调用，除非你们未来要绕过 ontology-query）：
  - `POST /api/agent-operator-integration/internal-v1/operator/proxy/{operator_id}`

## 六、 LLM 的提示词设计（metric + operator）

> 本节按“逻辑属性类型”分别定义提示词输入/输出/硬约束。推荐按 property 级别调用（便于并发与最小上下文）。

### 6.1 通用输入（两类共用）

- query
- kn_id / ot_id
- unique_identities
- additional_context（可选，包含对象实例信息、时间信息等上下文）
- now_ms / timezone（可选）
- 目标属性的 `logic_property` 配置（尤其是 `type / parameters / data_source`）

> **注**：`object_instances` 不再作为独立参数，对象实例信息统一通过 `additional_context` 传递。

### 6.2 通用输出（统一格式，便于合并与并发）

要求 LLM **只输出严格合法 JSON**，格式固定为：
```json
{
  "property_name": {
    "param1": value1,
    "param2": value2
  }
}
```

例如：
```json
{
  "approved_drug_count": {
    "instant": true,
    "start": 1762996342241,
    "end": 1762996342241
  }
}
```

缺参时输出（仍必须是合法 JSON）：
```json
{
  "_error": "缺少必填参数: start (时间范围开始时间戳), end (时间范围结束时间戳)"
}
```

### 6.3 metric 提示词（针对性设计）

- **只生成**该属性 `parameters` 中所有 `value_from:"input"` 的参数
- **固定系统项**：`instant/start/end/step`（`if_system_generate:true`）必须生成
- **step 枚举**：`day/week/month/quarter/year`（固定 1 个单位）
- **instant 定义**：`instant:true` 即时（单点）；`instant:false` 趋势（范围/序列，必须带 step）
- 其他 `value_from:"input"` 业务参数：尽量从 `additional_context/object_instances/query` 抽取；缺参则输出 missing_params

### 6.4 operator 提示词（针对性设计）

- **只生成**该属性 `parameters` 中所有 `value_from:"input"` 的参数
- operator 的参数可能来自 Path/Query/Body，但在本工具里统一表现为 `dynamic_params[property]` 的键值
- 参数值可能是基础类型/对象/数组（例如 projects 列表），必须保持结构可用
- **推荐补充 operator schema 输入**（若可用）：
  - 从 `logic_property.data_source.id` 得到 `operator_id`
  - 调用 `GET /operator/market/{operator_id}` 获取 openapi 元数据/参数 schema/示例，作为提示词的一部分
- 抽取优先级：`additional_context` > `query` >（schema 示例/默认值）；缺参输出 `_error`

## 七、 kn-logic-property-resolver 内部处理（不做语义规则识别前提）

1) 拉取对象类定义（模式B）：`ontology-manager` 获取 ot 定义
2) 截取子集：仅保留本次 `properties` 对应的 `logic_properties` 配置（含 parameters）
3) 组装 prompt：输入 `query + unique_identities + additional_context + logic_properties(parameters)`，并加入硬约束：
   - metric：生成所有 `value_from:"input"` 参数；其中 `instant/start/end/step` 固定项
   - operator：生成所有 `value_from:"input"` 参数（可为基础类型/对象/数组），并保持其结构与类型要求
   - step 枚举：`day/week/month/quarter/year`（固定1单位）
   - instant：true=即时；false=趋势（false 必带 step）
   - 必须输出严格合法 JSON
4) LLM 生成 dynamic_params（以及完整请求体/或仅 dynamic_params，二选一；建议仅 dynamic_params 更短更稳）
5) 结构校验 + 修复（最多一次）：
   - JSON 合法
   - step 枚举合法
   - dynamic_params 必含每个 property
6) 调底层 `ontology_query_object_proteries` 并返回


## 八、核心调用流程

**核心流程**：
```
generateDynamicParams()
├── 准备阶段：遍历所有 properties
├── 并发调用 LLM（统一控制 max_concurrency）
│   ├── property1 (metric)   → buildPrompt → callLLM → validate
│   ├── property2 (operator) → buildPrompt → callLLM → validate
│   ├── property3 (metric)   → buildPrompt → callLLM → validate
│   └── ...（最多同时 max_concurrency 个）
└── 收集结果（成功的 + 缺参的）
```

## 九、 附录：术语

- **logic_properties**：逻辑属性，包含 metric/operator 两类，需要 dynamic_params 才能执行查询
- **dynamic_params**：按 property 组织的动态参数对象：`dynamic_params[propertyName] = { ... }`
- **unique_identities**：对象实例主键集合（支持批量）
- **additional_context**：上游提供的上下文载体（自由格式字符串），用于帮助 Agent 生成参数