feat(consultation): unify server-distributed agents without fixed roles
This commit is contained in:
@@ -42,7 +42,7 @@ export async function prepareTeacherModel(
|
||||
throw new TeacherError(
|
||||
422,
|
||||
'teacher_model_unavailable',
|
||||
'老师所用模型暂不可用,请联系运营调整。'
|
||||
'智能体所用模型暂不可用,请联系运营调整。'
|
||||
);
|
||||
}
|
||||
const savedChoice = definition.model.reasoning_choice;
|
||||
@@ -61,7 +61,7 @@ export async function prepareTeacherModel(
|
||||
throw new TeacherError(
|
||||
422,
|
||||
'teacher_model_unavailable',
|
||||
'老师所用思考选项已不可用,请联系运营调整。'
|
||||
'智能体所用思考选项已不可用,请联系运营调整。'
|
||||
);
|
||||
}
|
||||
const outputLimit = Math.min(
|
||||
@@ -110,7 +110,7 @@ export async function streamTeacherReply(
|
||||
reads.shift();
|
||||
}
|
||||
if (options && estimateTeacherTokens(build()) + toolBudget > options.inputLimit) {
|
||||
throw new TeacherError(422, 'teacher_context_too_long', '老师读取的内容超过上下文预算,请缩小问题范围或联系运营增加预算。');
|
||||
throw new TeacherError(422, 'teacher_context_too_long', '智能体读取的内容超过上下文预算,请缩小问题范围或联系运营增加预算。');
|
||||
}
|
||||
const result = await streamTeacherTurn(config, modelId, reasoningFields, outputLimit,
|
||||
build(), signal, options?.finalOnly ? () => undefined : onText, fetchImpl, tools, round === 6);
|
||||
@@ -126,7 +126,7 @@ export async function streamTeacherReply(
|
||||
return usage;
|
||||
}
|
||||
if (!tools || round === 6) {
|
||||
throw new TeacherError(502, 'teacher_tools_unavailable', '老师未能完成本次读取,请缩小问题范围后重试。');
|
||||
throw new TeacherError(502, 'teacher_tools_unavailable', '智能体未能完成本次读取,请缩小问题范围后重试。');
|
||||
}
|
||||
const batch: TeacherModelMessage[] = [{ role: 'assistant', content: result.text, tool_calls: result.calls,
|
||||
...(result.reasoning ? { reasoning_content: result.reasoning } : {}) }];
|
||||
@@ -136,7 +136,7 @@ export async function streamTeacherReply(
|
||||
- toolBudget - estimateTeacherTokens([...messages, ...batch]) - 64 * result.calls.length)
|
||||
* TEACHER_ESTIMATED_BYTES_PER_TOKEN / result.calls.length));
|
||||
if (resultBudget < 128) {
|
||||
throw new TeacherError(422, 'teacher_context_too_long', '老师读取的内容超过上下文预算,请缩小问题范围或联系运营增加预算。');
|
||||
throw new TeacherError(422, 'teacher_context_too_long', '智能体读取的内容超过上下文预算,请缩小问题范围或联系运营增加预算。');
|
||||
}
|
||||
for (const call of result.calls) {
|
||||
signal.throwIfAborted();
|
||||
@@ -184,10 +184,10 @@ async function streamTeacherTurn(
|
||||
? '词元点数不足,请补充后再提问。'
|
||||
: response.status === 401
|
||||
? '模型凭据已失效,请重新提问。'
|
||||
: '老师暂时无法回复,请稍后重试。'
|
||||
: '智能体暂时无法回复,请稍后重试。'
|
||||
);
|
||||
}
|
||||
if (!response.body) throw new TeacherError(502, 'teacher_stream_missing', '未收到老师回复。');
|
||||
if (!response.body) throw new TeacherError(502, 'teacher_stream_missing', '未收到智能体回复。');
|
||||
const reader = response.body.getReader(),
|
||||
decoder = new TextDecoder();
|
||||
let buffer = '',
|
||||
@@ -211,13 +211,13 @@ async function streamTeacherTurn(
|
||||
usage?: { prompt_tokens: number; completion_tokens: number };
|
||||
};
|
||||
if (event.error)
|
||||
throw new TeacherError(502, 'teacher_model_failed', '老师回复中断,请保留当前内容后重试。');
|
||||
throw new TeacherError(502, 'teacher_model_failed', '智能体回复中断,请保留当前内容后重试。');
|
||||
const choice = event.choices?.[0];
|
||||
if (!tools && (choice?.delta?.tool_calls || choice?.finish_reason === 'tool_calls'))
|
||||
throw new TeacherError(
|
||||
502,
|
||||
'teacher_tools_unavailable',
|
||||
'老师只能提供文字建议,本次回复未完成。'
|
||||
'智能体只能提供文字建议,本次回复未完成。'
|
||||
);
|
||||
if (typeof choice?.delta?.content === 'string') {
|
||||
text += choice.delta.content;
|
||||
@@ -227,7 +227,7 @@ async function streamTeacherTurn(
|
||||
if (typeof choice?.delta?.reasoning_content === 'string') reasoning += choice.delta.reasoning_content;
|
||||
for (const delta of choice?.delta?.tool_calls ?? []) {
|
||||
if (!Number.isSafeInteger(delta.index) || delta.index < 0 || delta.index >= 8)
|
||||
throw new TeacherError(502, 'teacher_stream_invalid', '老师读取请求格式无效。');
|
||||
throw new TeacherError(502, 'teacher_stream_invalid', '智能体读取请求格式无效。');
|
||||
const call = calls.get(delta.index) ?? { id: '', type: 'function', function: { name: '', arguments: '' } };
|
||||
if (delta.id) call.id = delta.id;
|
||||
if (delta.function?.name) call.function.name += delta.function.name;
|
||||
@@ -262,7 +262,7 @@ async function streamTeacherTurn(
|
||||
if (data) frame(data);
|
||||
}
|
||||
if (buffer.length > 1_048_576)
|
||||
throw new TeacherError(502, 'teacher_stream_invalid', '老师回复格式无效。');
|
||||
throw new TeacherError(502, 'teacher_stream_invalid', '智能体回复格式无效。');
|
||||
if (chunk.done) break;
|
||||
}
|
||||
if (signal.aborted) throw signal.reason;
|
||||
@@ -270,7 +270,7 @@ async function streamTeacherTurn(
|
||||
throw new TeacherError(502, 'teacher_stream_interrupted', '回复中断,以下内容可能不完整。');
|
||||
if ((calls.size && finishReason !== 'tool_calls') || (finishReason === 'tool_calls' && !calls.size)
|
||||
|| [...calls.values()].some(call => !call.id || !call.function.name))
|
||||
throw new TeacherError(502, 'teacher_stream_interrupted', '老师读取请求未完整收到,请重试。');
|
||||
throw new TeacherError(502, 'teacher_stream_interrupted', '智能体读取请求未完整收到,请重试。');
|
||||
return { usage, text, reasoning, calls: [...calls.values()] };
|
||||
} finally {
|
||||
await reader.cancel().catch(() => undefined);
|
||||
|
||||
Reference in New Issue
Block a user