Text Generation
PEFT
Chinese
English
preference-learning
qlora
agent
personalization
association-engine
Instructions to use feiertu/hermes-association-engine with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use feiertu/hermes-association-engine with PEFT:
Task type is invalid.
- Notebooks
- Google Colab
- Kaggle
| """动态语义聚类 — scope 分配、合并、拆分.""" | |
| import uuid | |
| import sqlite3 | |
| import numpy as np | |
| from datetime import datetime, timezone | |
| from hermes_core.types import Scope, Dimension | |
| from hermes_core.db import ( | |
| get_active_scopes, get_active_records, upsert_scope, get_scope, get_records_by_scope | |
| ) | |
| from hermes_core.embedder import Embedder | |
| DEFAULT_MATCH_THRESHOLD = 0.70 | |
| DEFAULT_MERGE_THRESHOLD = 0.90 | |
| DEFAULT_SPLIT_THRESHOLD = 0.60 | |
| def _new_scope_id() -> str: | |
| return f"scope_{uuid.uuid4().hex[:8]}" | |
| def _now() -> str: | |
| return datetime.now(timezone.utc).isoformat() | |
| def assign_scope(conn: sqlite3.Connection, embedder: Embedder, | |
| scope_desc: str) -> tuple[str, str]: | |
| """为一条 scope_desc 分配 scope。匹配现有 scope 或创建新 scope。 | |
| Returns: | |
| (scope_id, scope_label) | |
| """ | |
| vec = embedder.encode(scope_desc) | |
| scopes = get_active_scopes(conn) | |
| best_score = 0.0 | |
| best_scope = None | |
| for scope in scopes: | |
| if scope.centroid is None: | |
| continue | |
| sim = embedder.cosine_similarity(vec, scope.centroid) | |
| if sim > best_score: | |
| best_score = sim | |
| best_scope = scope | |
| if best_score >= DEFAULT_MATCH_THRESHOLD and best_scope is not None: | |
| return best_scope.id, best_scope.label | |
| # 不匹配任何现有 scope → 创建新 scope | |
| sid = _new_scope_id() | |
| new_scope = Scope( | |
| id=sid, | |
| label=scope_desc, | |
| centroid=vec, | |
| record_count=0, | |
| created_at=_now(), | |
| last_activity=_now(), | |
| ) | |
| upsert_scope(conn, new_scope) | |
| return sid, scope_desc | |
| def recluster_scope(conn: sqlite3.Connection, embedder: Embedder, | |
| scope_id: str) -> None: | |
| """重新计算 scope 的聚类中心和内聚度。""" | |
| records = get_records_by_scope(conn, scope_id) | |
| if not records: | |
| return | |
| scope = get_scope(conn, scope_id) | |
| if scope is None: | |
| return | |
| labels = [r.scope_label for r in records] | |
| vecs = embedder.encode_batch(labels) | |
| centroid = np.mean(vecs, axis=0).tolist() | |
| # 计算内聚度:所有 label 与 centroid 的平均相似度 | |
| similarities = [embedder.cosine_similarity(v, centroid) for v in vecs] | |
| coherence = float(np.mean(similarities)) if similarities else 1.0 | |
| scope.centroid = centroid | |
| scope.record_count = len(records) | |
| scope.coherence = coherence | |
| scope.last_activity = _now() | |
| upsert_scope(conn, scope) | |
| def check_merge(conn: sqlite3.Connection, embedder: Embedder, | |
| threshold: float = DEFAULT_MERGE_THRESHOLD) -> list[tuple[str, str]]: | |
| """检查所有 active scope 两两之间是否应该合并。 | |
| Returns: | |
| [(scope_id_a, scope_id_b), ...] 需要合并的 scope 对 | |
| """ | |
| scopes = get_active_scopes(conn) | |
| pairs = [] | |
| for i in range(len(scopes)): | |
| for j in range(i + 1, len(scopes)): | |
| a, b = scopes[i], scopes[j] | |
| if a.centroid is None or b.centroid is None: | |
| continue | |
| sim = embedder.cosine_similarity(a.centroid, b.centroid) | |
| if sim >= threshold: | |
| pairs.append((a.id, b.id)) | |
| return pairs | |
| def check_split(conn: sqlite3.Connection, embedder: Embedder, | |
| scope_id: str, threshold: float = DEFAULT_SPLIT_THRESHOLD) -> bool: | |
| """检查一个 scope 内聚度是否过低,需要拆分。 | |
| Returns: | |
| True if split is needed | |
| """ | |
| recluster_scope(conn, embedder, scope_id) | |
| scope = get_scope(conn, scope_id) | |
| if scope is None: | |
| return False | |
| return scope.coherence < threshold | |