fix: 复用现有 Qwen VL 模型调用方式
This commit is contained in:
parent
3558eed251
commit
f7debfb55f
@ -1,6 +1,7 @@
|
|||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
import { db } from "@/lib/db";
|
import { generateText } from "ai";
|
||||||
import { aiProvider } from "@/lib/db/schema";
|
import { getEnabledAiModelsWithProvider } from "@/lib/db/queries";
|
||||||
|
import { getLanguageModelById } from "@/lib/ai/dynamic-provider";
|
||||||
|
|
||||||
export const runtime = "nodejs";
|
export const runtime = "nodejs";
|
||||||
export const maxDuration = 30;
|
export const maxDuration = 30;
|
||||||
@ -13,7 +14,7 @@ const POSITION_OPTIONS = [
|
|||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
interface PickObjectRequest {
|
interface PickObjectRequest {
|
||||||
imageUrl: string; // 图片 URL(不再使用 Base64)
|
imageUrl: string; // 图片 URL
|
||||||
clickX: number; // 点击位置 X (0-1)
|
clickX: number; // 点击位置 X (0-1)
|
||||||
clickY: number; // 点击位置 Y (0-1)
|
clickY: number; // 点击位置 Y (0-1)
|
||||||
}
|
}
|
||||||
@ -52,17 +53,28 @@ export async function POST(request: Request) {
|
|||||||
}, { status: 400 });
|
}, { status: 400 });
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取 Qwen-VL 配置 - 使用原生 SQL 查询
|
// 获取 Qwen VL 模型(复用现有逻辑)
|
||||||
const providers = await db.select().from(aiProvider);
|
const allModels = await getEnabledAiModelsWithProvider();
|
||||||
const qwenProvider = providers.find(p => p.providerId === 'qwen');
|
const qwenModel = allModels.find(
|
||||||
|
(m) => m.provider.type === "alibaba" && m.model.supportsVision
|
||||||
|
);
|
||||||
|
|
||||||
console.log('[PickObject] 找到 providers:', providers.length, '个');
|
if (!qwenModel) {
|
||||||
console.log('[PickObject] Qwen provider:', qwenProvider ? '已找到' : '未找到');
|
console.log("[PickObject] No Qwen VL model found");
|
||||||
|
|
||||||
if (!qwenProvider || !qwenProvider.isEnabled || !qwenProvider.apiKey) {
|
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
success: false,
|
success: false,
|
||||||
error: 'Qwen 服务未配置或未启用',
|
error: 'Qwen VL 模型未配置',
|
||||||
|
}, { status: 500 });
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('[PickObject] 使用模型:', qwenModel.model.modelId, qwenModel.model.displayName);
|
||||||
|
|
||||||
|
const model = await getLanguageModelById(qwenModel.model.id);
|
||||||
|
if (!model) {
|
||||||
|
console.log("[PickObject] Failed to get language model");
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
error: '无法加载模型',
|
||||||
}, { status: 500 });
|
}, { status: 500 });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,56 +101,33 @@ ${POSITION_OPTIONS.join('、')}
|
|||||||
【boundingBox】相对坐标 0-1,精确到小数点后2位
|
【boundingBox】相对坐标 0-1,精确到小数点后2位
|
||||||
`.trim();
|
`.trim();
|
||||||
|
|
||||||
const apiUrl = `${qwenProvider.apiBaseUrl || 'https://dashscope.aliyuncs.com/compatible-mode/v1'}/chat/completions`;
|
console.log('[PickObject] 调用 Qwen VL 模型...');
|
||||||
console.log('[PickObject] 调用 Qwen API:', apiUrl);
|
|
||||||
|
|
||||||
// 调用 Qwen-VL API(使用图片 URL)
|
// 调用 Qwen VL 模型(复用现有的 generateText)
|
||||||
const response = await fetch(apiUrl, {
|
const { text: responseText } = await generateText({
|
||||||
method: 'POST',
|
model,
|
||||||
headers: {
|
messages: [
|
||||||
'Content-Type': 'application/json',
|
{
|
||||||
'Authorization': `Bearer ${qwenProvider.apiKey}`,
|
role: 'user',
|
||||||
},
|
content: [
|
||||||
body: JSON.stringify({
|
{
|
||||||
model: 'qwen-vl-max',
|
type: 'image',
|
||||||
messages: [
|
image: imageUrl, // 直接使用图片 URL
|
||||||
{
|
},
|
||||||
role: 'user',
|
{
|
||||||
content: [
|
type: 'text',
|
||||||
{
|
text: prompt,
|
||||||
type: 'image_url',
|
},
|
||||||
image_url: {
|
],
|
||||||
url: imageUrl, // 直接使用图片 URL
|
},
|
||||||
},
|
],
|
||||||
},
|
temperature: 0.1,
|
||||||
{
|
maxTokens: 300,
|
||||||
type: 'text',
|
} as any);
|
||||||
text: prompt,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
max_tokens: 200,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('[PickObject] Qwen API 响应状态:', response.status);
|
console.log('[PickObject] Qwen 返回内容:', responseText?.substring(0, 200));
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!responseText) {
|
||||||
const errorText = await response.text();
|
|
||||||
console.error('[PickObject] Qwen API error:', errorText);
|
|
||||||
return NextResponse.json({
|
|
||||||
success: false,
|
|
||||||
error: `AI 识别服务错误: ${response.status}`,
|
|
||||||
}, { status: 500 });
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
const content = data.choices?.[0]?.message?.content;
|
|
||||||
|
|
||||||
console.log('[PickObject] Qwen 返回内容:', content?.substring(0, 200));
|
|
||||||
|
|
||||||
if (!content) {
|
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
success: false,
|
success: false,
|
||||||
error: 'AI 未返回结果',
|
error: 'AI 未返回结果',
|
||||||
@ -149,7 +138,7 @@ ${POSITION_OPTIONS.join('、')}
|
|||||||
let result: PickObjectResult;
|
let result: PickObjectResult;
|
||||||
try {
|
try {
|
||||||
// 尝试从返回内容中提取 JSON
|
// 尝试从返回内容中提取 JSON
|
||||||
const jsonMatch = content.match(/\{[\s\S]*\}/);
|
const jsonMatch = responseText.match(/\{[\s\S]*\}/);
|
||||||
if (!jsonMatch) {
|
if (!jsonMatch) {
|
||||||
throw new Error('未找到 JSON');
|
throw new Error('未找到 JSON');
|
||||||
}
|
}
|
||||||
@ -190,7 +179,7 @@ ${POSITION_OPTIONS.join('、')}
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (parseError) {
|
} catch (parseError) {
|
||||||
console.error('[PickObject] JSON parse error:', parseError, 'Content:', content);
|
console.error('[PickObject] JSON parse error:', parseError, 'Content:', responseText);
|
||||||
|
|
||||||
// 返回默认结果
|
// 返回默认结果
|
||||||
const posX = clickX < 0.33 ? '左' : clickX > 0.66 ? '右' : '中央';
|
const posX = clickX < 0.33 ? '左' : clickX > 0.66 ? '右' : '中央';
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user