Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
| """Abstract LLM client interface.""" | |
| from __future__ import annotations | |
| import os | |
| import re | |
| from abc import ABC, abstractmethod | |
| from pathlib import Path | |
| import yaml | |
| def load_config(config_path: str = "config.yaml") -> dict: | |
| with open(config_path) as f: | |
| return yaml.safe_load(f) | |
| def load_prompt_template(template_path: str) -> str: | |
| return Path(template_path).read_text() | |
| # Strip HTML comments (maintainer-only notes) from knowledge files before | |
| # passing to LLM. Authors put checklists / cross-file-update warnings in | |
| # <!-- ... --> blocks at the top of each knowledge/*.md; those are meta | |
| # about how to edit the file, not content the LLM should read. | |
| _HTML_COMMENT_RE = re.compile(r"<!--.*?-->", re.DOTALL) | |
| def load_expert_knowledge(knowledge_path: str) -> str: | |
| path = Path(knowledge_path) | |
| if not path.exists(): | |
| return "" | |
| return _HTML_COMMENT_RE.sub("", path.read_text()).lstrip() | |
| class LLMClient(ABC): | |
| """Abstract base class for LLM backends.""" | |
| def call( | |
| self, | |
| prompt_template: str, | |
| variables: dict, | |
| expert_knowledge: str = "", | |
| seed: int | None = None, | |
| ) -> str: | |
| """Call the LLM with a prompt template, variables, and optional expert knowledge. | |
| Args: | |
| prompt_template: The prompt template string with {placeholders}. | |
| variables: Dictionary of variables to fill into the template. | |
| expert_knowledge: Expert knowledge text to inject via {expert_knowledge} placeholder. | |
| seed: Optional integer seed for sampling reproducibility. Local backends | |
| must honor this when temperature > 0; cloud backends (claude / | |
| claude-cli) currently raise NotImplementedError when seed is not None. | |
| Returns: | |
| The LLM's response text. | |
| """ | |
| def call_with_config( | |
| self, | |
| prompt_key: str, | |
| knowledge_key: str, | |
| variables: dict, | |
| config: dict | None = None, | |
| seed: int | None = None, | |
| ) -> str: | |
| """Convenience method: load prompt template and knowledge from config paths, then call. | |
| Args: | |
| prompt_key: Key in config['prompts'] for the prompt template file path. | |
| knowledge_key: Key in config['knowledge'] for the expert knowledge file path. | |
| variables: Dictionary of variables to fill into the template. | |
| config: Config dict. If None, loads from config.yaml. | |
| seed: Optional seed forwarded to the underlying call() (see LLMClient.call). | |
| """ | |
| if config is None: | |
| config = load_config() | |
| template = load_prompt_template(config["prompts"][prompt_key]) | |
| knowledge = load_expert_knowledge(config["knowledge"][knowledge_key]) | |
| return self.call(template, variables, knowledge, seed=seed) | |