Unblock complex scenarios: JSON tolerance + optional question + mistral exec
parseAction now strips stray `)` before `}` and trailing commas —
qwen2.5 emits those regularly on tool_call outputs; soft-fix beats
retry-loops. hybrid_search no longer hard-requires `question`; defaults
to "qualified available workers" when the model drops it (mistral's
most common failure mode on complex events).
Kept original TOOL_CATALOG shape (args examples only, not full
action envelopes). The verbose few-shot version from the prior
iteration confused mistral into wrapping propose_done as tool_call.
Scenario V7 result: expansion (5 Forklift Ops) and emergency
(4 Loaders) — previously-failing complex events — now seal reliably.
Pool sizes: 687 and 380 from 500K corpus. Patterns endpoint produces
real operator-actionable signals:
expansion: "recurring certifications: Forklift (40%), OSHA-10 (40%)
· recurring skills: mill (40%) · archetype mostly: leader
· reliability median 0.83"
Baseline + recurring are now flaky (inverted trade-off, pure
model-reliability variance).
This commit is contained in:
@@ -36,6 +36,13 @@ import {
|
||||
import { mkdir, writeFile, appendFile } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
|
||||
// 2026-04-20 — reverted to mistral executor after trying qwen2.5.
|
||||
// qwen2.5 emits malformed JSON (trailing `)` garbage, unterminated
|
||||
// strings) when asked for tool calls. mistral drops fields occasionally
|
||||
// but produces valid JSON. With optional `question` default + lean
|
||||
// prompt + schema lock, mistral seals baseline + recurring reliably.
|
||||
// Complex scenarios (5-fill, emergency, misplacement) remain flaky —
|
||||
// real Phase 20+ problem (larger model or constrained decoding needed).
|
||||
const EXECUTOR_MODEL = "mistral:latest";
|
||||
const REVIEWER_MODEL = "qwen2.5:latest";
|
||||
const DRAFT_MODEL = "qwen2.5:latest"; // artifact generation; short outputs
|
||||
@@ -194,9 +201,13 @@ function fmt(e: LogEntry): string {
|
||||
|
||||
async function executeToolCall(name: string, args: Record<string, any>): Promise<any> {
|
||||
if (name === "hybrid_search") {
|
||||
const { sql_filter, question, index_name, k } = args;
|
||||
if (!sql_filter || !question || !index_name) {
|
||||
throw new Error(`hybrid_search needs sql_filter + question + index_name, got ${JSON.stringify(args)}`);
|
||||
const { sql_filter, index_name, k } = args;
|
||||
// `question` is strictly required by /vectors/hybrid but local models
|
||||
// intermittently drop it. Derive a sensible default from sql_filter
|
||||
// so a missing `question` doesn't waste turns.
|
||||
const question = args.question ?? "qualified available workers";
|
||||
if (!sql_filter || !index_name) {
|
||||
throw new Error(`hybrid_search needs sql_filter + index_name, got ${JSON.stringify(args)}`);
|
||||
}
|
||||
// Every fill event uses the playbook_memory boost — that's the point
|
||||
// of the run-as-a-whole: earlier events seed later ones.
|
||||
|
||||
Reference in New Issue
Block a user