mirror of
https://github.com/7836246/cursor2api.git
synced 2026-09-03 07:20:02 +08:00
perf: 视觉拦截器仅处理最后一条 user 消息的图片
历史消息中的图片已在前几轮被转换为文本描述,无需重复送入 OCR/Vision API 处理。此优化避免多轮对话中重复消耗 API 配额 并减少每次请求的延迟。
This commit is contained in:
@@ -7,47 +7,55 @@ export async function applyVisionInterceptor(messages: AnthropicMessage[]): Prom
|
||||
const config = getConfig();
|
||||
if (!config.vision?.enabled) return;
|
||||
|
||||
for (const msg of messages) {
|
||||
if (msg.role !== 'user') continue;
|
||||
if (!Array.isArray(msg.content)) continue;
|
||||
|
||||
let hasImages = false;
|
||||
const newContent: AnthropicContentBlock[] = [];
|
||||
const imagesToAnalyze: AnthropicContentBlock[] = [];
|
||||
|
||||
for (const block of msg.content) {
|
||||
if (block.type === 'image') {
|
||||
hasImages = true;
|
||||
imagesToAnalyze.push(block);
|
||||
} else {
|
||||
newContent.push(block);
|
||||
}
|
||||
// ★ 仅处理最后一条 user 消息中的图片
|
||||
// 历史消息的图片已在前几轮被转换为文本描述,无需重复处理
|
||||
// 这避免了多轮对话中重复消耗 Vision API 配额和增加延迟
|
||||
let lastUserMsg: AnthropicMessage | null = null;
|
||||
for (let i = messages.length - 1; i >= 0; i--) {
|
||||
if (messages[i].role === 'user') {
|
||||
lastUserMsg = messages[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasImages && imagesToAnalyze.length > 0) {
|
||||
try {
|
||||
let descriptions = '';
|
||||
if (config.vision.mode === 'ocr') {
|
||||
descriptions = await processWithLocalOCR(imagesToAnalyze);
|
||||
} else {
|
||||
descriptions = await callVisionAPI(imagesToAnalyze);
|
||||
}
|
||||
if (!lastUserMsg || !Array.isArray(lastUserMsg.content)) return;
|
||||
|
||||
// Add descriptions as a simulated system text block
|
||||
newContent.push({
|
||||
type: 'text',
|
||||
text: `\n\n[System: The user attached ${imagesToAnalyze.length} image(s). Visual analysis/OCR extracted the following context:\n${descriptions}]\n\n`
|
||||
});
|
||||
let hasImages = false;
|
||||
const newContent: AnthropicContentBlock[] = [];
|
||||
const imagesToAnalyze: AnthropicContentBlock[] = [];
|
||||
|
||||
msg.content = newContent;
|
||||
} catch (e) {
|
||||
console.error("[Vision API Error]", e);
|
||||
newContent.push({
|
||||
type: 'text',
|
||||
text: `\n\n[System: The user attached image(s), but the Vision interceptor failed to process them. Error: ${(e as Error).message}]\n\n`
|
||||
});
|
||||
msg.content = newContent;
|
||||
for (const block of lastUserMsg.content) {
|
||||
if (block.type === 'image') {
|
||||
hasImages = true;
|
||||
imagesToAnalyze.push(block);
|
||||
} else {
|
||||
newContent.push(block);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasImages && imagesToAnalyze.length > 0) {
|
||||
try {
|
||||
let descriptions = '';
|
||||
if (config.vision.mode === 'ocr') {
|
||||
descriptions = await processWithLocalOCR(imagesToAnalyze);
|
||||
} else {
|
||||
descriptions = await callVisionAPI(imagesToAnalyze);
|
||||
}
|
||||
|
||||
// Add descriptions as a simulated system text block
|
||||
newContent.push({
|
||||
type: 'text',
|
||||
text: `\n\n[System: The user attached ${imagesToAnalyze.length} image(s). Visual analysis/OCR extracted the following context:\n${descriptions}]\n\n`
|
||||
});
|
||||
|
||||
lastUserMsg.content = newContent;
|
||||
} catch (e) {
|
||||
console.error("[Vision API Error]", e);
|
||||
newContent.push({
|
||||
type: 'text',
|
||||
text: `\n\n[System: The user attached image(s), but the Vision interceptor failed to process them. Error: ${(e as Error).message}]\n\n`
|
||||
});
|
||||
lastUserMsg.content = newContent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user