# kn-logic-property-resolver 实现架构设计

> **说明**：本文档描述 kn-logic-property-resolver 的实现架构，包括并发控制、方法调用层次、错误处理等。

---

## 并发架构（按 property 并发）

### 核心设计原则

1. **按 property 并发**：每个 property 独立调用 Agent/LLM，不区分 metric/operator 类型
2. **统一并发控制**：在主方法中使用信号量控制 `max_concurrency`
3. **类型分派**：根据 property 类型选择不同的参数生成方法
4. **容错处理**：单个 property 失败不影响其他 property，收集所有结果后统一返回

---

## 方法调用层次

```
ResolveLogicProperties()                     # Handler 层
└── generateDynamicParams()                  # 主方法：并发控制
    ├── 准备阶段：构建任务列表
    ├── 并发阶段（max_concurrency 控制）
    │   ├── goroutine 1: generateSinglePropertyParams(property1)
    │   ├── goroutine 2: generateSinglePropertyParams(property2)
    │   ├── goroutine 3: generateSinglePropertyParams(property3)
    │   └── goroutine N: generateSinglePropertyParams(propertyN)
    └── 收集阶段：合并结果和缺参信息
```

---

## generateSinglePropertyParams 流程

处理单个 property 的完整流程：

```
generateSinglePropertyParams(property)
│
├── 根据类型选择参数生成方法
│   ├── if property.Type == Metric:
│   │   └── generateMetricParams() → 调用 Metric Agent
│   └── else if property.Type == Operator:
│       └── generateOperatorParams() → 调用 Operator Agent
│
├── Agent 内部流程（由 Agent 平台处理）
│   ├── 构建提示词
│   ├── 调用 LLM
│   ├── 解析 JSON 输出
│   └── 返回结果或缺参信息
│
├── 参数校验（服务端）
│   ├── if property.Type == Metric:
│   │   └── validateMetricParams()
│   │       ├── 检查 instant/start/end/step
│   │       ├── step 枚举校验
│   │       └── instant/step 组合校验
│   └── else if property.Type == Operator:
│       └── validateOperatorParams()
│           ├── 检查所有 value_from="input" 参数
│           └── 参数类型校验
│
└── 返回结果
    ├── 成功：dynamicParams
    ├── 缺参：MissingParams
    └── 错误：error
```

---

## Agent 集成架构

### 当前方案：使用 Agent 平台

```
knLogicPropertyResolverService
│
├── generateMetricParams()
│   └── agentApp.MetricDynamicParamsGeneratorAgent()
│       ├── 构建 AgentReq（序列化为 JSON）
│       ├── 调用 APIChat（Agent 平台）
│       ├── 解析 Agent 输出
│       │   ├── 成功：{ "<property>": { "param1": value1, ... } }
│       │   └── 缺参：{ "_error": "missing <property>: <params> | ask: <hint>" }
│       └── 返回 (dynamicParams, missingParams, error)
│
└── generateOperatorParams()
    └── agentApp.OperatorDynamicParamsGeneratorAgent()
        └── （流程同上）
```

### 扩展性设计

如需切换到直接调用 LLM：

1. 创建 LLM 客户端接口
2. 修改 `generateMetricParams/generateOperatorParams` 方法内部实现
3. 添加配置开关，选择 Agent 或 LLM
4. **无需修改上层调用代码**（`generateSinglePropertyParams` 及以上）

---

## 并发控制机制

### 信号量实现

```go
// 创建信号量（容量为 max_concurrency）
semaphore := make(chan struct{}, maxConcurrency)

// 每个 goroutine 执行前
semaphore <- struct{}{}  // 获取信号量（如果满了会阻塞）
defer func() { <-semaphore }()  // 释放信号量
```

### 并发流程图

```
主线程
  │
  ├─ 创建 semaphore (容量=4)
  ├─ 创建 results channel
  │
  ├─ for each property:
  │   └─ go func() {
  │       ├─ [等待] semaphore <- // 最多4个同时运行
  │       ├─ generateMetricParams/generateOperatorParams()
  │       ├─ validate()
  │       ├─ results <- result
  │       └─ <-semaphore // 释放
  │      }
  │
  └─ for i in properties:
      └─ result := <-results  // 收集所有结果
```

---

## 类型特定的辅助方法

### Metric 相关

```go
// 生成参数（调用 Agent）
generateMetricParams(property, request) -> (dynamicParams, missingParams, error)
  └── 参考：prd/feature-799460/04-metric参数生成提示词设计.md

// 校验参数（服务端）
validateMetricParams(property, params) -> error
  ├── 检查 instant/start/end/step 存在性
  ├── step ∈ [day, week, month, quarter, year]
  ├── instant=true  → step 不存在
  └── instant=false → step 必须存在
```

### Operator 相关

```go
// 生成参数（调用 Agent）
generateOperatorParams(property, request) -> (dynamicParams, missingParams, error)
  └── 参考：prd/feature-799460/07-operator参数生成提示词设计.md

// 校验参数（服务端）
validateOperatorParams(property, params) -> error
  ├── 检查所有 value_from="input" 参数
  └── 参数类型校验（基础类型/对象/数组）
```

