Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ openkb lint

OpenKB comes with [multi-LLM support](https://docs.litellm.ai/docs/providers) (e.g., OpenAI, Claude, Gemini) via [LiteLLM](https://github.com/BerriAI/litellm) (pinned to a [safe version](https://docs.litellm.ai/blog/security-update-march-2026)).

Create a `.env` file with your LLM API key. Choose your LLM during `openkb init` or edit [`.openkb/config.yaml`](#configuration).
Create a `.env` file with your LLM API key. Choose your LLM during `openkb init` or edit [`.openkb/config.yaml`](#configuration) (model names follow [LiteLLM format](https://docs.litellm.ai/docs/providers), e.g. `gpt-5.4`, `anthropic/claude-sonnet-4-6`).

```bash
LLM_API_KEY=your_llm_api_key
Expand Down Expand Up @@ -141,12 +141,19 @@ Generated by `openkb init`, stored in `.openkb/config.yaml`:

```yaml
model: gpt-5.4 # LLM model (any LiteLLM-supported provider)
api_key_env: LLM_API_KEY # Environment variable for LLM API key
language: en # Wiki output language
pageindex_threshold: 20 # PDF pages threshold for PageIndex
pageindex_api_key_env: "" # (Optional) Environment variable for PageIndex Cloud API key
```

Model names follow [LiteLLM format](https://docs.litellm.ai/docs/providers):

| Provider | Model example |
|---|---|
| OpenAI | `gpt-5.4` |
| Anthropic | `anthropic/claude-sonnet-4-6` |
| Gemini | `gemini/gemini-3.1-pro-preview` |

### PageIndex integration

For long documents, relying solely on summaries often leads to information loss.
Expand Down
1 change: 0 additions & 1 deletion config.yaml.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
model: gpt-5.4 # LLM model (any LiteLLM-supported provider)
api_key_env: LLM_API_KEY # Environment variable for API key
language: en # Wiki output language
pageindex_threshold: 20 # PDF pages threshold for PageIndex
pageindex_api_key_env: "" # Env var name for PageIndex Cloud API key
20 changes: 10 additions & 10 deletions openkb/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@
load_dotenv()


def _setup_llm_key(config: dict) -> None:
"""Set LiteLLM API key from the configured env var (default: LLM_API_KEY)."""
env_var = config.get("api_key_env", DEFAULT_CONFIG["api_key_env"])
api_key = os.environ.get(env_var, "")
def _setup_llm_key() -> None:
"""Set LiteLLM API key from LLM_API_KEY env var if present."""
api_key = os.environ.get("LLM_API_KEY", "")
if api_key:
litellm.api_key = api_key

Expand Down Expand Up @@ -76,7 +75,7 @@ def _add_single_file(file_path: Path, kb_dir: Path) -> None:

openkb_dir = kb_dir / ".openkb"
config = load_config(openkb_dir / "config.yaml")
_setup_llm_key(config)
_setup_llm_key()
model: str = config.get("model", DEFAULT_CONFIG["model"])
registry = HashRegistry(openkb_dir / "hashes.json")

Expand Down Expand Up @@ -160,8 +159,10 @@ def init():
return

# Interactive prompts
model = click.prompt("Model", default=DEFAULT_CONFIG["model"])
api_key_env = click.prompt("API key env var", default=DEFAULT_CONFIG["api_key_env"])
model = click.prompt(
"Model (e.g. gpt-5.4, anthropic/claude-sonnet-4-6, gemini/gemini-3.1-pro-preview)",
default=DEFAULT_CONFIG["model"],
)
language = click.prompt("Language", default=DEFAULT_CONFIG["language"])
pageindex_threshold = click.prompt(
"PageIndex threshold (pages)",
Expand Down Expand Up @@ -193,7 +194,6 @@ def init():
openkb_dir.mkdir()
config = {
"model": model,
"api_key_env": api_key_env,
"language": language,
"pageindex_threshold": pageindex_threshold,
"pageindex_api_key_env": pageindex_api_key_env,
Expand Down Expand Up @@ -255,7 +255,7 @@ def query(question, save):

openkb_dir = kb_dir / ".openkb"
config = load_config(openkb_dir / "config.yaml")
_setup_llm_key(config)
_setup_llm_key()
model: str = config.get("model", DEFAULT_CONFIG["model"])

try:
Expand Down Expand Up @@ -320,7 +320,7 @@ def lint(fix):

openkb_dir = kb_dir / ".openkb"
config = load_config(openkb_dir / "config.yaml")
_setup_llm_key(config)
_setup_llm_key()
model: str = config.get("model", DEFAULT_CONFIG["model"])

# Structural lint
Expand Down
1 change: 0 additions & 1 deletion openkb/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

DEFAULT_CONFIG: dict[str, Any] = {
"model": "gpt-5.4",
"api_key_env": "LLM_API_KEY",
"language": "en",
"pageindex_threshold": 20,
"pageindex_api_key_env": "", # Set to env var name (e.g. PAGEINDEX_API_KEY) to use cloud PageIndex
Expand Down
3 changes: 0 additions & 3 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@

def test_default_config_keys():
assert "model" in DEFAULT_CONFIG
assert "api_key_env" in DEFAULT_CONFIG
assert "language" in DEFAULT_CONFIG
assert "pageindex_threshold" in DEFAULT_CONFIG
assert "pageindex_api_key_env" in DEFAULT_CONFIG


def test_default_config_values():
assert DEFAULT_CONFIG["model"] == "gpt-5.4"
assert DEFAULT_CONFIG["api_key_env"] == "LLM_API_KEY"
assert DEFAULT_CONFIG["language"] == "en"
assert DEFAULT_CONFIG["pageindex_threshold"] == 20

Expand All @@ -39,7 +37,6 @@ def test_save_load_roundtrip(tmp_path):
assert loaded["model"] == "gpt-3.5-turbo"
assert loaded["language"] == "fr"
# Defaults fill in missing keys
assert loaded["api_key_env"] == DEFAULT_CONFIG["api_key_env"]
assert loaded["pageindex_threshold"] == DEFAULT_CONFIG["pageindex_threshold"]


Expand Down