Initial commit: Pegas Memory (PG + Qdrant + Memgraph, MCP server, 14 tools)
This commit is contained in:
commit
83e77ea8c9
24 files changed
+2201
No files matched your search
@@ -0,0 +1,72 @@
|
||||
"""Дистилляция чанка в типизированные атомы (LLM)."""
|
||||
from __future__ import annotations
|
||||
import json
|
||||
import httpx
|
||||
from . import config
|
||||
|
||||
_client = httpx.Client(timeout=600)
|
||||
|
||||
SYSTEM = """Ты — экстрактор знаний. Преврати текст в атомарные, типизированные утверждения.
|
||||
Верни ТОЛЬКО JSON-массив без пояснений. Каждый элемент:
|
||||
{
|
||||
"type": "text|definition|logical_rule|code|table|fact",
|
||||
"claim": "короткое каноническое утверждение (одно предложение)",
|
||||
"content": "полное значение атома",
|
||||
"confidence": 0.0-1.0
|
||||
}
|
||||
Правила:
|
||||
- definition: термин и его точное определение.
|
||||
- logical_rule: правило "если X то Y" (content = JSON со ключами if/then).
|
||||
- code: фрагмент кода или сигнатура функции (content = сам код).
|
||||
- table: табличные данные (content = JSON или markdown-таблица).
|
||||
- fact: проверяемый факт с числом или датой.
|
||||
- text: всё остальное ценное.
|
||||
- Отбрасывай воду, повторы, навигацию, рекламу. Только новое и ценное.
|
||||
- Если ничего ценного — верни []. No markdown fences."""
|
||||
|
||||
def distill_chunk(chunk_text: str, model: str | None = None) -> list[dict]:
|
||||
"""Вернуть список атомов (dict) из чанка."""
|
||||
m = model or config.LLM_MODEL
|
||||
r = _client.post(f"{config.OLLAMA_URL}/api/chat", json={
|
||||
"model": m,
|
||||
"messages": [
|
||||
{"role": "system", "content": SYSTEM},
|
||||
{"role": "user", "content": chunk_text[:6000]},
|
||||
],
|
||||
"stream": False,
|
||||
"options": {"temperature": 0.1},
|
||||
})
|
||||
r.raise_for_status()
|
||||
content = r.json()["message"]["content"]
|
||||
start = content.find("[")
|
||||
end = content.rfind("]")
|
||||
if start == -1 or end == -1:
|
||||
return []
|
||||
try:
|
||||
arr = json.loads(content[start:end + 1])
|
||||
except json.JSONDecodeError:
|
||||
return []
|
||||
return [a for a in arr if isinstance(a, dict) and a.get("type") and a.get("content")]
|
||||
|
||||
def verify_atom(atom: dict, context_atoms: list[dict], model: str | None = None) -> float:
|
||||
"""Оценить новизну/ценность атома против существующих (0..1)."""
|
||||
m = model or config.LLM_MODEL
|
||||
ctx = "\n".join(f"- {a.get('claim','')}" for a in context_atoms[:8])
|
||||
prompt = (
|
||||
f"Существующие знания:\n{ctx}\n\n"
|
||||
f"Новый атом ({atom.get('type')}): {atom.get('claim')}\n{atom.get('content','')[:500]}\n\n"
|
||||
f"Оцени от 0 до 1, насколько это НОВОЕ и ценное знание (0=дубль/вода, 1=уникальное важное). "
|
||||
f"Верни только число."
|
||||
)
|
||||
r = _client.post(f"{config.OLLAMA_URL}/api/chat", json={
|
||||
"model": m,
|
||||
"messages": [{"role": "user", "content": prompt}],
|
||||
"stream": False,
|
||||
"options": {"temperature": 0.0},
|
||||
})
|
||||
r.raise_for_status()
|
||||
out = r.json()["message"]["content"].strip()
|
||||
try:
|
||||
return float(out)
|
||||
except ValueError:
|
||||
return 0.5
|
||||
Reference in new issue
Block a user