6f8125570a
User feedback: custom interactions rarely produce new story content because the classifier heavily biased toward insert-beat (single reaction, no scene change). Three changes to fix this: 1. Freeform text input now always triggers a full scene generation (skips the classify step entirely) — users who type expect the story to advance. 2. Vision (background click) classifier de-biased: prompt now favors change-scene when uncertain, and the code fallback flipped from insert-beat to change-scene. insert-beat narrowed to pure observation. 3. Insert-beat enhanced: generates 1-3 beats (was 1) with follow-up choices (was: loop back to original beat). Even when vision classifies as insert-beat, the player gets richer content and new options. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
40 lines
1.1 KiB
TypeScript
40 lines
1.1 KiB
TypeScript
import { interpretClick } from "@infiplot/ai-client";
|
|
import type {
|
|
ClickIntent,
|
|
ProviderConfig,
|
|
Scene,
|
|
VisionClassify,
|
|
} from "@infiplot/types";
|
|
import { parseJsonLoose } from "./jsonParser";
|
|
import { VISION_SYSTEM_PROMPT, buildVisionUserPrompt } from "./prompts";
|
|
|
|
export type VisionInterpretation = {
|
|
intent: ClickIntent;
|
|
classify: VisionClassify;
|
|
};
|
|
|
|
export async function interpret(
|
|
config: ProviderConfig,
|
|
annotatedImageBase64: string,
|
|
scene: Scene | null,
|
|
): Promise<VisionInterpretation> {
|
|
const userPrompt = `${VISION_SYSTEM_PROMPT}\n\n${buildVisionUserPrompt(scene)}`;
|
|
const raw = await interpretClick(config, annotatedImageBase64, userPrompt);
|
|
const parsed = parseJsonLoose<{
|
|
freeformAction?: string;
|
|
classify?: string;
|
|
reasoning?: string;
|
|
}>(raw);
|
|
|
|
const classify: VisionClassify =
|
|
parsed.classify === "insert-beat" ? "insert-beat" : "change-scene";
|
|
|
|
return {
|
|
intent: {
|
|
freeformAction: parsed.freeformAction?.trim() || "玩家点了画面,但意图不明",
|
|
reasoning: parsed.reasoning?.trim() || "",
|
|
},
|
|
classify,
|
|
};
|
|
}
|