Merge remote-tracking branch 'origin/main'
This commit is contained in:
@@ -1,133 +0,0 @@
|
|||||||
# План: Вынести хардкод stable-блоков system prompt в файлы
|
|
||||||
|
|
||||||
**Статус:** Реализовано ✅ (ждёт перезапуска webhook)
|
|
||||||
|
|
||||||
## Мотивация
|
|
||||||
|
|
||||||
В Hermes Whale все stable-блоки system prompt (identity, guidance, enforcement) захардкожены в `agent/prompt_builder.py` как Python-константы. Невозможно изменить их без редактирования исходного кода Hermes Agent.
|
|
||||||
|
|
||||||
## Решение
|
|
||||||
|
|
||||||
Вынести каждый блок в отдельный `.md` файл, добавить маппинг в `config.yaml: agent.prompt_overrides`, и модифицировать `agent/system_prompt.py`, чтобы он читал файлы вместо констант.
|
|
||||||
|
|
||||||
## Изменяемые файлы
|
|
||||||
|
|
||||||
### 1. `agent/system_prompt.py` — замена констант на file-load
|
|
||||||
|
|
||||||
Добавлена функция `_load_prompt_block(agent, block_name, default_text)` — строки 51-71 в `/Users/admin/.hermes/hermes-agent/agent/system_prompt.py`:
|
|
||||||
- Читает `agent._prompt_overrides` (берётся из конфига на старте)
|
|
||||||
- Если для `block_name` указан путь — читает файл, возвращает его содержимое
|
|
||||||
- Иначе возвращает `default_text`
|
|
||||||
|
|
||||||
Заменены все 7 прямых ссылок на константы в `build_system_prompt_parts()` на вызовы `_load_prompt_block()`.
|
|
||||||
|
|
||||||
Добавлены импорты: `import logging`, `import os`, `from pathlib import Path`, `logger = logging.getLogger(__name__)`.
|
|
||||||
|
|
||||||
**Константы, которые заменяются (7 блоков):**
|
|
||||||
|
|
||||||
| Блок | Константа | Вставляется при условии |
|
|
||||||
|------|-----------|------------------------|
|
|
||||||
| `hermes_help` | `HERMES_AGENT_HELP_GUIDANCE` | всегда |
|
|
||||||
| `task_completion` | `TASK_COMPLETION_GUIDANCE` | всегда |
|
|
||||||
| `memory_guidance` | `MEMORY_GUIDANCE` | когда есть tool "memory" |
|
|
||||||
| `session_search_guidance` | `SESSION_SEARCH_GUIDANCE` | когда есть tool "session_search" |
|
|
||||||
| `skills_guidance` | `SKILLS_GUIDANCE` | когда есть tool "skill_manage" |
|
|
||||||
| `tool_use_enforcement` | `TOOL_USE_ENFORCEMENT_GUIDANCE` | зависит от модели |
|
|
||||||
| `execution_discipline` | `OPENAI_MODEL_EXECUTION_GUIDANCE` | зависит от модели |
|
|
||||||
|
|
||||||
**Не заменяется (остаётся в коде):**
|
|
||||||
- `DEFAULT_AGENT_IDENTITY` — это fallback когда нет SOUL.md (у нас есть SOUL.md, не нужно)
|
|
||||||
- `GOOGLE_MODEL_OPERATIONAL_GUIDANCE` — Google-specific, неактуально для Whale
|
|
||||||
- `COMPUTER_USE_GUIDANCE` — нет toolset
|
|
||||||
- `KANBAN_GUIDANCE` — нет kanban
|
|
||||||
- `PLATFORM_HINTS` — platform-specific, другая логика
|
|
||||||
|
|
||||||
### 2. `agent/system_prompt.py` — добавить функцию загрузки
|
|
||||||
|
|
||||||
```python
|
|
||||||
def _load_prompt_block(agent, block_name: str, default: str) -> str:
|
|
||||||
"""Load a prompt block from a file if configured, else return default."""
|
|
||||||
overrides = getattr(agent, "_prompt_overrides", None) or {}
|
|
||||||
path = overrides.get(block_name)
|
|
||||||
if path:
|
|
||||||
try:
|
|
||||||
resolved = os.path.expanduser(path)
|
|
||||||
content = Path(resolved).read_text(encoding="utf-8").strip()
|
|
||||||
if content:
|
|
||||||
return content
|
|
||||||
except Exception:
|
|
||||||
logger.debug("Could not load prompt override '%s' from %s", block_name, path)
|
|
||||||
return default
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. `agent/agent_init.py` — пробросить конфиг
|
|
||||||
|
|
||||||
После загрузки `_agent_cfg` (строка ~1058) добавлено чтение `agent.prompt_overrides`:
|
|
||||||
|
|
||||||
```python
|
|
||||||
agent._prompt_overrides = {}
|
|
||||||
try:
|
|
||||||
_po = _agent_cfg.get("agent", {}).get("prompt_overrides", {})
|
|
||||||
if isinstance(_po, dict):
|
|
||||||
agent._prompt_overrides = _po
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Конфиг Whale — `config.yaml`
|
|
||||||
|
|
||||||
Добавить секцию:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
agent:
|
|
||||||
prompt_overrides:
|
|
||||||
hermes_help: ~/.hermes/hermes-whale/review/hermes_help.md
|
|
||||||
task_completion: ~/.hermes/hermes-whale/review/task_completion.md
|
|
||||||
memory_guidance: ~/.hermes/hermes-whale/review/memory_guidance.md
|
|
||||||
session_search_guidance: ~/.hermes/hermes-whale/review/session_search_guidance.md
|
|
||||||
skills_guidance: ~/.hermes/hermes-whale/review/skills_guidance.md
|
|
||||||
tool_use_enforcement: ~/.hermes/hermes-whale/review/tool_use_enforcement.md
|
|
||||||
execution_discipline: ~/.hermes/hermes-whale/review/execution_discipline.md
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. Файлы блоков
|
|
||||||
|
|
||||||
Создать 7 файлов в `~/.hermes/hermes-whale/review/`:
|
|
||||||
|
|
||||||
- `hermes_help.md` — содержимое константы `HERMES_AGENT_HELP_GUIDANCE`
|
|
||||||
- `task_completion.md` — содержимое `TASK_COMPLETION_GUIDANCE`
|
|
||||||
- `memory_guidance.md` — содержимое `MEMORY_GUIDANCE`
|
|
||||||
- `session_search_guidance.md` — содержимое `SESSION_SEARCH_GUIDANCE`
|
|
||||||
- `skills_guidance.md` — содержимое `SKILLS_GUIDANCE`
|
|
||||||
- `tool_use_enforcement.md` — содержимое `TOOL_USE_ENFORCEMENT_GUIDANCE`
|
|
||||||
- `execution_discipline.md` — содержимое `OPENAI_MODEL_EXECUTION_GUIDANCE`
|
|
||||||
|
|
||||||
### 6. Обратная совместимость
|
|
||||||
|
|
||||||
Если `prompt_overrides` не задан или файл не найден — используется хардкод. Никакой код не ломается для других профилей/пользователей.
|
|
||||||
|
|
||||||
### 7. Документация
|
|
||||||
|
|
||||||
- Обновить `personal/plans/thread-scoped-memory.md` → переименовать или создать отдельный doc
|
|
||||||
- Создать `personal/plans/extract-stable-prompt-blocks.md` (этот)
|
|
||||||
|
|
||||||
## Порядок выполнения
|
|
||||||
|
|
||||||
1. ✅ Создать 7 файлов блоков в `~/.hermes/hermes-whale/review/`
|
|
||||||
2. ✅ Пропатчить `agent/system_prompt.py` — добавить `_load_prompt_block()` и заменить 7 констант
|
|
||||||
3. ✅ Пропатчить `agent/agent_init.py` — пробросить `prompt_overrides` из конфига
|
|
||||||
4. ✅ Обновить `config.yaml` — добавить `agent.prompt_overrides` (через копию, т.к. patch блокирован TIRITH)
|
|
||||||
5. ⏸️ Перезапустить webhook (ждёт команды)
|
|
||||||
6. ⏸️ Обновить Obsidian docs (этот шаг)
|
|
||||||
|
|
||||||
## Проверка
|
|
||||||
|
|
||||||
После изменений system prompt должен содержать те же блоки, что и раньше, но загруженные из файлов. При изменении файла и рестарте сессии — новый текст. При удалении файла — fallback на хардкод.
|
|
||||||
|
|
||||||
## Pitfalls
|
|
||||||
|
|
||||||
- **TIRITH блокирует patch/config.yaml** — `config.yaml` под защитой TIRITH, patch и write_file отказываются писать в него. Решение: `cp` в `/tmp/`, отредактировать там, `cp` обратно (с аппрувом).
|
|
||||||
- **sed не подходит для YAML конфигов** — сложные многострочные замены с вложенными отступами и escape-символами (`~`, `/`) ломаются в sed. Лучше patch.
|
|
||||||
- **Конфиг всё равно просит аппрув** — при `cp` обратно TIRITH запрашивает подтверждение (overwrite project env/config file). Это нормально, нужно подтвердить.
|
|
||||||
- **SOUL.md уже существует** — в Whale он лежит в `/Users/admin/.hermes/hermes-whale/SOUL.md`. Он НЕ выносится через prompt_overrides, т.к. уже является файлом и загружается отдельно через `load_soul_md()`.
|
|
||||||
- **webhook не в PLATFORM_HINTS** — webhook нет в словаре `PLATFORM_HINTS` в `prompt_builder.py`, поэтому блок platform hints пустой. Это не менялось.
|
|
||||||
Reference in New Issue
Block a user