mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-02 09:59:55 +08:00
feat(server): adapt gpt5 (#13478)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - New Features - Added GPT-5 family and made GPT-5/-mini the new defaults for Copilot scenarios and prompts. - Bug Fixes - Improved streaming chunk formats and reasoning/text semantics, consistent attachment mediaType handling, and more reliable reranking via log-prob handling. - Refactor - Unified maxOutputTokens usage; removed per-call step caps and migrated several tools to a unified inputSchema shape. - Chores - Upgraded AI SDK dependencies and bumped an internal dependency version. - Tests - Updated mocks and tests to reference GPT-5 variants and new stream formats. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -118,11 +118,11 @@ test.serial.before(async t => {
|
||||
enabled: true,
|
||||
scenarios: {
|
||||
image: 'flux-1/schnell',
|
||||
rerank: 'gpt-4.1-mini',
|
||||
complex_text_generation: 'gpt-4.1-mini',
|
||||
coding: 'gpt-4.1-mini',
|
||||
quick_decision_making: 'gpt-4.1-mini',
|
||||
quick_text_generation: 'gpt-4.1-mini',
|
||||
rerank: 'gpt-5-mini',
|
||||
complex_text_generation: 'gpt-5-mini',
|
||||
coding: 'gpt-5-mini',
|
||||
quick_decision_making: 'gpt-5-mini',
|
||||
quick_text_generation: 'gpt-5-mini',
|
||||
polish_and_summarize: 'gemini-2.5-flash',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -5,6 +5,7 @@ import { ProjectRoot } from '@affine-tools/utils/path';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import type { TestFn } from 'ava';
|
||||
import ava from 'ava';
|
||||
import { nanoid } from 'nanoid';
|
||||
import Sinon from 'sinon';
|
||||
|
||||
import { EventBus, JobQueue } from '../base';
|
||||
@@ -1340,16 +1341,16 @@ test('TextStreamParser should format different types of chunks correctly', t =>
|
||||
textDelta: {
|
||||
chunk: {
|
||||
type: 'text-delta' as const,
|
||||
textDelta: 'Hello world',
|
||||
} as any,
|
||||
text: 'Hello world',
|
||||
},
|
||||
expected: 'Hello world',
|
||||
description: 'should format text-delta correctly',
|
||||
},
|
||||
reasoning: {
|
||||
chunk: {
|
||||
type: 'reasoning' as const,
|
||||
textDelta: 'I need to think about this',
|
||||
} as any,
|
||||
type: 'reasoning-delta' as const,
|
||||
text: 'I need to think about this',
|
||||
},
|
||||
expected: '\n> [!]\n> I need to think about this',
|
||||
description: 'should format reasoning as callout',
|
||||
},
|
||||
@@ -1358,8 +1359,8 @@ test('TextStreamParser should format different types of chunks correctly', t =>
|
||||
type: 'tool-call' as const,
|
||||
toolName: 'web_search_exa' as const,
|
||||
toolCallId: 'test-id-1',
|
||||
args: { query: 'test query', mode: 'AUTO' as const },
|
||||
} as any,
|
||||
input: { query: 'test query', mode: 'AUTO' as const },
|
||||
},
|
||||
expected: '\n> [!]\n> \n> Searching the web "test query"\n> ',
|
||||
description: 'should format web search tool call correctly',
|
||||
},
|
||||
@@ -1368,8 +1369,8 @@ test('TextStreamParser should format different types of chunks correctly', t =>
|
||||
type: 'tool-call' as const,
|
||||
toolName: 'web_crawl_exa' as const,
|
||||
toolCallId: 'test-id-2',
|
||||
args: { url: 'https://example.com' },
|
||||
} as any,
|
||||
input: { url: 'https://example.com' },
|
||||
},
|
||||
expected: '\n> [!]\n> \n> Crawling the web "https://example.com"\n> ',
|
||||
description: 'should format web crawl tool call correctly',
|
||||
},
|
||||
@@ -1378,8 +1379,8 @@ test('TextStreamParser should format different types of chunks correctly', t =>
|
||||
type: 'tool-result' as const,
|
||||
toolName: 'web_search_exa' as const,
|
||||
toolCallId: 'test-id-1',
|
||||
args: { query: 'test query', mode: 'AUTO' as const },
|
||||
result: [
|
||||
input: { query: 'test query', mode: 'AUTO' as const },
|
||||
output: [
|
||||
{
|
||||
title: 'Test Title',
|
||||
url: 'https://test.com',
|
||||
@@ -1406,7 +1407,7 @@ test('TextStreamParser should format different types of chunks correctly', t =>
|
||||
chunk: {
|
||||
type: 'error' as const,
|
||||
error: { type: 'testError', message: 'Test error message' },
|
||||
} as any,
|
||||
},
|
||||
errorMessage: 'Test error message',
|
||||
description: 'should throw error for error chunks',
|
||||
},
|
||||
@@ -1436,78 +1437,85 @@ test('TextStreamParser should process a sequence of message chunks', t => {
|
||||
chunks: [
|
||||
// Reasoning chunks
|
||||
{
|
||||
type: 'reasoning' as const,
|
||||
textDelta: 'The user is asking about',
|
||||
} as any,
|
||||
id: nanoid(),
|
||||
type: 'reasoning-delta' as const,
|
||||
text: 'The user is asking about',
|
||||
},
|
||||
{
|
||||
type: 'reasoning' as const,
|
||||
textDelta: ' recent advances in quantum computing',
|
||||
} as any,
|
||||
id: nanoid(),
|
||||
type: 'reasoning-delta' as const,
|
||||
text: ' recent advances in quantum computing',
|
||||
},
|
||||
{
|
||||
type: 'reasoning' as const,
|
||||
textDelta: ' and how it might impact',
|
||||
} as any,
|
||||
id: nanoid(),
|
||||
type: 'reasoning-delta' as const,
|
||||
text: ' and how it might impact',
|
||||
},
|
||||
{
|
||||
type: 'reasoning' as const,
|
||||
textDelta: ' cryptography and data security.',
|
||||
} as any,
|
||||
id: nanoid(),
|
||||
type: 'reasoning-delta' as const,
|
||||
text: ' cryptography and data security.',
|
||||
},
|
||||
{
|
||||
type: 'reasoning' as const,
|
||||
textDelta:
|
||||
' I should provide information on quantum supremacy achievements',
|
||||
} as any,
|
||||
id: nanoid(),
|
||||
type: 'reasoning-delta' as const,
|
||||
text: ' I should provide information on quantum supremacy achievements',
|
||||
},
|
||||
|
||||
// Text delta
|
||||
{
|
||||
id: nanoid(),
|
||||
type: 'text-delta' as const,
|
||||
textDelta:
|
||||
'Let me search for the latest breakthroughs in quantum computing and their ',
|
||||
} as any,
|
||||
text: 'Let me search for the latest breakthroughs in quantum computing and their ',
|
||||
},
|
||||
|
||||
// Tool call
|
||||
{
|
||||
type: 'tool-call' as const,
|
||||
toolCallId: 'toolu_01ABCxyz123456789',
|
||||
toolName: 'web_search_exa' as const,
|
||||
args: {
|
||||
input: {
|
||||
query: 'latest quantum computing breakthroughs cryptography impact',
|
||||
},
|
||||
} as any,
|
||||
},
|
||||
|
||||
// Tool result
|
||||
{
|
||||
type: 'tool-result' as const,
|
||||
toolCallId: 'toolu_01ABCxyz123456789',
|
||||
toolName: 'web_search_exa' as const,
|
||||
args: {
|
||||
input: {
|
||||
query: 'latest quantum computing breakthroughs cryptography impact',
|
||||
},
|
||||
result: [
|
||||
output: [
|
||||
{
|
||||
title: 'IBM Unveils 1000-Qubit Quantum Processor',
|
||||
url: 'https://example.com/tech/quantum-computing-milestone',
|
||||
},
|
||||
],
|
||||
} as any,
|
||||
},
|
||||
|
||||
// More text deltas
|
||||
{
|
||||
id: nanoid(),
|
||||
type: 'text-delta' as const,
|
||||
textDelta: 'implications for security.',
|
||||
} as any,
|
||||
text: 'implications for security.',
|
||||
},
|
||||
{
|
||||
id: nanoid(),
|
||||
type: 'text-delta' as const,
|
||||
textDelta: '\n\nQuantum computing has made ',
|
||||
} as any,
|
||||
text: '\n\nQuantum computing has made ',
|
||||
},
|
||||
{
|
||||
id: nanoid(),
|
||||
type: 'text-delta' as const,
|
||||
textDelta: 'remarkable progress in the past year. ',
|
||||
} as any,
|
||||
text: 'remarkable progress in the past year. ',
|
||||
},
|
||||
{
|
||||
id: nanoid(),
|
||||
type: 'text-delta' as const,
|
||||
textDelta:
|
||||
'The development of more stable qubits has accelerated research significantly.',
|
||||
} as any,
|
||||
text: 'The development of more stable qubits has accelerated research significantly.',
|
||||
},
|
||||
],
|
||||
expected:
|
||||
'\n> [!]\n> The user is asking about recent advances in quantum computing and how it might impact cryptography and data security. I should provide information on quantum supremacy achievements\n\nLet me search for the latest breakthroughs in quantum computing and their \n> [!]\n> \n> Searching the web "latest quantum computing breakthroughs cryptography impact"\n> \n> \n> \n> [IBM Unveils 1000-Qubit Quantum Processor](https://example.com/tech/quantum-computing-milestone)\n> \n> \n> \n\nimplications for security.\n\nQuantum computing has made remarkable progress in the past year. The development of more stable qubits has accelerated research significantly.',
|
||||
|
||||
@@ -57,15 +57,6 @@ export class MockCopilotProvider extends OpenAIProvider {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'gpt-4.1',
|
||||
capabilities: [
|
||||
{
|
||||
input: [ModelInputType.Text, ModelInputType.Image],
|
||||
output: [ModelOutputType.Text, ModelOutputType.Object],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'gpt-4.1-2025-04-14',
|
||||
capabilities: [
|
||||
@@ -76,7 +67,25 @@ export class MockCopilotProvider extends OpenAIProvider {
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'gpt-4.1-mini',
|
||||
id: 'gpt-5',
|
||||
capabilities: [
|
||||
{
|
||||
input: [ModelInputType.Text, ModelInputType.Image],
|
||||
output: [ModelOutputType.Text, ModelOutputType.Object],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'gpt-5-2025-08-07',
|
||||
capabilities: [
|
||||
{
|
||||
input: [ModelInputType.Text, ModelInputType.Image],
|
||||
output: [ModelOutputType.Text, ModelOutputType.Object],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'gpt-5-mini',
|
||||
capabilities: [
|
||||
{
|
||||
input: [ModelInputType.Text, ModelInputType.Image],
|
||||
|
||||
@@ -48,7 +48,7 @@ let docId = 'doc1';
|
||||
|
||||
test.beforeEach(async t => {
|
||||
await t.context.module.initTestingDB();
|
||||
await t.context.copilotSession.createPrompt('prompt-name', 'gpt-4.1');
|
||||
await t.context.copilotSession.createPrompt('prompt-name', 'gpt-5-mini');
|
||||
user = await t.context.user.create({
|
||||
email: 'test@affine.pro',
|
||||
});
|
||||
|
||||
@@ -58,9 +58,9 @@ const createTestPrompts = async (
|
||||
copilotSession: CopilotSessionModel,
|
||||
db: PrismaClient
|
||||
) => {
|
||||
await copilotSession.createPrompt(TEST_PROMPTS.NORMAL, 'gpt-4.1');
|
||||
await copilotSession.createPrompt(TEST_PROMPTS.NORMAL, 'gpt-5-mini');
|
||||
await db.aiPrompt.create({
|
||||
data: { name: TEST_PROMPTS.ACTION, model: 'gpt-4.1', action: 'edit' },
|
||||
data: { name: TEST_PROMPTS.ACTION, model: 'gpt-5-mini', action: 'edit' },
|
||||
});
|
||||
};
|
||||
|
||||
@@ -116,7 +116,7 @@ const addMessagesToSession = async (
|
||||
await copilotSession.updateMessages({
|
||||
sessionId,
|
||||
userId: user.id,
|
||||
prompt: { model: 'gpt-4.1' },
|
||||
prompt: { model: 'gpt-5-mini' },
|
||||
messages: [
|
||||
{
|
||||
role: 'user',
|
||||
@@ -807,7 +807,7 @@ test('should handle fork and session attachment operations', async t => {
|
||||
pinned: forkConfig.pinned,
|
||||
title: null,
|
||||
parentSessionId,
|
||||
prompt: { name: TEST_PROMPTS.NORMAL, action: null, model: 'gpt-4.1' },
|
||||
prompt: { name: TEST_PROMPTS.NORMAL, action: null, model: 'gpt-5-mini' },
|
||||
messages: [
|
||||
{
|
||||
role: 'user',
|
||||
|
||||
Reference in New Issue
Block a user