mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-26 09:52:11 +03:00
fix(vision-bridge): force GPT-family image fallback (#1571)
Integrated into release/v3.7.0
This commit is contained in:
@@ -15,6 +15,7 @@ import {
|
||||
import {
|
||||
VISION_BRIDGE_DEFAULTS,
|
||||
getVisionBridgeConfig,
|
||||
isVisionBridgeForcedModel,
|
||||
} from "@/shared/constants/visionBridgeDefaults";
|
||||
|
||||
export interface VisionBridgeDependencies {
|
||||
@@ -55,9 +56,11 @@ export class VisionBridgeGuardrail extends BaseGuardrail {
|
||||
return { block: false };
|
||||
}
|
||||
|
||||
const forceVisionBridge = isVisionBridgeForcedModel(model);
|
||||
|
||||
// 4. Check if model supports vision
|
||||
const capabilities = getResolvedModelCapabilities(model);
|
||||
if (capabilities.supportsVision === true) {
|
||||
if (capabilities.supportsVision === true && !forceVisionBridge) {
|
||||
return { block: false };
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
* Vision Bridge default configuration values.
|
||||
*/
|
||||
|
||||
const NORMALIZED_GPT_MODEL_PATTERN = /^gpt-/i;
|
||||
|
||||
export function isVisionBridgeForcedModel(model: string | null | undefined): boolean {
|
||||
if (!model) return false;
|
||||
const normalizedModel = model.includes("/") ? model.split("/").pop() || model : model;
|
||||
return NORMALIZED_GPT_MODEL_PATTERN.test(normalizedModel);
|
||||
}
|
||||
|
||||
export const VISION_BRIDGE_DEFAULTS = {
|
||||
enabled: true,
|
||||
model: "openai/gpt-4o-mini",
|
||||
|
||||
@@ -164,6 +164,37 @@ test("VB-S02: passthroughs for vision-capable model (gpt-4o)", async () => {
|
||||
}
|
||||
});
|
||||
|
||||
test("VB-S02b: forces Vision Bridge for GPT-family models even when model capabilities advertise vision", async () => {
|
||||
const guardrail = createGuardrail();
|
||||
|
||||
for (const model of ["gpt-5.4", "gpt-5.4-mini", "gpt-4o", "openai/gpt-4o-mini"]) {
|
||||
mockVisionResponse = `Forced bridge description for ${model}`;
|
||||
visionCallCount = 0;
|
||||
|
||||
const payload = createPayload({
|
||||
model,
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: [
|
||||
{ type: "text", text: "What is this?" },
|
||||
{
|
||||
type: "image_url",
|
||||
image_url: { url: "https://example.com/image.png" },
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const result = await guardrail.preCall(payload, createContext({ model }));
|
||||
|
||||
assert.strictEqual(result.block, false, `expected passthrough=false for ${model}`);
|
||||
assert.ok(result.modifiedPayload, `expected modified payload for ${model}`);
|
||||
assert.strictEqual(visionCallCount, 1, `expected one forced bridge call for ${model}`);
|
||||
}
|
||||
});
|
||||
|
||||
test("VB-S02: model capabilities returns supportsVision for known models", () => {
|
||||
const gpt4oCaps = getResolvedModelCapabilities("openai/gpt-4o");
|
||||
// supportsVision may be true (if sync data exists) or null (if not synced)
|
||||
|
||||
Reference in New Issue
Block a user