forked from diegoecab/oci-deal-accelerator
Diagram tooling: make targets, CI gate, LLM-rewrite hook, refresh docs
Implements points 3–8 of the post-procedure follow-up. - Make targets: diagram-lookup, diagram-validate-spec, diagram-spec-audit, archcenter-descriptions-refresh, archcenter-smoke. Promotes the new tools out of "remember the CLI" into discoverable build-automation. - .gitea/workflows/diagram-validators.yaml — runs spec validator across every absolute_layout spec on push/PR, plus a drawio re-render smoke test on the canonical example. Hard fail blocks merges. - archcenter_pattern_lookup --llm-rewrite — opt-in (ANTHROPIC_API_KEY env var, mirroring DRAWIO_EXE pattern). Rewrites natural-language queries into canonical OCI terminology before scoring; falls back to the original query on any error. - diagram_spec_validator — documents the policy on legacy archcenter reproductions: LABEL_NEAR_PARENT_EDGE stays a warning so verbatim reconstructions don't lose pixel-fidelity from cosmetic edits. - README — documents the asset refresh procedure (downloader + description fetcher are idempotent, refresh quarterly). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -33,7 +33,12 @@ as the basis for your absolute_layout authoring.
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
@@ -100,6 +105,60 @@ def _expand_query_tokens(tokens: set[str]) -> set[str]:
|
||||
return expanded
|
||||
|
||||
|
||||
def _llm_rewrite_query(query: str) -> str:
|
||||
"""Rewrite ``query`` into canonical OCI/Oracle terminology via the
|
||||
Anthropic API.
|
||||
|
||||
Opt-in: requires ``ANTHROPIC_API_KEY`` in the environment. Returns
|
||||
the original query unchanged on any error or when the key is
|
||||
missing — never fails the lookup. The synonym table covers the
|
||||
common abbreviations; this hook is for natural-language queries
|
||||
where rule-based expansion alone misses the intent.
|
||||
"""
|
||||
api_key = os.environ.get("ANTHROPIC_API_KEY")
|
||||
if not api_key:
|
||||
print("[lookup] --llm-rewrite skipped: ANTHROPIC_API_KEY not set",
|
||||
file=sys.stderr)
|
||||
return query
|
||||
model = os.environ.get("ANTHROPIC_MODEL", "claude-haiku-4-5-20251001")
|
||||
payload = {
|
||||
"model": model,
|
||||
"max_tokens": 120,
|
||||
"system": (
|
||||
"Rewrite the user's free-text architecture query into a "
|
||||
"concise list of canonical OCI and cloud terms. Expand "
|
||||
"abbreviations (LB → load balancer, ADG → active data "
|
||||
"guard, AD → availability domain, etc.). Do NOT add "
|
||||
"topology elements the user did not request. Output ONLY "
|
||||
"the rewritten query as a single space-separated phrase, "
|
||||
"no preface, no quotes."
|
||||
),
|
||||
"messages": [{"role": "user", "content": query}],
|
||||
}
|
||||
req = urllib.request.Request(
|
||||
"https://api.anthropic.com/v1/messages",
|
||||
data=json.dumps(payload).encode("utf-8"),
|
||||
headers={
|
||||
"content-type": "application/json",
|
||||
"x-api-key": api_key,
|
||||
"anthropic-version": "2023-06-01",
|
||||
},
|
||||
)
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=15) as resp:
|
||||
body = json.loads(resp.read().decode("utf-8"))
|
||||
except (urllib.error.URLError, urllib.error.HTTPError, TimeoutError, ValueError) as exc:
|
||||
print(f"[lookup] --llm-rewrite failed: {exc}; using original query",
|
||||
file=sys.stderr)
|
||||
return query
|
||||
blocks = body.get("content") or []
|
||||
text = " ".join(b.get("text", "") for b in blocks if b.get("type") == "text").strip()
|
||||
if not text:
|
||||
return query
|
||||
print(f"[lookup] llm-rewrote: {query!r} → {text!r}", file=sys.stderr)
|
||||
return text
|
||||
|
||||
|
||||
def _description_text(entry: dict) -> str:
|
||||
"""Read the cached `_description.md` body if present.
|
||||
|
||||
@@ -251,6 +310,11 @@ def main() -> None:
|
||||
parser.add_argument("--no-synonyms", action="store_true",
|
||||
help="Disable query-token expansion via "
|
||||
"kb/architecture-center/synonyms.yaml.")
|
||||
parser.add_argument("--llm-rewrite", action="store_true",
|
||||
help="Rewrite the query via the Anthropic API "
|
||||
"before scoring (opt-in; requires "
|
||||
"ANTHROPIC_API_KEY). Useful for natural-language "
|
||||
"queries the synonym table doesn't cover.")
|
||||
args = parser.parse_args()
|
||||
|
||||
queries: list[str] = list(args.queries)
|
||||
@@ -260,6 +324,8 @@ def main() -> None:
|
||||
parser.error("Provide a positional query or --queries.")
|
||||
|
||||
expand = not args.no_synonyms
|
||||
if args.llm_rewrite:
|
||||
queries = [_llm_rewrite_query(q) for q in queries]
|
||||
if args.format == "yaml":
|
||||
bundle = {q: lookup(q, top=args.top, expand_synonyms=expand) for q in queries}
|
||||
print(yaml.safe_dump(bundle if len(queries) > 1 else bundle[queries[0]],
|
||||
|
||||
Reference in New Issue
Block a user