Compare commits
4
Commits
13e0b87446
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51b79d4045 | ||
|
|
b4552df1a6 | ||
|
|
bc68b68598 | ||
|
|
726e360926 |
No files matched your search
@@ -134,3 +134,14 @@ A **gap** is a question you know you cannot answer yet. Manage them, don't just
|
||||
- If the question turned out irrelevant → `status='dismissed'` (prefer this over deleting).
|
||||
- Raise `priority` when the user asks about the topic; lower it when it stops mattering.
|
||||
- Keep questions **specific and answerable** ("How does HNSW build its graph?" not "HNSW").
|
||||
|
||||
## 8. Documentation language (English source of truth)
|
||||
|
||||
All docs (`*.md`) are written in **English = canonical source of truth**. Russian
|
||||
(`*.ru.md`) is generated for quick comprehension only; terminology may drift and must
|
||||
NEVER be used as the editing basis (editing on drifted Russian breaks intent).
|
||||
|
||||
Workflow: write/edit EN → `python3 en2ru.py file.md` → `file.ru.md`. See
|
||||
[`DOCSTRAT.md`](./DOCSTRAT.md). `translategemma:latest` renders clean orthography but
|
||||
mishandles jargon (`dedup`→«дублирование», `receipt`→«результат»), so review the
|
||||
stderr hints; keep unsure terms in Latin.
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
# Стратегия документов (English source of truth)
|
||||
|
||||
## Правило (обязательное)
|
||||
|
||||
- **Английский — канонический источник (source of truth).** Все правки вносятся
|
||||
**только** в исходный `*.md` (EN).
|
||||
- **Русский — только для бегного понимания.** Это вычислительный **инструмент**;
|
||||
термиология может «поплыть».
|
||||
- **Ник не использовать `.ru.md` за основу для правок.** Правим EN → перезапускаем
|
||||
`en2ru.py`. Нарушение → накаплием ошибочный русский текст и **не можем сделать то,
|
||||
что задумано** (опора на «поплывшую» термиологию ломает смысл).
|
||||
|
||||
### Причина
|
||||
|
||||
`translategemma:latest` **чисто пишет орфографию**, но **джаргон** переводит криво —
|
||||
вплоть до переворота значения: `dedup` → «дублирование» (обратное значение),
|
||||
`receipt` → «результат». Порусскому — вторичен и нуждается в ревью джаргона.
|
||||
|
||||
## Ингест в базу (запрет русского с опечаткой)
|
||||
|
||||
- **Ingest только из английских источников.** `memory_ingest` / `memory_store`
|
||||
принимают **EN**-текст → дестилируются в атомы.
|
||||
- **Русский в атомы — только после орфографической чистки.** Если русский источник
|
||||
неизбежен → сначала прогоним через `en2ru.py` / проверку орфографии → только чистый
|
||||
текст может стать атомом.
|
||||
- **`.ru.md` — никогда не ingest'ится в атомы.** Это внешний слой понимания, вне базы.
|
||||
- **Фиаско**, если русское с опечаткой попадёт в атомы: такой атом станет «источник»
|
||||
для ответов и расруит ошибку по кругу. Английская основа этого не позволяет.
|
||||
|
||||
## Как
|
||||
|
||||
```bash
|
||||
python3 en2ru.py ROADMAP.md # -> ROADMAP.ru.md
|
||||
cat doc.md | python3 en2ru.py - # stdin -> doc.ru.md
|
||||
```
|
||||
|
||||
- Вывод: `<file>.ru.md`.
|
||||
- Джаргон-ревью (термы, где модель ошибается) — в **stderr**, не в RU-выводе.
|
||||
- Оффлайн: зависимостей нет (`urllib`), модель уже в Ollama (`translategemma:latest`).
|
||||
|
||||
## Порядок работ
|
||||
|
||||
1. Пишем/правим **EN** источник.
|
||||
2. `en2ru.py` → генерим **RU**.
|
||||
3. Смотри **stderr** — правь flagged-термы (ревью, не авто).
|
||||
4. Храни **оба** файла рядом: `X.md` (EN, канон) + `X.ru.md` (RU, понимание).
|
||||
+16
-3
@@ -139,13 +139,26 @@ Hermes-анализ показал: Pegas сильна в **«detect»** (verify
|
||||
- **Tier 2 — средний приоритет**
|
||||
- ② **Самообучение правил инференции** — `memory_infer` **предлагает кандидаты**
|
||||
`logical_rule` на ревью (никогда не применяет автоматически).
|
||||
- ⑤ **Атомные паттерны действий** — агент действует (это я через `mcp__pegas-memory__*`),
|
||||
поэтому повторы успешных `/запрос` или воркфлоу ≥N раз с `verified`-результатом →
|
||||
**атомный** паттерн-рецепт (не файлы Hermes, а атомно с dedup).
|
||||
- ⑤ **Процедурная/рецепт-память** (паттерн из mem0, `procedural memory`) — agent действует
|
||||
(это я через `mcp__pegas-memory__*`), поэтому повторы успешных `/запрос` или воркфлоу ≥N
|
||||
раз с `verified`-результатом → **атомный** паттерн-рецепт (не файлы Hermes, а атомно с
|
||||
dedup). Формат receipt: **goal → шаги → условия → результат** (переиспользуемый воркфлоу).
|
||||
- **Tier 3 — структурные**
|
||||
- ④ **Скунт-скан** — периодический бэч-проход графа на противоречия → авто gap.
|
||||
- ⑥ **Авто-обнаружение gap** — `verify` открывает gap на конфликт/дыру в источнике.
|
||||
|
||||
### Перенимаемое из mem0 (паттерны, а не таксомология)
|
||||
|
||||
- **Процедурный receipt** (`goal -> шаги -> условия -> результат`) — структура переиспользуемого
|
||||
воркфлоу (mem0 `procedural memory`). Хранится как типизированный атом с dedup, не как
|
||||
накопитель markdown-файлов (как у Hermes) -> no prompt-bloat.
|
||||
- **гибридный retrieval** (cache + vector + graph rerank) — поднимает recall у слабо-релевантных
|
||||
и низкоуверенных атомов. Механизм: recent-cache (Qdrant) + reranking по graph-ёбрам.
|
||||
- **Entity resolution** — объединение вариантов одной entity между источниками (против
|
||||
фрагментации атомов на «один объект, разные формулировки»).
|
||||
|
||||
> Таксомология «эпизод/declarative/процедур» не вводится: declarative = атомы, эпизод =
|
||||
`pm_episodic_trace`, новый только процедурный ⑵. Перенимаем паттерны, а не метки.
|
||||
### Atom-efficiency guardrail (обязательное)
|
||||
|
||||
Чтобы self-improvement **не скатился в гермесовский файловый балласт**, все записи и
|
||||
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
# Pegas Memory — Roadmap
|
||||
|
||||
Подсистема памяти и базы знаний агента Alicorn («Pegas»). Реализация на Python как отдельный
|
||||
сервис, который Rust-ядро Alicorn вызывает через MCP/HTTP. Спецификация — в
|
||||
`alicorn-agent/ARCHITECTURE.md` (ADR-4, ADR-11, ADR-12).
|
||||
|
||||
## Принятые решения (по итогам обсуждения)
|
||||
|
||||
1. **PostgreSQL = единственный источник истины.** Текст, метаданные, трейсы, верификация, outbox.
|
||||
2. **Qdrant = векторный срез** (EmbeddingGemma 2, dim=768). Замена pgvector.
|
||||
3. **Memgraph = графовый срез** (связи атомов, зависимости кода). Замена Apache AGE.
|
||||
4. **pgvector и AGE — НЕ используем.** Векторы только в Qdrant, граф только в Memgraph.
|
||||
5. **Единица знания — типизированный «атом»**, не чистый текст.
|
||||
Типы: `text | definition | logical_rule | code | table | fact`.
|
||||
6. **Память агента (episodic) ≠ база знаний (curated).** Разные таблицы/подсистемы.
|
||||
7. **Код хранится отдельно**: content-addressed исходники + tree-sitter символы + граф зависимостей.
|
||||
8. **Логические знания** — структурные правила (pattern→conclusion) с инференцией в графе.
|
||||
9. **Исследование пробелов** — замкнутый цикл: detect→plan→acquire→parse→extract→value→verify→commit.
|
||||
|
||||
## Инфраструктура (проверено на сервере)
|
||||
|
||||
| Компонент | Адрес | Состояние |
|
||||
|---|---|---|
|
||||
| PostgreSQL 16 | atom-db :5434 (user atom, db content_atom) | работает |
|
||||
| Qdrant | :6333 | работает |
|
||||
| Memgraph (bolt) | :7687 | работает |
|
||||
| Ollama | :11434 | работает |
|
||||
| EmbeddingGemma 2 | `embeddinggemma-2-740m-Q8_0` | dim=768, R@1 0.922 (лучший для ru) |
|
||||
| LLM-генерация | `lfm25-24b-a2b:128k`, `qwen3.5:4b`, `gemma4:E4B` | работает |
|
||||
|
||||
> EmbeddingGemma 2: полная размерность 768 (проверено curl-тестом). Q8_0 — оптимальный
|
||||
> баланс производительность/память (MRR 0.944, не теряет производительность). Не путать с v1 `embeddinggemma:300m`.
|
||||
|
||||
## Модель данных (PostgreSQL — канон)
|
||||
|
||||
```
|
||||
document — источники (web|pdf|epub|text|code_repo), uri, authority, content_hash
|
||||
chunk — чистые сегменты (доказательства, locator) — НЕ для извлечения напрямую
|
||||
atom — типизированные единицы знания (заявление + контент + доверие + статус)
|
||||
atom_link — связи (inference|cause|reference|contradicts|depends_on|calls|defines)
|
||||
citation — доказательная база (atom → document → locator → quoted_text)
|
||||
code_symbol — tree-sitter символы (repo, path, language, name, kind, signature)
|
||||
episodic_trace— память агента (шаги/действия) — отдельно от базы знаний
|
||||
research_gap — выявленные пробелы для исследования
|
||||
outbox — CDC-журнал для синхронизации в Qdrant + Memgraph
|
||||
```
|
||||
|
||||
Статусы атома: `candidate → verified | stale | contested`.
|
||||
Векторы НЕ хранятся в Postgres — только в Qdrant (payload: type/confidence/status/doc_id).
|
||||
|
||||
## Фазы
|
||||
|
||||
### Фаза 1 — Фундамент (MVP) ✅ ЗАВЕРШЕНА
|
||||
- [x] Структура проекта + venv + зависимости
|
||||
- [x] DDL Postgres (schema.sql)
|
||||
- [x] Клиент эмбеддингов EmbeddingGemma 2 (dim=768)
|
||||
- [x] Клиент Qdrant (коллекция `alicorn_atoms`)
|
||||
- [x] Клиент Memgraph (узлы atom + рёбра atom_link)
|
||||
- [x] Ингест: text/pdf/epub/web → чанки
|
||||
- [x] Дистилляция чанка → атомы (LLM)
|
||||
- [x] Синхронизация outbox PG → Qdrant + Memgraph
|
||||
- [x] Smoke-тест end-to-end
|
||||
|
||||
### Фаза 2 — Исследование пробелов ✅ (реализовано, snippet-fallback)
|
||||
- [x] Детект пробелов (research_gap + add_gap/list_gaps)
|
||||
- [x] Планирование (приоритетная очередь пробелов)
|
||||
- [x] Acquire: web-поиск (3 источника) + pdf/epub/text
|
||||
- [x] Оценка ценности (verify_atom + min_confidence)
|
||||
- [~] Верификация (verify_atom готов; полный автономный запуск требует прокси для зарубежных сайтов)
|
||||
|
||||
### Фаза 3 — Код ✅ / Логика ✅
|
||||
- [x] tree-sitter: извлечение символов (function/class/method/type) — 43 символа сохранено
|
||||
- [x] Граф зависимостей кода (calls/imports/inherits) — 310 зависимостей, 162 узла CodeSymbol
|
||||
- [x] Логические правила + инференция в Memgraph (forward-chaining до fixpoint, 38 рёбер выведено)
|
||||
|
||||
### Фаза 4 — Интеграция с DSH (MCP) ✅ ВЫПОЛНЕНА
|
||||
- [x] MCP-сервер (memory_search/store/ingest/add_gap/list_gaps/research/stats/get_context)
|
||||
- [x] Подключение к DSH через @deepseek-ai/dsh-mcp-client (cordis.patch.yml, live-reload)
|
||||
- [ ] Подключение к Rust-ядру Alicorn (Planner/Researcher) — когда ядро будет готово
|
||||
|
||||
## Дополнительно реализовано
|
||||
- Опциональный прокси (PROXY_URL, SOCKS5/HTTP) + улучшенный User-Agent для полной загрузки страниц.
|
||||
|
||||
- Фильтрация артефактов графа кода (dst="." от относительных импортов).
|
||||
- Дедупликация в memory_store (опциональный dedup).
|
||||
(после MVP)
|
||||
- Семантическая дедупликация атомов (эмбеддинги EmbeddingGemma 2, порог 0.90, конфигуруемо).
|
||||
- Фильтрация шумных logical_rule (только kind-рёбры) в инференции.
|
||||
|
||||
## Критические риски
|
||||
- EmbeddingGemma 2 dim=768 — не совместима с bge-m3 (1024) → отдельная коллекция, без миграции.
|
||||
- Memgraph in-memory: объём графа ограничен RAM.
|
||||
- Дистилляция зависит от качества локальной LLM — нужна верификация.
|
||||
|
||||
## Самообучение (self-improvement) — статус и планы
|
||||
|
||||
### Что работает (4 механизма, но НЕ замкнутый loop)
|
||||
|
||||
1. **Верификация** (`verify_atom`/`memory_verify` + `verify.py`). LLM self-critique
|
||||
(`duplicate | corroborates | contradicts`) + **меж-системная подтверждение** (≥1 другой
|
||||
`doc_id`, cosine ≥ 0.90) → ставка растёт, статус `verified`. Самый зрелый этап.
|
||||
2. **Логическая инференция** (`memory_infer` + `inference.py`). Применение правил к рёбрам
|
||||
графа до fixpoint (`imports → depends_on` и т.д.). ⚠️ Даст **только связи**, не новые факты.
|
||||
Правила **статичные/ручное написание**, новых не выводит сама.
|
||||
3. **Синтез контекста** (`memory_get_context`). Ищет Qdrant, кластеризует + суммирует атомы.
|
||||
Может **создавать gap** из исходного текста → есть *реактивное* появление вопроса из источника.
|
||||
4. **Эпизодические следы** (`pm_episodic_trace`). План/действие/наблюдение/рефлексия —
|
||||
отдельно от БЗ. Самый «рефлексивный», но **условный**, не привязанный к gap.
|
||||
|
||||
### Что не хватает (дыры в петлях, а не в примитивах)
|
||||
|
||||
| Пробел | Почему критично |
|
||||
|---|---|
|
||||
| **① цепочка gap↛answer («дыра commit»)** | При закрытии вакуума **ответ не автоматически
|
||||
пишется обратно в атомы** → знания улетучиваются, приходится пере-исследовать. |
|
||||
| **② Самообучение схемы инференции** | Ничего не *предлагает новые правила* из повторяющихся
|
||||
`verified`-атомов. Это как раз слабое место Hermes-аналога. |
|
||||
| **③ Застарелость/забывание (staleness guard)** | `verify` ставит `verified`, но **ничто не
|
||||
помечает `stale`** пере-проверкой по свежему источнику. Путь →`stale` не идёт автоматически. |
|
||||
| **④ Поверхность противоречий** | `verify` ловит конфликт только в окрестности атома. Ничего
|
||||
не сканирует весь граф → противоречия не переходят в gap автоматически. |
|
||||
| **⑤ Процедурная/рецепт-память** | Повторяющиеся успешные воркфлоу не ловятся как переиспользуемые атомы. |
|
||||
| **⑥ Пассивное создание gap** | Gap создаются через `add_gap` (ручно) или из `memory_get_context`.
|
||||
Нет авто-обнаружения из не-верифицированного/переносного контента. |
|
||||
|
||||
### Приоритет
|
||||
|
||||
Hermes-анализ показал: Pegas сильна в **«detect»** (verify, infer), слаба в **«commit»** и
|
||||
**«maintain»**. Слабые места — **feedback-петли**, а не примитивы. Поэтому максимальный выигрыш:
|
||||
① дыра «commit» × ③ гвард сталкнутости × ② самообучение правил инференции — это **закрывает loop**.
|
||||
|
||||
### Планируемые улучшения (Tier)
|
||||
|
||||
- **Tier 1 — высокий приоритет, безопасно / малый**
|
||||
- ① **Окончите дырой** — после `verify`, подняв атомы из gap, запустить синтез обратно в
|
||||
`memory_ingest/synthesis` (надпись верифицированного ответа в атомы).
|
||||
- ③ **Гвард сталкнутости** — `update_status`: пере-`web_search` по URL/date атома;
|
||||
противоречит/устарел → `stale`. Реализуйте путь →`stale`, который сейчас не ходит.
|
||||
- **Tier 2 — средний приоритет**
|
||||
- ② **Самообучение правил инференции** — `memory_infer` **предлагает кандидаты**
|
||||
`logical_rule` на ревью (никогда не применяет автоматически).
|
||||
- ⑥ **Процедурная/рецепт-память** (паттерн из mem0, `procedural memory`) — агент действует
|
||||
(это я через `mcp__pegas-memory__*`), поэтому повторы успешных `/запрос` или воркфлоу ≥N
|
||||
раз с `verified`-результатом → **атомный** паттерн-рецепт (не файлы Hermes, а атомно с
|
||||
dedup). Формат receipt: **goal → шаги → условия → результат** (переиспользуемый воркфлоу).
|
||||
- **Tier 3 — структурные**
|
||||
- ④ **Сканирование на противоречия** — периодический бэк-проход графа на противоречия → авто gap.
|
||||
- ⑥ **Авто-обнаружение gap** — `verify` открывает gap на конфликт/дыру в источнике.
|
||||
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env python3
|
||||
"""en2ru — English-source-of-truth -> Russian comprehension doc.
|
||||
|
||||
RULE (see DOCSTRAT.md): English is the CANONICAL source of truth. Russian is
|
||||
only a comprehension aid; terminology may drift and MUST NEVER be used as the
|
||||
editing basis. Always edit the `*.md` (EN), then re-run this to refresh
|
||||
`<file>.ru.md`.
|
||||
|
||||
Usage:
|
||||
python3 en2ru.py path/to/doc.md # writes path/to/doc.ru.md
|
||||
cat doc.md | python3 en2ru.py - # stdin -> stdout + doc.ru.md
|
||||
|
||||
Model: translategemma:latest (Ollama, local @ 127.0.0.1:11434).
|
||||
Jargon drift hints are printed to STDERR (never inside the RU output).
|
||||
No external deps (urllib only) so it works offline after the model is pulled.
|
||||
"""
|
||||
import sys
|
||||
import json
|
||||
import urllib.request
|
||||
|
||||
OLLAMA_URL = "http://127.0.0.1:11434/v1/chat/completions"
|
||||
MODEL = "translategemma:latest"
|
||||
|
||||
# Terms TranslateGemma-4b mishandles -> flag for human review (never auto-fix).
|
||||
# Maps the EN token to the safe RU handling. JAPN is intentional: keep short.
|
||||
JARGON_HINTS = [
|
||||
("dedup", "дедупляция / удаление дублей"), # NOT «дублирование» (reversed!)
|
||||
("receipt", "рецепт (паттерн действий)"), # NOT «результат»
|
||||
("atom-level", "на уровне атомов"),
|
||||
("stale", "устаревший (status=stale)"),
|
||||
("gap", "пробел (gap)"),
|
||||
("verify", "верификация / verify"),
|
||||
("rerank", "реранг / reranking"),
|
||||
("cache", "кэш"),
|
||||
("inferred", "выведено / inferred"),
|
||||
("web_search", "web_search (инструмент)"),
|
||||
("ingest", "ингестия / загрузка / ingest"),
|
||||
]
|
||||
|
||||
|
||||
def translate(text: str) -> str:
|
||||
prompt = (
|
||||
"Translate the following Markdown technical text to Russian.\n"
|
||||
"Rules:\n"
|
||||
"- Output ONLY the Russian text. Preserve Markdown structure, code blocks,\n"
|
||||
" backticks, code identifiers, URLs, command and tool names verbatim.\n"
|
||||
"- Do NOT translate: code, identifiers, tool names, file extensions, URLs,\n"
|
||||
" and product names (Memgraph, PostgreSQL, Qdrant, Memgraph).\n"
|
||||
"- If unsure about a term, keep it as-is in Latin (do not guess).\n"
|
||||
"- Words you must handle carefully: "
|
||||
+ ", ".join(en for en, _ in JARGON_HINTS) + ".\n\n"
|
||||
"TEXT:\n```\n" + text + "\n```"
|
||||
)
|
||||
payload = {
|
||||
"model": MODEL,
|
||||
"stream": False,
|
||||
"messages": [{"role": "user", "content": prompt}],
|
||||
}
|
||||
req = urllib.request.Request(
|
||||
OLLAMA_URL,
|
||||
data=json.dumps(payload).encode("utf-8"),
|
||||
headers={"Content-Type": "application/json"},
|
||||
)
|
||||
with urllib.request.urlopen(req, timeout=300) as resp:
|
||||
return json.loads(resp.read())["choices"][0]["message"]["content"]
|
||||
|
||||
|
||||
def main() -> None:
|
||||
if len(sys.argv) < 2 or sys.argv[1] == "-":
|
||||
src = sys.stdin.read()
|
||||
base = "doc"
|
||||
else:
|
||||
with open(sys.argv[1], encoding="utf-8") as fh:
|
||||
src = fh.read()
|
||||
base = sys.argv[1].rsplit(".", 1)[0]
|
||||
|
||||
ru = translate(src)
|
||||
# model echoes the prompt's ``` fences -> drop leading/trailing fence lines
|
||||
lines = ru.splitlines()
|
||||
if lines and lines[0].strip() == "```":
|
||||
lines = lines[1:]
|
||||
if lines and lines[-1].strip() == "```":
|
||||
lines = lines[:-1]
|
||||
ru = "\n".join(lines).strip()
|
||||
out_path = base + ".ru.md"
|
||||
with open(out_path, "w", encoding="utf-8") as fh:
|
||||
fh.write(ru)
|
||||
|
||||
low = src.lower()
|
||||
print("# en2ru -> " + out_path, file=sys.stderr)
|
||||
for en, hint in JARGON_HINTS:
|
||||
if en.lower() in low:
|
||||
print(" review: '%s' -> ensure '%s'" % (en, hint), file=sys.stderr)
|
||||
print("OK: " + out_path)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user