mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-25 06:18:45 +08:00
feat(core): support ai network search (#9357)
### What Changed?
- Add `PerplexityProvider` in backend.
- Update session prompt name if user toggle network search mode in chat panel.
- Add experimental flag for AI network search feature.
- Add unit tests and e2e tests.
Search results are streamed and appear word for word:
<div class='graphite__hidden'>
<div>🎥 Video uploaded on Graphite:</div>
<a href="https://app.graphite.dev/media/video/sJGviKxfE3Ap685cl5bj/56f6ec7b-4b21-405f-9612-43e083f6fb84.mov">
<img src="https://app.graphite.dev/api/v1/graphite/video/thumbnail/sJGviKxfE3Ap685cl5bj/56f6ec7b-4b21-405f-9612-43e083f6fb84.mov">
</a>
</div>
<video src="https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/sJGviKxfE3Ap685cl5bj/56f6ec7b-4b21-405f-9612-43e083f6fb84.mov">录屏2024-12-27 18.58.40.mov</video>
Click the little globe icon to manually turn on/off Internet search:
<div class='graphite__hidden'>
<div>🎥 Video uploaded on Graphite:</div>
<a href="https://app.graphite.dev/media/video/sJGviKxfE3Ap685cl5bj/778f1406-bf29-498e-a90d-7dad813392d1.mov">
<img src="https://app.graphite.dev/api/v1/graphite/video/thumbnail/sJGviKxfE3Ap685cl5bj/778f1406-bf29-498e-a90d-7dad813392d1.mov">
</a>
</div>
<video src="https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/sJGviKxfE3Ap685cl5bj/778f1406-bf29-498e-a90d-7dad813392d1.mov">录屏2024-12-27 19.01.16.mov</video>
When there is an image, it will automatically switch to the openai model:
<div class='graphite__hidden'>
<div>🎥 Video uploaded on Graphite:</div>
<a href="https://app.graphite.dev/media/video/sJGviKxfE3Ap685cl5bj/56431d8e-75e1-4d84-ab4a-b6636042cc6a.mov">
<img src="https://app.graphite.dev/api/v1/graphite/video/thumbnail/sJGviKxfE3Ap685cl5bj/56431d8e-75e1-4d84-ab4a-b6636042cc6a.mov">
</a>
</div>
<video src="https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/sJGviKxfE3Ap685cl5bj/56431d8e-75e1-4d84-ab4a-b6636042cc6a.mov">录屏2024-12-27 19.02.13.mov</video>
This commit is contained in:
@@ -16,6 +16,7 @@ import {
|
||||
CopilotProviderService,
|
||||
FalProvider,
|
||||
OpenAIProvider,
|
||||
PerplexityProvider,
|
||||
registerCopilotProvider,
|
||||
unregisterCopilotProvider,
|
||||
} from '../src/plugins/copilot/providers';
|
||||
@@ -41,6 +42,7 @@ import {
|
||||
sse2array,
|
||||
textToEventStream,
|
||||
unsplashSearch,
|
||||
updateCopilotSession,
|
||||
} from './utils/copilot';
|
||||
|
||||
const test = ava as TestFn<{
|
||||
@@ -63,6 +65,9 @@ test.beforeEach(async t => {
|
||||
fal: {
|
||||
apiKey: '1',
|
||||
},
|
||||
perplexity: {
|
||||
apiKey: '1',
|
||||
},
|
||||
unsplashKey: process.env.UNSPLASH_ACCESS_KEY || '1',
|
||||
},
|
||||
},
|
||||
@@ -91,6 +96,7 @@ test.beforeEach(async t => {
|
||||
|
||||
unregisterCopilotProvider(OpenAIProvider.type);
|
||||
unregisterCopilotProvider(FalProvider.type);
|
||||
unregisterCopilotProvider(PerplexityProvider.type);
|
||||
registerCopilotProvider(MockCopilotTestProvider);
|
||||
|
||||
await prompt.set(promptName, 'test', [
|
||||
@@ -156,6 +162,85 @@ test('should create session correctly', async t => {
|
||||
}
|
||||
});
|
||||
|
||||
test('should update session correctly', async t => {
|
||||
const { app } = t.context;
|
||||
|
||||
const assertUpdateSession = async (
|
||||
sessionId: string,
|
||||
error: string,
|
||||
asserter = async (x: any) => {
|
||||
t.truthy(await x, error);
|
||||
}
|
||||
) => {
|
||||
await asserter(updateCopilotSession(app, token, sessionId, promptName));
|
||||
};
|
||||
|
||||
{
|
||||
const { id: workspaceId } = await createWorkspace(app, token);
|
||||
const docId = randomUUID();
|
||||
const sessionId = await createCopilotSession(
|
||||
app,
|
||||
token,
|
||||
workspaceId,
|
||||
docId,
|
||||
promptName
|
||||
);
|
||||
await assertUpdateSession(
|
||||
sessionId,
|
||||
'should be able to update session with cloud workspace that user can access'
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
const sessionId = await createCopilotSession(
|
||||
app,
|
||||
token,
|
||||
randomUUID(),
|
||||
randomUUID(),
|
||||
promptName
|
||||
);
|
||||
await assertUpdateSession(
|
||||
sessionId,
|
||||
'should be able to update session with local workspace'
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
const aToken = (await signUp(app, 'test', 'test@affine.pro', '123456'))
|
||||
.token.token;
|
||||
const { id: workspaceId } = await createWorkspace(app, aToken);
|
||||
const inviteId = await inviteUser(
|
||||
app,
|
||||
aToken,
|
||||
workspaceId,
|
||||
'darksky@affine.pro'
|
||||
);
|
||||
await acceptInviteById(app, workspaceId, inviteId, false);
|
||||
const sessionId = await createCopilotSession(
|
||||
app,
|
||||
token,
|
||||
workspaceId,
|
||||
randomUUID(),
|
||||
promptName
|
||||
);
|
||||
await assertUpdateSession(
|
||||
sessionId,
|
||||
'should able to update session after user have permission'
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
const sessionId = '123456';
|
||||
await assertUpdateSession(sessionId, '', async x => {
|
||||
await t.throwsAsync(
|
||||
x,
|
||||
{ instanceOf: Error },
|
||||
'should not able to update invalid session id'
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
test('should fork session correctly', async t => {
|
||||
const { app } = t.context;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user