- Hybrid BM25 + HNSW vector search with context enrichment - Knowledge graph with entities, relations, and community detection - Host-following LLM route with fallback backends - 3-tier lint system (static + HNSW dup + contradiction detection) - Q&A Synthesis (Karpathy LLM Wiki pattern) - 16 MCP tools for agent-driven workflows - Incremental wiki generation with checkpointing - SQLite-backed item store with FTS5 + vector indexes
4.2 KiB
4.2 KiB
Host-Following LLM Spec
Status: proposed Owner: habraid Scope: wiki generation routing, config schema, host integration boundary
Goal
HaBraid의 wiki generation이 특정 provider/model에 고정되지 않고, 기본적으로 현재 host(Hermes/OpenClaw/Codex CLI)의 추론 정책을 따르도록 만든다.
Context
현재 habraid는 src/wiki/llm.ts에서 직접 외부 LLM backend를 호출한다. 이 구조는 다음 문제를 만든다.
- host와 habraid의 모델이 분리된다.
- quota / auth / provider routing이 이중화된다.
- 사용자는 "지금 네가 쓰는 모델로 해"를 기대하지만 habraid는 자체 config를 따른다.
HaBraid의 본질은 모델 선택이 아니라 memory backend를 wiki 표현층으로 변환하는 orchestration 이다.
Product Principles
- HaBraid는 저장소가 아니라 기억 시각화 계층이다.
- source of truth는 MemPalace/mem0 같은 memory backend에 있다.
- 위키는 사람과 AI의 공용 인터페이스다.
- 모델 선택은 기본적으로 host가 한다.
- raw memory는 의미 단위(topic/entity/decision/timeline)로 재구성된다.
Constraints
- 기존 standalone 실행 경로를 완전히 깨면 안 된다.
- 레거시 config(
provider/model/api_url/api_key_env)는 하위 호환해야 한다. - exact host model string은 있으면 좋지만 필수 의존성으로 삼지 않는다.
- host bridge가 unavailable일 수 있으므로 fallback 경로가 필요하다.
Non-Goals
- 이번 변경에서 MemPalace direct ingest 문제를 해결하지 않는다.
- 새로운 memory backend(mem0 등)를 실제로 붙이지 않는다.
- host와 완전한 양방향 protocol을 이번 단계에서 확정하지 않는다.
Desired Architecture
items/raw
↓
grouping + prompt building
↓
LLM gateway
├─ host mode (default)
│ └─ host가 실제 모델/정책 선택
└─ standalone mode / fallback
└─ openai | zai | ollama 직접 호출
↓
response normalization
↓
wiki files + sync state + logs
Routing Rules
Default behavior
llm.mode = "host"이면 host route를 먼저 시도한다.- host route가 사용 가능하면 실제 생성은 host가 수행한다.
- host가 어떤 provider/model을 썼는지는 optional metadata로만 기록한다.
Fallback behavior
- host route unavailable이면 configured fallback을 사용한다.
- fallback은 explicit config일 때만 활성화한다.
- fallback도 없으면 명확한 에러를 반환한다.
Standalone behavior
llm.mode = "standalone"이면 기존처럼 직접 backend를 호출한다.- 레거시 config는 내부적으로 standalone mode로 normalize한다.
Config Shape
{
"llm": {
"mode": "host",
"preferences": {
"priority": "balanced"
},
"fallback": {
"provider": "ollama",
"model": "qwen2.5:14b",
"api_url": "http://localhost:11434"
}
}
}
Legacy compatibility
{
"llm": {
"provider": "zai",
"model": "glm-5.1",
"api_url": "https://api.example.com/v1",
"api_key_env": "GLM_API_KEY",
"max_tokens": 4096
}
}
위 형태는 내부적으로 fallback/runtime config로 흡수된다. mode를 명시하지 않은 레거시 config는 기본적으로 host 모드를 따르고, 위 값들은 fallback/backend metadata로 유지된다.
Host Bridge Contract
interface HostInferenceBridge {
isAvailable(): Promise<boolean>;
generate(request: {
systemPrompt: string;
userPrompt: string;
maxTokens?: number;
preference?: "fast" | "balanced" | "smart";
}): Promise<{
text: string;
model?: string;
provider?: string;
}>;
}
Observability
최소한 다음 정보는 기록 가능해야 한다.
- 마지막 generation route (
host/fallback/standalone) - 마지막 provider/model (알 수 있을 때만)
- fallback 사용 여부
Done when
llm.mode = host | standalone구조가 코드와 문서에 반영된다.- host unavailable 시 fallback 규칙이 명확히 동작한다.
- generator가 특정 provider/model을 직접 전제하지 않는다.
- status/log에서 마지막 LLM route를 볼 수 있다.
- 기존 standalone config 사용자는 깨지지 않는다.