| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- #!/usr/bin/env python3
- """
- Demo 1: 扫描鸿蒙 Agent DSL 管道配置,发现类型不兼容 bug
- ========================================================
- 流程:
- 1. 加载鸿蒙旅行规划 YAML 配置(模拟 Agent DSL 导出)
- 2. 从 chain.steps 提取每个 Agent 的 output_type / input_type
- 3. 用 T-Compose 规则检查相邻 Agent 的类型兼容性
- 4. 用 lint_config 扫描 26 条结构规则
- 核心发现:
- Planner 输出 Json(object{route, budget, days})
- Transport 期望 Str
- → 仓颉编译器看到的都是 String,不报错
- → lambdagent T-Compose: Json(object) ≮: Str → 编译时报错
- """
- from __future__ import annotations
- import sys, os, yaml
- from typing import Optional
- sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
- from lambdagent.types import (
- AgentType, LamType, TypeTag,
- check_compose_types, AgentTypeError,
- is_subtype, T_ANY, T_STR,
- )
- from lambdagent.fromconfig.lint import lint_config
- def json_schema_to_lam_type(schema: Optional[dict]) -> LamType:
- """把 YAML 中的 JSON Schema 类型标注转为 LamType"""
- if schema is None:
- return T_ANY
- t = schema.get("type", "any")
- if t == "string":
- return T_STR
- elif t in ("object", "array"):
- return LamType(TypeTag.JSON, schema=schema)
- elif t == "integer":
- return LamType(TypeTag.INT)
- elif t == "number":
- return LamType(TypeTag.FLOAT)
- elif t == "boolean":
- return LamType(TypeTag.BOOL)
- return T_ANY
- def main():
- config_path = os.path.join(os.path.dirname(__file__), "harmony_travel.yaml")
- print("=" * 62)
- print("Demo 1: 扫描鸿蒙 Agent DSL 管道 — T-Compose 类型检查")
- print("=" * 62)
- print()
- # ── Step 1: 加载配置 ──
- print(f"[Step 1] 加载配置: {os.path.basename(config_path)}")
- with open(config_path, "r", encoding="utf-8") as f:
- cfg = yaml.safe_load(f)
- steps = cfg.get("chain", {}).get("steps", [])
- print(f" Pipeline: {' → '.join(s['name'] for s in steps)}")
- print(f" 模型: {cfg.get('model', {}).get('name', 'unknown')}")
- print()
- # ── Step 2: 从配置提取 Agent 类型签名 ──
- print("[Step 2] 从 YAML 提取 Agent 类型签名")
- agent_types = []
- for step in steps:
- name = step["name"]
- in_t = json_schema_to_lam_type(step.get("input_type"))
- out_t = json_schema_to_lam_type(step.get("output_type"))
- at = AgentType(input_type=in_t, output_type=out_t, effect="llm")
- agent_types.append((name, at))
- print(f" {name:12s}: {at}")
- print()
- # ── Step 3: CangjieMagic / 仓颉编译器视角 ──
- print("[Step 3] CangjieMagic / 仓颉编译器视角")
- print()
- print(" // CangjieMagic Agent DSL 代码:")
- print(' @agent[model: "pangu-lite", executor: "naive"]')
- print(" class Planner {")
- print(' @prompt[pattern: APE](')
- print(' action: "制定旅行计划",')
- print(' expectation: "JSON格式行程")')
- print(" func planTrip(req: String): String // ← 仓颉类型")
- print(" }")
- print()
- print(' @agent[model: "pangu-lite"]')
- print(" class Transport {")
- print(' @prompt[pattern: APE](action: "预订交通")')
- print(" func book(plan: String): String // ← 仓颉类型")
- print(" }")
- print()
- print(" // 仓颉编译器: String → String → String ✅ 全部通过")
- print(" // → 仓颉/CangjieMagic 只看到 String,不检查 JSON 结构")
- print()
- # ── Step 4: T-Compose 类型检查 ──
- print("[Step 4] lambdagent T-Compose 类型检查")
- print(" 规则: f >> g 要求 output(f) <: input(g)")
- print()
- for i in range(len(agent_types) - 1):
- name_f, type_f = agent_types[i]
- name_g, type_g = agent_types[i + 1]
- out_f = type_f.output_type
- in_g = type_g.input_type
- ok = is_subtype(out_f, in_g)
- status = "✅" if ok else "❌"
- print(f" {name_f} >> {name_g}:")
- print(f" output({name_f}) = {out_f}")
- print(f" input({name_g}) = {in_g}")
- print(f" {out_f} <: {in_g} ? → {status}")
- print()
- # 整体检查
- try:
- result = check_compose_types([at for _, at in agent_types])
- print(f" ✅ Pipeline 类型安全: {result}")
- except AgentTypeError as e:
- print(f" ❌ [T-Compose ERROR] {e}")
- print()
- print(" 影响分析:")
- print(" → Transport 收到 JSON 而非城市名 → 解析失败")
- print(" → 端侧: 用户看到白屏 → 卸载 App")
- print(" → 服务端: 可以重试;手机上: 没有第二次机会")
- print()
- # ── Step 5: Lint 结构扫描 ──
- print("[Step 5] Lint 26 条规则扫描")
- results = lint_config(cfg)
- if results:
- for r in results:
- print(f" [{r.level:5s}] {r.rule}: {r.message}")
- else:
- print(" ✅ No lint issues")
- print()
- print("=" * 62)
- print("结论:")
- print(" 仓颉编译器: String → String → String ✅ (漏掉类型 bug)")
- print(" lambdagent: Json(obj) → Str ❌ (编译时发现)")
- print(" → 合作方案: 把 T-Compose 集成到仓颉编译器")
- print("=" * 62)
- if __name__ == "__main__":
- main()
|