---

## Agent 输出格式解析

### 成功输出

```json
{
  "approved_drug_count": {
    "instant": false,
    "start": 1731460342241,
    "end": 1762996342241,
    "step": "month"
  }
}
```

解析逻辑：
- 直接返回整个 map 作为 `dynamic_params`
- property name 作为顶层 key

### 缺参输出

```json
{
  "_error": "missing approved_drug_count: start,end | ask: 请在 additional_context 中补充时间范围"
}
```

解析逻辑：
1. 检测 `_error` 字段
2. 解析格式：`missing <property>: <p1>,<p2> | ask: <hint>`
3. 构造 `MissingPropertyParams` 结构返回

---

## 错误处理策略

### 单个 property 失败

```go
// 不会中断其他 property 的处理
if err != nil {
    // 转换为缺参信息
    missingParams = append(missingParams, MissingPropertyParams{
        Property: propertyName,
        Params: [{Name: "_error", Hint: err.Error()}],
    })
    continue  // 继续处理其他 property
}
```

### 所有 property 处理完成后

```go
// 如果有缺参，返回缺参错误
if len(missingParams) > 0 {
    return nil, missingParams, nil
}

// 否则返回成功
return dynamicParams, nil, nil
```

---

## 性能优化点

### 1. 并发粒度

✅ **按 property 并发**（最细粒度）
- 每个 property 独立执行
- 充分利用并发，不受类型限制

❌ ~~按类型串行~~（粗粒度，已废弃）
- metric 和 operator 串行执行
- 浪费并发机会

### 2. 并发上限

- 默认：`max_concurrency = 4`
- 可配置：通过 `ResolveOptions.MaxConcurrency` 调整
- 依据：平衡 Agent/LLM 网关限流（如 10 QPS）与延迟收益

### 3. Agent 调用优化

- **异步并发**：多个 property 并发调用 Agent
- **请求合并**：将完整请求序列化为 JSON 传递给 Agent
- **错误隔离**：单个 Agent 调用失败不影响其他

---

## 配置管理

### Agent Key 配置

在 `config.yaml` 中配置：

```yaml
deploy_agent:
  metric_dynamic_params_generator_key: "metric_agent_key_xxx"
  operator_dynamic_params_generator_key: "operator_agent_key_xxx"
```

在代码中使用：

```go
type DeployAgentConfig struct {
    MetricDynamicParamsGeneratorKey   string `yaml:"metric_dynamic_params_generator_key"`
    OperatorDynamicParamsGeneratorKey string `yaml:"operator_dynamic_params_generator_key"`
}
```

---

## 测试建议

### 单元测试

```go
// 测试单个 property 处理
TestGenerateSinglePropertyParams_Metric()
TestGenerateSinglePropertyParams_Operator()

// 测试并发控制
TestGenerateDynamicParams_Concurrency()
TestGenerateDynamicParams_MaxConcurrency()

// 测试错误处理
TestGenerateDynamicParams_PartialFailure()
TestGenerateDynamicParams_AllFailure()

// 测试 Agent 输出解析
TestParseAgentOutput_Success()
TestParseAgentOutput_MissingParams()
```

### 集成测试

```go
// 测试 metric + operator 混合
TestGenerateDynamicParams_Mixed()

// 测试大量 properties
TestGenerateDynamicParams_LargeScale()

// 测试真实 Agent 调用
TestAgentIntegration_Metric()
TestAgentIntegration_Operator()
```

---

## 文件结构

```
server/
├── interfaces/
│   ├── kn_logic_property_resolver.go   # 接口定义
│   ├── driven_agent.go                 # Agent 接口定义（已扩展）
│   └── driven_ontology_manager.go      # Ontology Manager 接口
├── drivenadapters/
│   ├── agent_app.go                    # Agent 平台适配器（已扩展）
│   ├── ontology_manager.go             # Ontology Manager 适配器
│   └── ontology_query.go               # Ontology Query 适配器
├── driveradapters/
│   └── knlogicpropertyresolver/
│       └── index.go                    # HTTP Handler
└── logics/
    └── knlogicpropertyresolver/
        └── index.go                    # 业务逻辑实现
```

---

## 参考文档

- 需求澄清：`prd/feature-799460/08-需求澄清结果汇总.md`
- 方案设计：`prd/feature-799460/03-方案设计.md`
- 并发策略：`prd/feature-799460/05-并发策略与超时配置.md`
- Metric 提示词：`prd/feature-799460/04-metric参数生成提示词设计.md`
- Operator 提示词：`prd/feature-799460/07-operator参数生成提示词设计.md`
- 错误码清单：`prd/feature-799460/06-错误码清单与处理策略.md`

---

**版本**：v1.0
**更新日期**：2025-12-16
**当前状态**：已实现 Agent 集成架构，保留扩展到直接调用 LLM 的能力

