Fase 1a kjørt, og den leverte funn — ikke beviset. Stigen: endepunkt (http 200) → --live-dry-run (exit 0) → --scripted-replies (HELE loopen, null modellkall, ValidatedProposal) → ekte modell. De tre første grønne; den fjerde exit 1. Trinn 3 er det som gjør rapporten verdt noe: loopen er bevist sammenhengende UTEN en modell i bildet, så feilen i trinn 4 er attribuerbar til levende modell-output. Fire funn, alle målt: 1. Den lokale klienten har ingen timeout-søm (backends.py:130) — kjøringen døde etter 3 x 600 s = 30 min på SDK-standardverdier. Ikke fikset her: produksjons- kode krever feilende test først. 2. qwen3:4b er resonnerende og brukte hele budsjettet på tankerekka — målt 4,0 tok/s, og 256 tokens ga TOMT svar. 3. Planens `--max-*`-flagg for token-tak finnes ikke; takene er kompilert inn. Inert lokalt, bærende for 1b: en betalt kjøring ville gått under et 100k-tak ingen har valgt. 4. Prompten (4388 tokens) ble STILLE kuttet mot Ollamas 4096-vindu, keep=4 — altså røk formatinstruksjonene først. Advarselen står i Ollamas logg, ikke i vår. Kjøring 2 (qwen2.5:3b uten tankemodus, 16k kontekst) lukket funn 4 men traff samme vegg: 600 s-taket er bindende på denne maskinvaren UANSETT modell — en 1B-modell brukte også over ti minutter per kall mens CPU-en strupet seg til 54 %. Ærlighetsgrense: null vellykkede modellkall. Prompt-former, VERDICT-linja og runde-taket er fortsatt uverifiserte mot en levende modell. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X737cbkG2uAXJ2Bvhf6X5M
9.5 KiB
Fase 1a — første ende-til-ende-kjøring mot en levende modell (lokal)
Dato: 2026-08-13 · Tre: 5871e39 (v1.0.0 + de to presentasjonsfilene) · Profil: local
Rammeverket hadde aldri kjørt mot en levende språkmodell — bare mot skriptede stand-ins. Denne rapporten er den første målingen av hva som faktisk skjer når en ekte modell settes inn i loopen. Fase 1a er den gratis halvdelen: en lokal Ollama-kjøring feller alt som ikke er autentisering, slik at den betalte Foundry-kjøringen (1b) bare har RBAC, token og deployment-navn igjen å feile på.
Ærlighetsgrense. Alt under er målt på ÉN maskin (Intel i9-9880H, CPU-only) med SMÅ lokale modeller. Tallene beskriver denne maskinen og disse modellene — ikke rammeverkets ytelse generelt, og ikke hva en Foundry-modell vil gjøre.
Miljø
| Maskin | Intel Core i9-9880H, 16 logiske kjerner, ingen GPU-akselerasjon for Ollama |
| Ollama | 0.16.3 |
| Python / MAF | 3.12.13 / agent-framework-core 1.9.0 |
| Kunnskapsbase | shared/examples/bygg-energi-mikro, prosjekt BYGG-KONTOR-NORD |
| Tak | max_rounds=3, max_tokens=100000 (kompilert inn, se funn 3) |
Stigen: fire trinn, der de tre første er gratis
Rekkefølgen er ikke tilfeldig. Hvert trinn gjør neste trinns feil attribuerbar.
| # | Hva | Utfall |
|---|---|---|
| 1 | Endepunkt nås (GET /api/tags) |
http 200 |
| 2 | --live-dry-run — bygger klient, stopper før første kall |
exit 0, models={proposer: qwen3:4b, checker: qwen3:4b} |
| 3 | --scripted-replies — HELE loopen, null modellkall |
exit 0, ValidatedProposal (decision=approved) |
| 4 | Ekte kjøring mot levende modell | se under |
Trinn 3 er det som gjør rapporten verdt noe: det beviser at argumentrekka, kunnskapsbasen, debatten, den deterministiske validatoren og domsavsigelsen henger sammen uten en modell i bildet. Enhver feil i trinn 4 er dermed forårsaket av levende modell-output, ikke av oppsettet.
Merk at et grønt trinn 2 ikke beviser at endepunktet virker: --live-dry-run bygger
klienten og stopper før første kall, så det går grønt også med serveren nede. Trinn 1 er
derfor en egen måling, ikke en formalitet.
Kjøring 1 — den shippede konfigurasjonen (qwen3:4b)
uv run python -m portfolio_optimiser.run BYGG-KONTOR-NORD --profile local \
--docs-dir shared/examples/bygg-energi-mikro \
--bundle-dir shared/examples/bygg-energi-mikro
Utfall: exit 1 etter 1804 sekunder (30 minutter), null forslag produsert.
agent_framework.exceptions.ChatClientException: OpenAIChatCompletionClient service failed
to complete the prompt: Request timed out. (APITimeoutError)
Årsakskjeden er målt hele veien, ikke resonnert:
- Ollamas logg viser tre kall, hvert avbrutt på nøyaktig
10m0s. 3 × 600 s = 1800 s, som er de 1804 sekundene kjøringen brukte. Det er OpenAI-SDK-ens standard timeout på 600 s pluss dens to standard retries — ingen av delene er valgt av oss (funn 1). - Modellen rakk aldri å svare. Målt direkte på samme maskin:
qwen3:4bgenererer 4,0 tokens/sekund. Et 600-sekunders vindu rommer altså ~2400 tokens. - Og den brukte alt på å tenke.
qwen3er en resonnerende modell. I en kontrollmåling med 256 tokens til rådighet var svaret tomt — hele budsjettet gikk med til den interne tankerekka<think>, før ett eneste tegn av det faktiske svaret ble skrevet (funn 2).
Funn
Funn 1 — den lokale klienten har ingen timeout-søm (rammeverket)
backends.py:130 konstruerer OpenAIChatCompletionClient(model=..., api_key=..., base_url=...).
Målt mot klassens signatur: den tar ingen timeout- eller max_retries-parameter. Eneste
vei inn er å bygge og sende inn en egen async_client.
Konsekvensen er at enhver maskin som er tregere enn modellen krever, feiler etter 30 minutter med en melding som ser ut som et nettverksproblem. Det er ikke en nettverksfeil — det er et tak ingen har valgt.
Ikke fikset her. Det er produksjonskode og krever en feilende test først (Iron Law), altså
egen økt. Formen på fiksen er kjent: la create_chat_client bygge AsyncOpenAI(timeout=…, max_retries=…) med verdier fra env, og la en load-bearing test bli rød når sømmen kobles fra.
Funn 2 — en resonnerende modell bruker hele budsjettet på å tenke
Dette er ikke en defekt i rammeverket, men det er en forutsetning ingen hadde skrevet ned:
modell-mappets lokale rolle pekte på qwen3:4b, og en resonnerende modell på treg maskinvare
når aldri fram til svaret. For den lokale profilen bør standardvalget være en modell uten
tankemodus — eller tankemodus må skrus av eksplisitt.
Funn 3 — planens token-tak-mekanisme finnes ikke i CLI-en
Planens fase 1b foreskriver «harde token-tak (--max-*-flaggene i run.py)». Målt: slike
flagg finnes ikke. Takene er kompilert inn — _DEFAULT_MAX_ROUNDS = 3,
_DEFAULT_MAX_TOKENS = 100_000 (run.py:110-111) — og kan ikke settes fra kommandolinjen.
Gratis og uvesentlig lokalt. For 1b er det bærende: en betalt kjøring vil ellers gå under et 100 000-tokens tak ingen har tatt stilling til. Dette er en beslutning for operatøren før den første Foundry-kjøringen, ikke noe som skal oppdages under den.
Funn 4 — kunnskapsbasen sprengte standard kontekstvindu, stille
Ollamas logg, kjøring 1:
level=WARN msg="truncating input prompt" limit=4096 prompt=4388 keep=4 new=4096
Ollamas standard kontekstvindu er 4096 tokens; prompten fra den navigerte kunnskapsbasen er
4388. Overskytende ble kuttet — og keep=4 betyr at bare fire tokens fra starten ble
bevart, altså at instruksjonene om svarformat sto først i det som røk.
Advarselen står i Ollamas logg, ikke i vår. En operatør som kjører lokalt ser den ikke.
Rettet for kjøring 2 ved å starte serveren med OLLAMA_CONTEXT_LENGTH=16384; at dette må
gjøres bør stå i den lokale oppskriften.
Kjøring 2 — med funn 2 og 4 kompensert
Modell byttet til qwen2.5:3b (uten tankemodus) via en modell-map utenfor treet
(PORTFOLIO_MODEL_MAP), og serveren restartet med OLLAMA_CONTEXT_LENGTH=16384. Repoets egen
konfig er urørt — dette er en erklært overstyring, ikke den shippede oppsettet.
Utfall: samme vegg. To kall, begge avbrutt på nøyaktig 10m0s. Kjøringen ble stoppet manuelt
framfor å brenne det tredje forsøket mot et kjent utfall.
Ett funn ble likevel lukket: null trunkering i loggen. Det større kontekstvinduet løser funn 4.
Diagnosen flyttet seg, og det er den viktigste setningen i rapporten: flaskehalsen er ikke
tankemodusen. Det er at 600-sekunders-taket er bindende på denne maskinvaren uansett modell.
En kontrollmåling med llama3.2:1b — en modell på 1,3 GB — brukte også over ti minutter på ett
kall med denne kontekststørrelsen, mens maskinen strupet seg fra 62 % til 54 % klokkefrekvens.
Hva som er bevist, og hva som ikke er
Bevist: loopen henger sammen fra ende til annen og produserer et validert forslag — men med skriptede svar, null modellkall (trinn 3).
IKKE bevist: at en levende modell produserer noe loopen kan konsumere. Null vellykkede modellkall. Dermed står disse fortsatt åpne, og de var hele grunnen til at 1a finnes:
- om prompt-formene gir parsebar JSON fra en ekte modell
- om checkeren faktisk avslutter med
VERDICT:-linja - om runde-taket oppfører seg som forutsatt
- om validatoren avviser kandidater av riktig grunn
Hva dette betyr for 1b
Fase 1a har levert funn, ikke beviset. Den lokale halvdelen kan ikke fullføre på denne maskinvaren uten at funn 1 fikses først — timeout-sømmen er dermed en forutsetning for lokal ende-til-ende, ikke en forbedring.
To veier videre, og de utelukker ikke hverandre:
- Bygg timeout-sømmen (egen økt, feilende test → fiks → målt mutasjon). Da blir lokal profil kjørbar på treg maskinvare, og 1b arver en klient med et tak noen har valgt.
- Gå til 1b. En Foundry-modell svarer på sekunder, ikke minutter — 600 s er ikke bindende der. Ende-til-ende blir da bevist mot ekte modell, som er det operatøren opprinnelig ba om.
Kostnad er ikke en begrensning for 1b. Regnet på Anthropics egen prisliste for Claude Haiku 4.5
($1,00/MTok inn, $5,00/MTok ut — Claude er tilgjengelig på Microsoft Foundry til standard
API-priser): ~54 000 input-tokens + ~5 000 output-tokens per full kjøring ≈ $0,08, altså under
én krone. Ti kjøringer er en tier. Det som gjenstår for 1b er ikke penger, men Azure-oppsettet:
ressurs, prosjekt, én billig deployment og rollen Foundry User — portal-steg bare operatøren kan
gjøre.
Uverifisert, må måles før det bygges på: om MAFs FoundryChatClient kan binde en
Claude-deployment. Foundry-tilgjengeligheten er dokumentert; klient-kompatibiliteten er det ikke.
Verifiseringslogg
| Påstand | Kilde |
|---|---|
| Trinn 1–3 grønne; trinn 4 exit 1 etter 1804 s | egne kjøringer, stdout/stderr fanget ordrett |
| 3 × 600 s timeout + 2 retries er SDK-standard | Ollamas logg (500 | 10m0s × 3) + agent_framework traceback |
Klienten har ingen timeout-parameter |
inspect.signature(OpenAIChatCompletionClient.__init__) |
qwen3:4b gir 4,0 tok/s; 256 tokens ga tomt svar |
/api/generate med eval_count/eval_duration |
| Prompt 4388 tokens, kuttet mot 4096 | Ollamas truncating input prompt-advarsel |
_DEFAULT_MAX_ROUNDS = 3, _DEFAULT_MAX_TOKENS = 100_000 |
run.py:110-111; CLI-en har ingen --max-* |
| Haiku 4.5-priser; Claude på Foundry til standard API-rater | Anthropics modell-/prisdokumentasjon (claude-api-skillen) |