update at 2025-10-15 15:07:45
This commit is contained in:
@@ -293,9 +293,12 @@ export class ModelServiceManager {
|
||||
|
||||
case 'dashscope':
|
||||
return [
|
||||
'qwen3-max',
|
||||
'qwen3-vl-30b-a3b-thinking',
|
||||
'qwen3-vl-8b-thinking',
|
||||
'qwen-flash',
|
||||
'qwen-turbo-latest', // 通义千问 Turbo 最新版 - 高性价比,响应快
|
||||
'qwen-plus', // 通义千问增强版 - 推理能力强
|
||||
'qwen3-max',
|
||||
'qwen-long', // 通义千问长文本版 - 支持超长上下文(1M tokens)
|
||||
'qwen3-omni-flash' // 通义千问全能闪电版 - 多模态,极速响应
|
||||
]
|
||||
@@ -307,11 +310,9 @@ export class ModelServiceManager {
|
||||
// DeepSeek-V3 系列 - 深度思考模型
|
||||
'deepseek-v3-1-terminus', // DeepSeek V3.1 terminus版本
|
||||
'deepseek-v3-1-250821', // DeepSeek V3.1 250821版本
|
||||
|
||||
// Doubao Seed 1.6 系列 - 深度思考模型(推荐)
|
||||
'doubao-seed-1-6-flash', // 快速多模态深度思考
|
||||
'doubao-seed-1-6-vision-250815', // 多模态深度思考(图片+视频+GUI)
|
||||
'doubao-seed-1-6-250615', // 纯文本深度思考
|
||||
'doubao-seed-1-6-flash-250828', // 快速多模态深度思考
|
||||
'doubao-seed-1-6-thinking-250715', // 纯思考模型
|
||||
]
|
||||
|
||||
@@ -408,7 +409,8 @@ export class ModelServiceManager {
|
||||
messages: any[],
|
||||
model: string,
|
||||
onChunk: (chunk: string) => void,
|
||||
tools?: any[]
|
||||
tools?: any[],
|
||||
signal?: AbortSignal
|
||||
): Promise<ApiResponse<{ toolCalls?: any[] }>> {
|
||||
const startTime = performance.now()
|
||||
console.log('🚀🚀🚀 [sendChatRequestStream] === 进入流式请求方法 ===')
|
||||
@@ -431,7 +433,7 @@ export class ModelServiceManager {
|
||||
}
|
||||
|
||||
try {
|
||||
const toolCalls = await this.makeChatRequestStream(service, messages, model, onChunk, tools)
|
||||
const toolCalls = await this.makeChatRequestStream(service, messages, model, onChunk, tools, signal)
|
||||
|
||||
const endTime = performance.now()
|
||||
console.log('⏱️ [sendChatRequestStream] 流式请求完成,总耗时:', (endTime - startTime).toFixed(2), 'ms')
|
||||
@@ -600,7 +602,8 @@ export class ModelServiceManager {
|
||||
messages: any[],
|
||||
model: string,
|
||||
onChunk: (text: string) => void,
|
||||
tools?: any[]
|
||||
tools?: any[],
|
||||
signal?: AbortSignal
|
||||
): Promise<any[] | undefined> {
|
||||
const requestStartTime = performance.now()
|
||||
|
||||
@@ -675,8 +678,9 @@ export class ModelServiceManager {
|
||||
console.log(' URL:', url)
|
||||
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')
|
||||
|
||||
const controller = new AbortController()
|
||||
const timeoutId = setTimeout(() => controller.abort(), 60000) // 流式请求60秒超时
|
||||
// 使用外部传入的 signal,或创建一个带超时的内部 controller
|
||||
const controller = signal ? null : new AbortController()
|
||||
const timeoutId = controller ? setTimeout(() => controller.abort(), 60000) : undefined // 流式请求60秒超时
|
||||
|
||||
try {
|
||||
const beforeFetch = performance.now()
|
||||
@@ -686,10 +690,10 @@ export class ModelServiceManager {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body: JSON.stringify(body),
|
||||
signal: controller.signal
|
||||
signal: signal || controller?.signal
|
||||
})
|
||||
|
||||
clearTimeout(timeoutId)
|
||||
if (timeoutId) clearTimeout(timeoutId)
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
@@ -715,6 +719,13 @@ export class ModelServiceManager {
|
||||
const toolCallsMap = new Map<number, any>()
|
||||
|
||||
while (true) {
|
||||
// 检查是否被中止(参考 cherry-studio 的实现)
|
||||
if (signal?.aborted) {
|
||||
console.log('🛑 [makeChatRequestStream] 检测到中止信号,停止读取流')
|
||||
reader.cancel()
|
||||
throw new DOMException('用户中止操作', 'AbortError')
|
||||
}
|
||||
|
||||
const { done, value } = await reader.read()
|
||||
if (done) break
|
||||
|
||||
@@ -753,6 +764,11 @@ export class ModelServiceManager {
|
||||
|
||||
// 处理工具调用
|
||||
if (delta?.tool_calls) {
|
||||
// 只在第一次检测到时输出日志
|
||||
if (toolCallsMap.size === 0) {
|
||||
console.log('🔧 [makeChatRequestStream] 检测到工具调用,开始收集...')
|
||||
}
|
||||
|
||||
for (const toolCall of delta.tool_calls) {
|
||||
const index = toolCall.index
|
||||
if (!toolCallsMap.has(index)) {
|
||||
@@ -785,7 +801,18 @@ export class ModelServiceManager {
|
||||
// 收集所有工具调用
|
||||
if (toolCallsMap.size > 0) {
|
||||
collectedToolCalls = Array.from(toolCallsMap.values())
|
||||
console.log('🔧 [makeChatRequestStream] 检测到工具调用:', collectedToolCalls.length, '个')
|
||||
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')
|
||||
console.log('🔧 [makeChatRequestStream] 最终收集到工具调用:', collectedToolCalls.length, '个')
|
||||
collectedToolCalls.forEach((tc, idx) => {
|
||||
console.log(` 工具 [${idx}]:`, {
|
||||
id: tc.id,
|
||||
name: tc.function.name,
|
||||
arguments: tc.function.arguments
|
||||
})
|
||||
})
|
||||
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')
|
||||
} else {
|
||||
console.log('⚠️ [makeChatRequestStream] 没有检测到工具调用')
|
||||
}
|
||||
|
||||
const endTime = performance.now()
|
||||
@@ -795,10 +822,18 @@ export class ModelServiceManager {
|
||||
|
||||
return collectedToolCalls.length > 0 ? collectedToolCalls : undefined
|
||||
} catch (error) {
|
||||
clearTimeout(timeoutId)
|
||||
if (timeoutId) clearTimeout(timeoutId)
|
||||
|
||||
// 如果是 AbortError,直接抛出原始错误(可能是用户中止或超时)
|
||||
if (error instanceof Error && error.name === 'AbortError') {
|
||||
throw new Error('流式请求超时(60秒)')
|
||||
console.log('⚠️ [makeChatRequestStream] 请求被中止:', error.message)
|
||||
throw error
|
||||
}
|
||||
if (error instanceof DOMException && error.name === 'AbortError') {
|
||||
console.log('⚠️ [makeChatRequestStream] 请求被中止:', error.message)
|
||||
throw error
|
||||
}
|
||||
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user