feat(config): named LLM provider list via env vars, runtime selection
- Config.llm_profiles: LLM_PROVIDERS declares names, each group defined by LLM_<NAME>_BASE_URL/_API_KEY/_MODEL (required) and optional _TIMEOUT_SECONDS/ _MAX_RETRIES/_TEMPERATURE/_EXTRA_BODY; JSON-dict form of LLM_PROVIDERS also supported. LLM_PROVIDER selects the active group at runtime; empty/fake = offline scripted model - removed fixed openai/kimi groups (AGENT_LLM_PROVIDER, KIMI_LLM_*) - validate(): incomplete groups and unknown LLM_PROVIDER fail fast with the configured-name list - OpenAILLMService: http client trust_env from LLM_HTTP_TRUST_ENV (default False - local gateways must bypass the Windows system proxy) - build_llm_service(provider): explicit name or LLM_PROVIDER default - .env/.env.example: deepseek + kimi groups side by side, switch by LLM_PROVIDER=kimi (thinking off via EXTRA_BODY reasoning_effort=none) - eval probe scripts updated to the new config interface Verified: 172 unit tests; live calls succeed on both providers (deepseek 28s, kimi 6.6s, both emitting valid <state> prefixes)
This commit is contained in:
@@ -39,13 +39,13 @@ def main():
|
||||
path = args.prompt_dir / (name+'.md')
|
||||
return path.read_text(encoding='utf-8') if path.exists() else original_loader(name)
|
||||
registry.load_prompt = snapshot_loader
|
||||
if Config.AGENT_BACKEND != 'langgraph' or Config.AGENT_LLM_PROVIDER != 'openai':
|
||||
if Config.AGENT_BACKEND != 'langgraph' or not Config.LLM_PROVIDER or Config.LLM_PROVIDER == 'fake':
|
||||
raise SystemExit('Requires langgraph backend and real openai provider')
|
||||
args.output_dir.mkdir(parents=True, exist_ok=True)
|
||||
cases = load_cases(DEFAULT_CASES_DIR, args.case)
|
||||
from src.agent.prompts import load_prompt
|
||||
metadata = {
|
||||
'model': Config.LLM_MODEL, 'temperature': Config.LLM_TEMPERATURE,
|
||||
**{k: v for k, v in (Config.llm_profile(Config.LLM_PROVIDER) or {}).items() if k in ('model', 'temperature')},
|
||||
'backend': Config.AGENT_BACKEND, 'workers': args.workers,
|
||||
'commit': subprocess.check_output(['git', 'rev-parse', 'HEAD'], text=True).strip(),
|
||||
'case_hashes': {str(p.relative_to(DEFAULT_CASES_DIR)): sha256(p.read_bytes()).hexdigest()
|
||||
|
||||
@@ -63,7 +63,7 @@ async def main(args):
|
||||
if args.prompt_dir:
|
||||
import src.agent.prompts as registry
|
||||
registry.load_prompt = lambda name: (args.prompt_dir / (name+'.md')).read_text(encoding='utf-8')
|
||||
llm = build_llm_service('openai')
|
||||
llm = build_llm_service()
|
||||
semaphore = asyncio.Semaphore(4)
|
||||
async def run(case):
|
||||
async with semaphore:
|
||||
@@ -107,7 +107,8 @@ async def main(args):
|
||||
results = await asyncio.gather(*(run(c) for c in selected))
|
||||
from src.core.config import Config
|
||||
from src.agent.prompts import load_prompt
|
||||
output = dict(model=Config.LLM_MODEL, temperature=Config.LLM_TEMPERATURE,
|
||||
profile = Config.llm_profile(Config.LLM_PROVIDER) or {}
|
||||
output = dict(model=profile.get('model'), temperature=profile.get('temperature'),
|
||||
execution_mode='runtime' if args.runtime else 'raw_prompt',
|
||||
prompt_hashes={name:sha256(load_prompt(name).encode('utf-8')).hexdigest() for name in (COLLECTION,EXTRACTION)},
|
||||
passed=sum(r['passed'] for r in results), total=len(results), results=results)
|
||||
|
||||
@@ -26,7 +26,7 @@ def parsed_time(value):
|
||||
|
||||
|
||||
async def main(output):
|
||||
llm = build_llm_service('openai')
|
||||
llm = build_llm_service()
|
||||
cases = []
|
||||
for delay in (75,135):
|
||||
cases.append(dict(name=f'anchored_cross_midnight_delay_{delay}',now=ORIGIN+timedelta(minutes=delay),
|
||||
|
||||
Reference in New Issue
Block a user