fix: 网页端Anthropic Claude对话格式去除system角色,改为assistant角色
This commit is contained in:
@@ -1,12 +1,13 @@
|
|||||||
import { useHookFetch } from 'hook-fetch/vue';
|
|
||||||
import { ElMessage } from 'element-plus';
|
|
||||||
import { ref, computed } from 'vue';
|
|
||||||
import type { AnyObject } from 'typescript-api-pro';
|
import type { AnyObject } from 'typescript-api-pro';
|
||||||
import { deleteMessages, unifiedSend } from '@/api';
|
|
||||||
import { useModelStore } from '@/stores/modules/model';
|
|
||||||
import { convertToApiFormat, parseStreamChunk, type UnifiedMessage } from '@/utils/apiFormatConverter';
|
|
||||||
import type { BubbleProps } from 'vue-element-plus-x/types/Bubble';
|
import type { BubbleProps } from 'vue-element-plus-x/types/Bubble';
|
||||||
import type { ThinkingStatus } from 'vue-element-plus-x/types/Thinking';
|
import type { ThinkingStatus } from 'vue-element-plus-x/types/Thinking';
|
||||||
|
import type { UnifiedMessage } from '@/utils/apiFormatConverter';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
import { useHookFetch } from 'hook-fetch/vue';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { unifiedSend } from '@/api';
|
||||||
|
import { useModelStore } from '@/stores/modules/model';
|
||||||
|
import { convertToApiFormat, parseStreamChunk } from '@/utils/apiFormatConverter';
|
||||||
|
|
||||||
export type MessageRole = 'ai' | 'user' | 'assistant' | string;
|
export type MessageRole = 'ai' | 'user' | 'assistant' | string;
|
||||||
|
|
||||||
@@ -83,7 +84,8 @@ export function useChatSender(options: UseChatSenderOptions) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const latest = messages[messages.length - 1];
|
const latest = messages[messages.length - 1];
|
||||||
if (!latest) return;
|
if (!latest)
|
||||||
|
return;
|
||||||
|
|
||||||
// 处理 token 使用情况
|
// 处理 token 使用情况
|
||||||
if (parsed.usage) {
|
if (parsed.usage) {
|
||||||
@@ -99,7 +101,8 @@ export function useChatSender(options: UseChatSenderOptions) {
|
|||||||
latest.thinkingStatus = 'thinking';
|
latest.thinkingStatus = 'thinking';
|
||||||
latest.loading = true;
|
latest.loading = true;
|
||||||
latest.thinlCollapse = true;
|
latest.thinlCollapse = true;
|
||||||
if (!latest.reasoning_content) latest.reasoning_content = '';
|
if (!latest.reasoning_content)
|
||||||
|
latest.reasoning_content = '';
|
||||||
latest.reasoning_content += parsed.reasoning_content;
|
latest.reasoning_content += parsed.reasoning_content;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,21 +111,26 @@ export function useChatSender(options: UseChatSenderOptions) {
|
|||||||
const thinkStart = parsed.content.includes('<think>');
|
const thinkStart = parsed.content.includes('<think>');
|
||||||
const thinkEnd = parsed.content.includes('</think>');
|
const thinkEnd = parsed.content.includes('</think>');
|
||||||
|
|
||||||
if (thinkStart) isThinking.value = true;
|
if (thinkStart)
|
||||||
if (thinkEnd) isThinking.value = false;
|
isThinking.value = true;
|
||||||
|
if (thinkEnd)
|
||||||
|
isThinking.value = false;
|
||||||
|
|
||||||
if (isThinking.value) {
|
if (isThinking.value) {
|
||||||
latest.thinkingStatus = 'thinking';
|
latest.thinkingStatus = 'thinking';
|
||||||
latest.loading = true;
|
latest.loading = true;
|
||||||
latest.thinlCollapse = true;
|
latest.thinlCollapse = true;
|
||||||
if (!latest.reasoning_content) latest.reasoning_content = '';
|
if (!latest.reasoning_content)
|
||||||
|
latest.reasoning_content = '';
|
||||||
latest.reasoning_content += parsed.content
|
latest.reasoning_content += parsed.content
|
||||||
.replace('<think>', '')
|
.replace('<think>', '')
|
||||||
.replace('</think>', '');
|
.replace('</think>', '');
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
latest.thinkingStatus = 'end';
|
latest.thinkingStatus = 'end';
|
||||||
latest.loading = false;
|
latest.loading = false;
|
||||||
if (!latest.content) latest.content = '';
|
if (!latest.content)
|
||||||
|
latest.content = '';
|
||||||
latest.content += parsed.content;
|
latest.content += parsed.content;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,7 +152,8 @@ export function useChatSender(options: UseChatSenderOptions) {
|
|||||||
textFiles: any[],
|
textFiles: any[],
|
||||||
onUpdate: (messages: MessageItem[]) => void,
|
onUpdate: (messages: MessageItem[]) => void,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (isSending.value) return;
|
if (isSending.value)
|
||||||
|
return;
|
||||||
|
|
||||||
isSending.value = true;
|
isSending.value = true;
|
||||||
currentRequestApiType.value = modelStore.currentModelInfo.modelApiType || 'Completions';
|
currentRequestApiType.value = modelStore.currentModelInfo.modelApiType || 'Completions';
|
||||||
@@ -207,7 +216,8 @@ export function useChatSender(options: UseChatSenderOptions) {
|
|||||||
fileContent += `<FILE_NAME>${fileItem.name}</FILE_NAME>\n`;
|
fileContent += `<FILE_NAME>${fileItem.name}</FILE_NAME>\n`;
|
||||||
fileContent += `<FILE_CONTENT>\n${fileItem.fileContent}\n</FILE_CONTENT>\n`;
|
fileContent += `<FILE_CONTENT>\n${fileItem.fileContent}\n</FILE_CONTENT>\n`;
|
||||||
fileContent += `</ATTACHMENT_FILE>\n`;
|
fileContent += `</ATTACHMENT_FILE>\n`;
|
||||||
if (index < textFiles.length - 1) fileContent += '\n';
|
if (index < textFiles.length - 1)
|
||||||
|
fileContent += '\n';
|
||||||
});
|
});
|
||||||
contentArray.push({ type: 'text', text: fileContent });
|
contentArray.push({ type: 'text', text: fileContent });
|
||||||
}
|
}
|
||||||
@@ -225,7 +235,8 @@ export function useChatSender(options: UseChatSenderOptions) {
|
|||||||
baseMessage.content = contentArray.length > 1 || imageFiles.length > 0 || textFiles.length > 0
|
baseMessage.content = contentArray.length > 1 || imageFiles.length > 0 || textFiles.length > 0
|
||||||
? contentArray
|
? contentArray
|
||||||
: item.content;
|
: item.content;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
baseMessage.content = (item.role === 'ai' || item.role === 'assistant') && item.content.length > 10000
|
baseMessage.content = (item.role === 'ai' || item.role === 'assistant') && item.content.length > 10000
|
||||||
? `${item.content.substring(0, 10000)}...(内容过长,已省略)`
|
? `${item.content.substring(0, 10000)}...(内容过长,已省略)`
|
||||||
: item.content;
|
: item.content;
|
||||||
|
|||||||
@@ -127,18 +127,20 @@ export function toResponsesFormat(messages: UnifiedMessage[]): ResponsesMessage[
|
|||||||
* 将统一格式的消息转换为 Anthropic Claude 格式
|
* 将统一格式的消息转换为 Anthropic Claude 格式
|
||||||
*/
|
*/
|
||||||
export function toClaudeFormat(messages: UnifiedMessage[]): { messages: ClaudeMessage[]; system?: string } {
|
export function toClaudeFormat(messages: UnifiedMessage[]): { messages: ClaudeMessage[]; system?: string } {
|
||||||
let systemPrompt: string | undefined;
|
|
||||||
const claudeMessages: ClaudeMessage[] = [];
|
const claudeMessages: ClaudeMessage[] = [];
|
||||||
|
|
||||||
for (const msg of messages) {
|
for (const msg of messages) {
|
||||||
// Claude 的 system 消息需要单独提取
|
// system 消息转换为 assistant 角色放入 messages 数组
|
||||||
|
let role: 'user' | 'assistant';
|
||||||
if (msg.role === 'system') {
|
if (msg.role === 'system') {
|
||||||
msg.role = 'assistant';
|
role = 'assistant';
|
||||||
// systemPrompt = typeof msg.content === 'string' ? msg.content : msg.content.map(c => c.text || '').join('');
|
}
|
||||||
// continue;
|
else if (msg.role === 'model') {
|
||||||
|
role = 'assistant';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
role = msg.role as 'user' | 'assistant';
|
||||||
}
|
}
|
||||||
|
|
||||||
const role = msg.role === 'model' ? 'assistant' : msg.role;
|
|
||||||
|
|
||||||
// 处理内容格式
|
// 处理内容格式
|
||||||
let content: string | ClaudeContent[];
|
let content: string | ClaudeContent[];
|
||||||
|
|||||||
Reference in New Issue
Block a user