OpenViking Memory Directories Split by Language: Unify With Custom Templates
OpenViking memory paths ended up with two parallel directory trees: entities/infrastructure/ and entities/基础设施/ holding the same kind of content. The cause is in the session commit auto-extraction pipeline, which names directories in the detected conversation language. Editing the memory template fixes the naming at the source; steps below.
Symptom
viking://user/<user>/memories/entities/ contained both:
entities/infrastructure/ ← dmit.md, surface.md (written by Hermes via viking_remember)
entities/基础设施/ ← backrest_backup.md, legion_wsl.md (auto-extracted by session commit)
entities/services/ ← hermes_gateway_sessions.md
entities/服务/ ← same content, second copyThe two write paths use different directory languages: Hermes writes English directories, OpenViking’s auto-extraction writes Chinese ones, splitting the same class of content in two.
Root cause
During session commit, OpenViking detects the output language from conversation content (_detect_language() in session_extract_context_provider.py). A Chinese conversation sets the template variable {{ language }} to zh-CN.
In the memory type YAML templates, the entities directory comes from the category field:
# prompts/templates/memory/entities.yaml
filename_template: "{{ category }}/{{ name }}.md"
fields:
- name: category
description: |
Category written in {{ language }}.
{% if language == 'en' %}Use lowercase with underscores, max 3 words.{% else %}Keep it concise and natural in {{ language }}.{% endif %}The language-adaptive instruction makes the LLM write category in Chinese (“基础设施”, “服务”), producing Chinese directories. The name field already allows Chinese or English, and filenames do not affect path-level consistency, so leave it alone.
Editing the template
OpenViking supports memory.custom_templates_dir: YAML files loaded from this directory override built-in templates of the same name (MemoryTypeRegistry.load_from_directory(..., replace=True)).
- Copy the built-in entities.yaml to the custom directory:
mkdir -p /path/to/openviking/data/custom_templates
podman cp systemd-openviking:/app/.venv/lib/python3.13/site-packages/openviking/prompts/templates/memory/entities.yaml \
/path/to/openviking/data/custom_templates/entities.yaml- Change the category description to be unconditionally English (independent of
{{ language }}):
# custom_templates/entities.yaml
- name: category
type: string
description: |
ALWAYS English: lowercase with underscores, max 3 words.
Never use Chinese or any other language for this field, even if the conversation is in Chinese.
merge_op: immutableLeave the name field untouched.
- Enable it in
ov.conf(container path/app/.openviking/ov.conf):
"memory": {
"custom_templates_dir": "/app/.openviking/custom_templates"
}- Restart the service to apply.
Verification
After the template change, new entities extracted from normal conversations all land in English directories:
| Entity mentioned in chat | Resulting path |
|---|---|
| netcup server | entities/infrastructure/netcup.md (merged into existing English dir) |
| wireguard tunnel | entities/networking/wireguard_tunnel.md |
| PEAK (co-op climbing game with mods) | entities/game/peak.md |
No new Chinese directories. Event filenames may still be Chinese (events/2026/08/12/WireGuard隧道配置完成.md) — filenames do not affect path-level consistency.
Other memory types (events, preferences, cases, …) use fixed directory structures (dates, usernames) with no LLM-named directory level, so they need no changes.