Skip to content

Commit

Permalink
🐛 fix: MiniMax output long content interrupted by non-existent error (#…
Browse files Browse the repository at this point in the history
…4088)

* Update index.ts

* Update index.test.ts

* Update index.ts

* Update minimax.ts

* Update minimax.ts

* fix

* Update minimax.ts

* Create minimax.test.ts

* Update minimax.ts

* Update minimax.ts

* Update minimax.ts
  • Loading branch information
sxjeru committed Sep 25, 2024
1 parent b1442b9 commit 4f6e20d
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 10 deletions.
8 changes: 4 additions & 4 deletions src/libs/agent-runtime/minimax/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,10 @@ describe('LobeMinimaxAI', () => {
});
});

it('should include max tokens when model is abab6.5-chat', () => {
it('should include max tokens when model is abab6.5t-chat', () => {
const payload: ChatStreamPayload = {
messages: [{ content: 'Hello', role: 'user' }],
model: 'abab6.5-chat',
model: 'abab6.5t-chat',
temperature: 0,
top_p: 0,
};
Expand All @@ -265,9 +265,9 @@ describe('LobeMinimaxAI', () => {

expect(result).toEqual({
messages: [{ content: 'Hello', role: 'user' }],
model: 'abab6.5-chat',
model: 'abab6.5t-chat',
stream: true,
max_tokens: 2048,
max_tokens: 4096,
});
});
});
Expand Down
22 changes: 16 additions & 6 deletions src/libs/agent-runtime/minimax/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,14 @@ export class LobeMinimaxAI implements LobeRuntimeAI {
// https://www.minimaxi.com/document/guides/chat-model/V2
private getMaxTokens(model: string): number | undefined {
switch (model) {
case 'abab6.5-chat':
case 'abab6.5t-chat':
case 'abab6.5g-chat':
case 'abab5.5s-chat':
case 'abab5.5-chat':{
return 4096;
}
case 'abab6.5s-chat': {
return 2048;
return 8192;
}
}
}
Expand All @@ -139,12 +144,17 @@ export class LobeMinimaxAI implements LobeRuntimeAI {

return {
...params,
max_tokens: this.getMaxTokens(payload.model),
frequency_penalty: undefined,
max_tokens:
payload.max_tokens !== undefined
? payload.max_tokens
: this.getMaxTokens(payload.model),
presence_penalty: undefined,
stream: true,
temperature:
temperature === undefined || temperature <= 0
? undefined
: temperature / 2,
temperature === undefined || temperature <= 0
? undefined
: temperature / 2,

tools: params.tools?.map((tool) => ({
function: {
Expand Down
24 changes: 24 additions & 0 deletions src/libs/agent-runtime/utils/streams/minimax.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { describe, it, expect } from 'vitest';
import { processDoubleData } from './minimax'; // 假设文件名为 minimax.ts

describe('processDoubleData', () => {
it('should remove the second "data: {"id": and everything after it when matchCount is 2', () => {
const chunkValue = `data: {"id":"first"} some other text
data: {"id":"second"} more text`;
const result = processDoubleData(chunkValue);
expect(result).toBe('data: {"id":"first"} some other text');
});

it('should not modify chunkValue when matchCount is not 2', () => {
const chunkValue = `data: {"id":"first"} some other text`;
const result = processDoubleData(chunkValue);
expect(result).toBe(chunkValue);
});

it('should not modify chunkValue when matchCount is more than 2', () => {
const chunkValue = `data: {"id":"first"} some other text data: {"id":"second"} more text data: {"id":"third"} even more text`;
const result = processDoubleData(chunkValue);
expect(result).toBe(chunkValue);
});
});
15 changes: 15 additions & 0 deletions src/libs/agent-runtime/utils/streams/minimax.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ import { ChatStreamCallbacks } from '../../types';
import { transformOpenAIStream } from './openai';
import { createCallbacksTransformer, createSSEProtocolTransformer } from './protocol';

export const processDoubleData = (chunkValue: string): string => {
const dataPattern = /data: {"id":"/g;
const matchCount = (chunkValue.match(dataPattern) || []).length;
let modifiedChunkValue = chunkValue;
if (matchCount === 2) {
const secondDataIdIndex = chunkValue.indexOf('data: {"id":', chunkValue.indexOf('data: {"id":') + 1);
if (secondDataIdIndex !== -1) {
modifiedChunkValue = chunkValue.slice(0, secondDataIdIndex).trim();
}
}
return modifiedChunkValue;
};

const unit8ArrayToJSONChunk = (unit8Array: Uint8Array): OpenAI.ChatCompletionChunk => {
const decoder = new TextDecoder();

Expand All @@ -12,6 +25,8 @@ const unit8ArrayToJSONChunk = (unit8Array: Uint8Array): OpenAI.ChatCompletionChu
// chunkValue example:
// data: {"id":"028a65377137d57aaceeffddf48ae99f","choices":[{"finish_reason":"tool_calls","index":0,"delta":{"role":"assistant","tool_calls":[{"id":"call_function_7371372822","type":"function","function":{"name":"realtime-weather____fetchCurrentWeather","arguments":"{\"city\": [\"杭州\", \"北京\"]}"}}]}}],"created":155511,"model":"abab6.5s-chat","object":"chat.completion.chunk"}

chunkValue = processDoubleData(chunkValue);

// so we need to remove `data:` prefix and then parse it as JSON
if (chunkValue.startsWith('data:')) {
chunkValue = chunkValue.slice(5).trim();
Expand Down

0 comments on commit 4f6e20d

Please sign in to comment.