Skip to content

Commit

Permalink
馃悰 fix: fix anthropic messages need pairs
Browse files Browse the repository at this point in the history
  • Loading branch information
arvinxx committed May 9, 2024
1 parent 023c21b commit 0e01db0
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 16 deletions.
41 changes: 28 additions & 13 deletions src/libs/agent-runtime/anthropic/index.ts
Expand Up @@ -27,21 +27,11 @@ export class LobeAnthropicAI implements LobeRuntimeAI {
}

async chat(payload: ChatStreamPayload, options?: ChatCompetitionOptions) {
const { messages, model, max_tokens, temperature, top_p } = payload;
const system_message = messages.find((m) => m.role === 'system');
const user_messages = messages.filter((m) => m.role !== 'system');

try {
const anthropicPayload = this.buildAnthropicPayload(payload);

const response = await this.client.messages.create(
{
max_tokens: max_tokens || 4096,
messages: buildAnthropicMessages(user_messages),
model: model,
stream: true,
system: system_message?.content as string,
temperature: temperature,
top_p: top_p,
},
{ ...anthropicPayload, stream: true },
{ signal: options?.signal },
);

Expand Down Expand Up @@ -71,6 +61,15 @@ export class LobeAnthropicAI implements LobeRuntimeAI {
provider: ModelProvider.Anthropic,
});
}

case 403: {
throw AgentRuntimeError.chat({
endpoint: desensitizedEndpoint,
error: error as any,
errorType: AgentRuntimeErrorType.LocationNotSupportError,
provider: ModelProvider.Anthropic,
});
}

Check warning on line 72 in src/libs/agent-runtime/anthropic/index.ts

View check run for this annotation

Codecov / codecov/patch

src/libs/agent-runtime/anthropic/index.ts#L66-L72

Added lines #L66 - L72 were not covered by tests
default: {
break;
}
Expand All @@ -84,6 +83,22 @@ export class LobeAnthropicAI implements LobeRuntimeAI {
});
}
}

private buildAnthropicPayload(payload: ChatStreamPayload) {
const { messages, model, max_tokens, temperature, top_p } = payload;
const system_message = messages.find((m) => m.role === 'system');
const user_messages = messages.filter((m) => m.role !== 'system');

return {
max_tokens: max_tokens || 4096,
messages: buildAnthropicMessages(user_messages),
model: model,
stream: true,
system: system_message?.content as string,
temperature: temperature,
top_p: top_p,
};
}
}

export default LobeAnthropicAI;
65 changes: 64 additions & 1 deletion src/libs/agent-runtime/utils/anthropicHelpers.test.ts
@@ -1,7 +1,11 @@
import { describe, expect, it } from 'vitest';

import { OpenAIChatMessage, UserMessageContentPart } from '../types/chat';
import { buildAnthropicBlock, buildAnthropicMessage } from './anthropicHelpers';
import {
buildAnthropicBlock,
buildAnthropicMessage,
buildAnthropicMessages,
} from './anthropicHelpers';
import { parseDataUri } from './uriParser';

describe('anthropicHelpers', () => {
Expand Down Expand Up @@ -48,4 +52,63 @@ describe('anthropicHelpers', () => {
expect(result).toEqual({ content: [{ type: 'text', text: 'Hello!' }], role: 'assistant' });
});
});

describe('buildAnthropicMessages', () => {
it('should correctly convert OpenAI Messages to Anthropic Messages', () => {
const messages: OpenAIChatMessage[] = [
{ content: 'Hello', role: 'user' },
{ content: 'Hi', role: 'assistant' },
];

const result = buildAnthropicMessages(messages);
expect(result).toHaveLength(2);
expect(result).toEqual([
{ content: 'Hello', role: 'user' },
{ content: 'Hi', role: 'assistant' },
]);
});

it('messages should end with user', () => {
const messages: OpenAIChatMessage[] = [
{ content: 'Hello', role: 'user' },
{ content: 'Hello', role: 'user' },
{ content: 'Hi', role: 'assistant' },
];

const contents = buildAnthropicMessages(messages);

expect(contents).toHaveLength(4);
expect(contents).toEqual([
{ content: 'Hello', role: 'user' },
{ content: '_', role: 'assistant' },
{ content: 'Hello', role: 'user' },
{ content: 'Hi', role: 'assistant' },
]);
});

it('messages should pair', () => {
const messages: OpenAIChatMessage[] = [
{ content: 'a', role: 'assistant' },
{ content: 'b', role: 'assistant' },
{ content: 'c', role: 'assistant' },
{ content: 'd', role: 'assistant' },
{ content: '浣犲ソ', role: 'user' },
];

const contents = buildAnthropicMessages(messages);

expect(contents).toHaveLength(9);
expect(contents).toEqual([
{ content: '_', role: 'user' },
{ content: 'a', role: 'assistant' },
{ content: '_', role: 'user' },
{ content: 'b', role: 'assistant' },
{ content: '_', role: 'user' },
{ content: 'c', role: 'assistant' },
{ content: '_', role: 'user' },
{ content: 'd', role: 'assistant' },
{ content: '浣犲ソ', role: 'user' },
]);
});
});
});
20 changes: 18 additions & 2 deletions src/libs/agent-runtime/utils/anthropicHelpers.ts
Expand Up @@ -37,5 +37,21 @@ export const buildAnthropicMessage = (
};

export const buildAnthropicMessages = (
messages: OpenAIChatMessage[],
): Anthropic.Messages.MessageParam[] => messages.map((message) => buildAnthropicMessage(message));
oaiMessages: OpenAIChatMessage[],
): Anthropic.Messages.MessageParam[] => {
const messages: Anthropic.Messages.MessageParam[] = [];
let lastRole = 'assistant';

oaiMessages.forEach((message) => {
const anthropicMessage = buildAnthropicMessage(message);

if (lastRole === anthropicMessage.role) {
messages.push({ content: '_', role: lastRole === 'user' ? 'assistant' : 'user' });
}

lastRole = anthropicMessage.role;
messages.push(anthropicMessage);
});

return messages;
};

0 comments on commit 0e01db0

Please sign in to comment.