Route live research through llm-connect and record pilot findings

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a0cffe-206f-7323-89d3-b20ca4cf4bf9
This commit is contained in:
tegwick 2026-09-24 15:55:31 +02:00
parent 1f95f6389a
commit 2ec23bb22c
39 changed files with 2259 additions and 22 deletions

View file

@ -5,6 +5,8 @@ import argparse
import hashlib
import json
import re
from urllib import error, request
from urllib.parse import urlsplit
from pathlib import Path
import shutil
@ -12,7 +14,8 @@ import yaml
from infospace_bench import create_infospace, load_infospace, register_artifact
from infospace_bench.errors import InfospaceError
from infospace_bench.workflow import FixtureAssistedGenerationAdapter, run_workflow
from infospace_bench.openrouter import OpenRouterAssistedGenerationAdapter
from infospace_bench.workflow import AssistedGenerationResult
from llm_connect.models import RunConfig
REPO = Path(__file__).resolve().parents[1]
PROFILE = REPO / "research/bench/profile"
@ -83,6 +86,50 @@ def plan(root):
"review_status": "unreviewed"}
class LLMConnectAdapter:
"""Client of llm-connect's /execute contract; credentials stay at the service."""
def __init__(self, endpoint, model, max_tokens=4000):
parsed = urlsplit(endpoint)
if (parsed.scheme not in ("http", "https") or not parsed.hostname
or parsed.username or parsed.password or parsed.query or parsed.fragment):
raise ValueError("Use an HTTP(S) llm-connect URL without credentials or query")
if max_tokens <= 0:
raise ValueError("--max-tokens must be positive")
self.endpoint, self.model = endpoint.rstrip("/"), model
self.config = RunConfig(model_name=model, temperature=0.2, max_tokens=max_tokens)
self.responses = []
def generate(self, generation):
payload = {"prompt": generation.prompt, "config": self.config.to_dict()}
req = request.Request(self.endpoint + "/execute",
data=json.dumps(payload).encode(),
headers={"Content-Type": "application/json"})
try:
with request.urlopen(req, timeout=self.config.timeout_seconds + 15) as response:
data = json.load(response)
except error.HTTPError as exc:
raise InfospaceError("llm_connect_http", "llm-connect request failed",
{"error": f"HTTP Error {exc.code}"}) from None
except (error.URLError, TimeoutError):
raise InfospaceError("llm_connect_transport", "llm-connect unavailable", {}) from None
except ValueError:
raise InfospaceError("llm_connect_response", "Invalid llm-connect JSON", {}) from None
if not isinstance(data, dict):
raise ValueError("Invalid llm-connect response object")
metadata = {key: data.get(key) for key in ("model", "usage", "finish_reason")}
extra = data.get("metadata") or {}
metadata.update({key: extra[key] for key in (
"provider", "response_id", "latency_seconds", "profile", "profile_model",
"profile_provider") if key in extra})
self.responses.append({"stage": generation.stage_id, **metadata})
if (not isinstance(data.get("content"), str) or not data["content"].strip()
or data.get("finish_reason") != "stop"):
raise ValueError("llm-connect returned empty or incomplete generation; see receipt")
return AssistedGenerationResult(markdown=data["content"], provider="llm-connect",
metadata=metadata)
class LimitedAdapter:
def __init__(self, adapter, limit):
self.adapter, self.limit, self.calls = adapter, limit, 0
@ -111,6 +158,10 @@ def execute(root, adapter, max_calls=4):
manifest["status"] = "started"
manifest["adapter"] = type(adapter).__name__
manifest["model"] = getattr(adapter, "model", "")
if isinstance(adapter, LLMConnectAdapter):
manifest["execution"] = {"endpoint": adapter.endpoint,
"config": adapter.config.to_dict(),
"call_limit_scope": "service requests; server retries unknown"}
receipt.write_text(json.dumps(manifest, indent=2) + "\n")
limited = LimitedAdapter(adapter, max_calls)
try:
@ -127,6 +178,9 @@ def execute(root, adapter, max_calls=4):
raise
finally:
manifest["provider_calls_attempted"] = limited.calls
if isinstance(adapter, LLMConnectAdapter):
manifest["service_requests_attempted"] = limited.calls
manifest["responses"] = adapter.responses
receipt.write_text(json.dumps(manifest, indent=2) + "\n")
return manifest
@ -144,8 +198,9 @@ def main():
run.add_argument("root", type=Path)
providers = run.add_mutually_exclusive_group(required=True)
providers.add_argument("--fixture-responses", type=Path)
providers.add_argument("--provider", choices=["openrouter"])
run.add_argument("--model")
providers.add_argument("--llm-connect-url", help="llm-connect service base URL")
run.add_argument("--model", help="Model or runtime profile requested from llm-connect")
run.add_argument("--max-tokens", type=int, default=4000)
run.add_argument("--max-calls", type=int, default=4)
args = parser.parse_args()
try:
@ -161,7 +216,7 @@ def main():
else:
if not args.model:
raise ValueError("Live generation requires --model")
adapter = OpenRouterAssistedGenerationAdapter(model=args.model, retry_limit=0)
adapter = LLMConnectAdapter(args.llm_connect_url, args.model, args.max_tokens)
result = execute(args.root, adapter, args.max_calls)
print(json.dumps(result, indent=2, default=str))
except (ValueError, OSError, InfospaceError) as exc: