feat(runtime): implement single-article consolidation runtime and modularize codebase
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
"""Contract tests for runtime-config.schema.json."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import jsonschema
|
||||
import pytest
|
||||
|
||||
from src.runtime.core.config import create_schema_registry, load_runtime_config, load_schema
|
||||
|
||||
|
||||
def test_runtime_config_schema_validation_valid():
|
||||
schema = load_schema("runtime-config.schema.json")
|
||||
registry = create_schema_registry()
|
||||
validator = jsonschema.Draft202012Validator(schema, registry=registry)
|
||||
|
||||
valid_config = {
|
||||
"config_version": "1.0.0",
|
||||
"paths": {"output_dir": "out/articles", "sqlite_db": "out/runtime.db"},
|
||||
"roles": {
|
||||
"runtime_primary": {
|
||||
"role_config_version": "1.0.0",
|
||||
"provider": "groq",
|
||||
"model": "llama-3.1-8b-instant",
|
||||
"endpoint_url": "https://api.groq.com/openai/v1",
|
||||
"timeout_seconds": 30,
|
||||
"max_retries": 3,
|
||||
"parameters": {"temperature": 0.0},
|
||||
"hygiene_prompt_version": "1.0.0",
|
||||
"hygiene_schema_version": "1.0.0",
|
||||
"enrichment_prompt_version": "1.0.0",
|
||||
"enrichment_schema_version": "1.0.0",
|
||||
},
|
||||
"runtime_fallback": {
|
||||
"role_config_version": "1.0.0",
|
||||
"provider": "deepseek",
|
||||
"model": "deepseek-chat",
|
||||
"endpoint_url": "https://api.deepseek.com/v1",
|
||||
"timeout_seconds": 30,
|
||||
"max_retries": 3,
|
||||
"parameters": {"temperature": 0.0},
|
||||
"hygiene_prompt_version": "1.0.0",
|
||||
"hygiene_schema_version": "1.0.0",
|
||||
"enrichment_prompt_version": "1.0.0",
|
||||
"enrichment_schema_version": "1.0.0",
|
||||
},
|
||||
},
|
||||
"prompts": {
|
||||
"article_content_hygiene": {
|
||||
"path": "prompts/article_content_hygiene.v1.txt",
|
||||
"version": "1.0.0",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
},
|
||||
"article_sentiment_tags": {
|
||||
"path": "prompts/article_sentiment_tags.v1.txt",
|
||||
"version": "1.0.0",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
},
|
||||
},
|
||||
"ecp": {
|
||||
"canonical_schema_reference": "specs/006-article-consolidation-runtime/contracts/ecp-snapshot.schema.json",
|
||||
"classifier_module": "src.classifier.InherenceClassifier",
|
||||
},
|
||||
"limits": {"max_input_bytes": 1048576, "context_strategy": "fail_before_provider"},
|
||||
"pricing": {
|
||||
"primary_input_1k": 0.00005,
|
||||
"primary_output_1k": 0.00008,
|
||||
"fallback_input_1k": 0.00014,
|
||||
"fallback_output_1k": 0.00028,
|
||||
},
|
||||
"langfuse": {"environment": "local", "trace_content_policy": "metadata_only"},
|
||||
"sqlite": {"busy_timeout_ms": 5000},
|
||||
}
|
||||
|
||||
errors = list(validator.iter_errors(valid_config))
|
||||
assert len(errors) == 0, f"Schema validation errors: {[e.message for e in errors]}"
|
||||
|
||||
|
||||
def test_runtime_config_fixture_loads_successfully():
|
||||
config = load_runtime_config("runtime_config.local.json")
|
||||
assert config.config_version == "1.0.0"
|
||||
assert "runtime_primary" in config.roles
|
||||
assert "runtime_fallback" in config.roles
|
||||
assert config.roles["runtime_primary"].model == "llama-3.1-8b-instant"
|
||||
|
||||
|
||||
def test_runtime_config_rejects_powerful_models(tmp_path: Path):
|
||||
valid_base = json.loads(Path("runtime_config.local.json").read_text(encoding="utf-8"))
|
||||
valid_base["roles"]["runtime_primary"]["model"] = "gpt-4o" # Forbidden powerful model
|
||||
cfg_file = tmp_path / "invalid_cfg.json"
|
||||
cfg_file.write_text(json.dumps(valid_base), encoding="utf-8")
|
||||
|
||||
with pytest.raises(ValueError, match="Forbidden powerful model"):
|
||||
load_runtime_config(cfg_file)
|
||||
Reference in New Issue
Block a user