feat(wp7-02): support Gemini chat image relay
Dada P0-A isolated Windows CI / validate-and-package (push) Canceled after 0s
Dada P0-A isolated Windows CI / validate-and-package (push) Canceled after 0s
This commit is contained in:
@@ -26,7 +26,7 @@ function assertModelConfig(modelConfig) {
|
|||||||
const profile = modelConfig.route_profile;
|
const profile = modelConfig.route_profile;
|
||||||
if (!profile || typeof profile !== "object" || typeof profile.endpoint !== "string"
|
if (!profile || typeof profile !== "object" || typeof profile.endpoint !== "string"
|
||||||
|| !profile.endpoint.startsWith("https://oneapi.intelligrow.cn/")
|
|| !profile.endpoint.startsWith("https://oneapi.intelligrow.cn/")
|
||||||
|| !["gemini-interactions-v1beta", "gemini-native-v1beta", "openai-images-v1"].includes(profile.protocol_version)) {
|
|| !["gemini-interactions-v1beta", "gemini-native-v1beta", "gemini-openai-chat-v1", "openai-images-v1"].includes(profile.protocol_version)) {
|
||||||
throw new Error("WP7_02_ROUTE_PROFILE_INVALID");
|
throw new Error("WP7_02_ROUTE_PROFILE_INVALID");
|
||||||
}
|
}
|
||||||
if (profile.protocol_version === "gemini-interactions-v1beta"
|
if (profile.protocol_version === "gemini-interactions-v1beta"
|
||||||
@@ -34,6 +34,11 @@ function assertModelConfig(modelConfig) {
|
|||||||
|| profile.provider_model_id !== "gemini-3.1-flash-image")) {
|
|| profile.provider_model_id !== "gemini-3.1-flash-image")) {
|
||||||
throw new Error("WP7_02_ROUTE_PROFILE_INVALID");
|
throw new Error("WP7_02_ROUTE_PROFILE_INVALID");
|
||||||
}
|
}
|
||||||
|
if (profile.protocol_version === "gemini-openai-chat-v1"
|
||||||
|
&& (profile.endpoint !== "https://oneapi.intelligrow.cn/v1/chat/completions"
|
||||||
|
|| profile.provider_model_id !== "gemini-3.1-flash-image")) {
|
||||||
|
throw new Error("WP7_02_ROUTE_PROFILE_INVALID");
|
||||||
|
}
|
||||||
if (profile.protocol_version === "openai-images-v1"
|
if (profile.protocol_version === "openai-images-v1"
|
||||||
&& (profile.reference_endpoint !== "https://oneapi.intelligrow.cn/v1/images/edits")) {
|
&& (profile.reference_endpoint !== "https://oneapi.intelligrow.cn/v1/images/edits")) {
|
||||||
throw new Error("WP7_02_REFERENCE_ROUTE_PROFILE_INVALID");
|
throw new Error("WP7_02_REFERENCE_ROUTE_PROFILE_INVALID");
|
||||||
@@ -108,6 +113,28 @@ export function buildProviderRequest({ modelConfig, prompt, ratio, reference })
|
|||||||
url: config.route_profile.endpoint,
|
url: config.route_profile.endpoint,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (config.route_profile.protocol_version === "gemini-openai-chat-v1") {
|
||||||
|
const content = reference
|
||||||
|
? [
|
||||||
|
{ text: prompt, type: "text" },
|
||||||
|
{
|
||||||
|
image_url: { url: `data:${reference.mime_type};base64,${reference.bytes.toString("base64")}` },
|
||||||
|
type: "image_url",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: prompt;
|
||||||
|
return {
|
||||||
|
body: {
|
||||||
|
extra_body: { google: { image_config: { aspect_ratio: ratio, image_size: "1K" } } },
|
||||||
|
messages: [{ content, role: "user" }],
|
||||||
|
model: config.route_profile.provider_model_id,
|
||||||
|
stream: false,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
method: "POST",
|
||||||
|
url: config.route_profile.endpoint,
|
||||||
|
};
|
||||||
|
}
|
||||||
const providerModelId = config.route_profile.provider_model_id ?? config.model_id;
|
const providerModelId = config.route_profile.provider_model_id ?? config.model_id;
|
||||||
const body = {
|
const body = {
|
||||||
model: providerModelId,
|
model: providerModelId,
|
||||||
@@ -193,12 +220,20 @@ function geminiUsage(response) {
|
|||||||
function openAiUsage(response) {
|
function openAiUsage(response) {
|
||||||
const usage = response?.usage;
|
const usage = response?.usage;
|
||||||
return {
|
return {
|
||||||
input_units: integerOrZero(usage?.input_tokens ?? usage?.inputTokens),
|
input_units: integerOrZero(usage?.input_tokens ?? usage?.inputTokens ?? usage?.prompt_tokens ?? usage?.promptTokens),
|
||||||
output_units: integerOrZero(usage?.output_tokens ?? usage?.outputTokens),
|
output_units: integerOrZero(usage?.output_tokens ?? usage?.outputTokens ?? usage?.completion_tokens ?? usage?.completionTokens),
|
||||||
total_units: integerOrZero(usage?.total_tokens ?? usage?.totalTokens),
|
total_units: integerOrZero(usage?.total_tokens ?? usage?.totalTokens),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openAiChatImage(response) {
|
||||||
|
const content = response?.choices?.[0]?.message?.content;
|
||||||
|
if (typeof content !== "string") throw new Error("WP7_02_RESPONSE_SINGLE_IMAGE_REQUIRED");
|
||||||
|
const matches = [...content.matchAll(/!\[[^\]]*\]\(\s*data:(image\/(?:jpeg|png|webp));base64,([A-Za-z0-9+/=\r\n]+)\s*\)/gi)];
|
||||||
|
if (matches.length !== 1) throw new Error("WP7_02_RESPONSE_SINGLE_IMAGE_REQUIRED");
|
||||||
|
return { data: matches[0][2], mime: matches[0][1].toLowerCase() };
|
||||||
|
}
|
||||||
|
|
||||||
function interactionUsage(response) {
|
function interactionUsage(response) {
|
||||||
const usage = response?.usage;
|
const usage = response?.usage;
|
||||||
return {
|
return {
|
||||||
@@ -230,6 +265,11 @@ export function normalizeProviderResponse(modelConfig, response) {
|
|||||||
mime = images[0].mimeType ?? images[0].mime_type;
|
mime = images[0].mimeType ?? images[0].mime_type;
|
||||||
bytes = Buffer.from(images[0].data, "base64");
|
bytes = Buffer.from(images[0].data, "base64");
|
||||||
usageSummary = geminiUsage(response);
|
usageSummary = geminiUsage(response);
|
||||||
|
} else if (config.route_profile.protocol_version === "gemini-openai-chat-v1") {
|
||||||
|
const image = openAiChatImage(response);
|
||||||
|
bytes = Buffer.from(image.data, "base64");
|
||||||
|
mime = image.mime;
|
||||||
|
usageSummary = openAiUsage(response);
|
||||||
} else {
|
} else {
|
||||||
if (!Array.isArray(response?.data) || response.data.length !== 1 || typeof response.data[0]?.b64_json !== "string") {
|
if (!Array.isArray(response?.data) || response.data.length !== 1 || typeof response.data[0]?.b64_json !== "string") {
|
||||||
throw new Error("WP7_02_RESPONSE_SINGLE_IMAGE_REQUIRED");
|
throw new Error("WP7_02_RESPONSE_SINGLE_IMAGE_REQUIRED");
|
||||||
|
|||||||
Reference in New Issue
Block a user