初始化提交
This commit is contained in:
commit
887c1f449e
963 files changed
+166869
No files matched your search
@@ -0,0 +1,140 @@
|
||||
"""解析模型返回为记忆/世界抽取草稿(纯函数,无 IO)。
|
||||
|
||||
模型输出对象 ``{"memories": [...], "entities": [...]}``。缺省取**安全悲观默认**:
|
||||
记忆 ``sensitivity=low``、世界 ``state_type=inference``(非 fact,召回降权,见
|
||||
[世界模型设计] ../../docs/domain/core-domains.md §8)。
|
||||
"""
|
||||
|
||||
import json
|
||||
import re
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any
|
||||
|
||||
|
||||
@dataclass
|
||||
class MemoryCandidateDraft:
|
||||
type: str
|
||||
title: str
|
||||
content: str
|
||||
confidence: float = 0.5
|
||||
importance: float = 0.5
|
||||
sensitivity: str = "low"
|
||||
reason: str = ""
|
||||
|
||||
|
||||
@dataclass
|
||||
class WorldEntityDraft:
|
||||
type: str
|
||||
name: str
|
||||
attributes: dict[str, Any] = field(default_factory=dict)
|
||||
state_type: str = "inference"
|
||||
confidence: float = 0.5
|
||||
|
||||
|
||||
_MEMORY_TYPES = {
|
||||
"user",
|
||||
"preference",
|
||||
"event",
|
||||
"relationship",
|
||||
"skill",
|
||||
"goal",
|
||||
"other",
|
||||
}
|
||||
_ENTITY_TYPES = {
|
||||
"self",
|
||||
"person",
|
||||
"object",
|
||||
"place",
|
||||
"device",
|
||||
"project",
|
||||
"task",
|
||||
"concept",
|
||||
}
|
||||
_STATE_TYPES = {"fact", "observation", "inference", "hypothesis", "stale"}
|
||||
_SENSITIVITY = {"low", "medium", "high"}
|
||||
|
||||
|
||||
def parse_extraction(
|
||||
raw: str,
|
||||
) -> tuple[list[MemoryCandidateDraft], list[WorldEntityDraft]]:
|
||||
data = extract_json_object(raw)
|
||||
if not isinstance(data, dict):
|
||||
return [], []
|
||||
return parse_memory_drafts(data.get("memories")), _parse_entities(data.get("entities"))
|
||||
|
||||
|
||||
def parse_memory_drafts(value: Any) -> list[MemoryCandidateDraft]:
|
||||
if not isinstance(value, list):
|
||||
return []
|
||||
result: list[MemoryCandidateDraft] = []
|
||||
for item in value:
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
title = str(item.get("title", "")).strip()
|
||||
content = str(item.get("content", "")).strip()
|
||||
if not title or not content:
|
||||
continue
|
||||
result.append(
|
||||
MemoryCandidateDraft(
|
||||
type=_enum(item.get("type"), _MEMORY_TYPES, "other"),
|
||||
title=title,
|
||||
content=content,
|
||||
confidence=_clamp(item.get("confidence"), 0.5),
|
||||
importance=_clamp(item.get("importance"), 0.5),
|
||||
sensitivity=_enum(item.get("sensitivity"), _SENSITIVITY, "low"),
|
||||
reason=str(item.get("reason", "")).strip(),
|
||||
)
|
||||
)
|
||||
return result
|
||||
|
||||
|
||||
def _parse_entities(value: Any) -> list[WorldEntityDraft]:
|
||||
if not isinstance(value, list):
|
||||
return []
|
||||
result: list[WorldEntityDraft] = []
|
||||
for item in value:
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
name = str(item.get("name", "")).strip()
|
||||
if not name:
|
||||
continue
|
||||
attrs = item.get("attributes")
|
||||
result.append(
|
||||
WorldEntityDraft(
|
||||
type=_enum(item.get("type"), _ENTITY_TYPES, "concept"),
|
||||
name=name,
|
||||
attributes=attrs if isinstance(attrs, dict) else {},
|
||||
state_type=_enum(item.get("state_type"), _STATE_TYPES, "inference"),
|
||||
confidence=_clamp(item.get("confidence"), 0.5),
|
||||
)
|
||||
)
|
||||
return result
|
||||
|
||||
|
||||
def extract_json_object(raw: str) -> dict[str, Any]:
|
||||
text = raw.strip()
|
||||
if text.startswith("```"):
|
||||
text = re.sub(r"^```(?:json)?\s*", "", text)
|
||||
text = re.sub(r"\s*```$", "", text)
|
||||
start = text.find("{")
|
||||
end = text.rfind("}")
|
||||
if start != -1 and end > start:
|
||||
text = text[start : end + 1]
|
||||
try:
|
||||
data = json.loads(text)
|
||||
except json.JSONDecodeError:
|
||||
return {}
|
||||
return data if isinstance(data, dict) else {}
|
||||
|
||||
|
||||
def _enum(value: Any, valid: set[str], default: str) -> str:
|
||||
text = str(value or "").strip().lower()
|
||||
return text if text in valid else default
|
||||
|
||||
|
||||
def _clamp(value: Any, default: float) -> float:
|
||||
try:
|
||||
num = float(value)
|
||||
except (TypeError, ValueError):
|
||||
return default
|
||||
return max(0.0, min(1.0, num))
|
||||
Reference in new issue
Block a user