mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-17 14:27:02 +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:
@@ -10,7 +10,10 @@ import {
|
||||
getBlockSuiteEditorTitle,
|
||||
waitForEditorLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
import { clickSideBarAllPageButton } from '@affine-test/kit/utils/sidebar';
|
||||
import {
|
||||
clickSideBarAllPageButton,
|
||||
clickSideBarUseAvatar,
|
||||
} from '@affine-test/kit/utils/sidebar';
|
||||
import { createLocalWorkspace } from '@affine-test/kit/utils/workspace';
|
||||
import { expect, type Page } from '@playwright/test';
|
||||
|
||||
@@ -48,14 +51,15 @@ function getUser() {
|
||||
};
|
||||
}
|
||||
|
||||
test.skip(
|
||||
() =>
|
||||
!process.env.COPILOT_OPENAI_API_KEY ||
|
||||
!process.env.COPILOT_FAL_API_KEY ||
|
||||
process.env.COPILOT_OPENAI_API_KEY === '1' ||
|
||||
process.env.COPILOT_FAL_API_KEY === '1',
|
||||
'skip test if no copilot api key'
|
||||
);
|
||||
const isCopilotConfigured =
|
||||
!!process.env.COPILOT_OPENAI_API_KEY &&
|
||||
!!process.env.COPILOT_FAL_API_KEY &&
|
||||
!!process.env.COPILOT_PERPLEXITY_API_KEY &&
|
||||
process.env.COPILOT_OPENAI_API_KEY !== '1' &&
|
||||
process.env.COPILOT_FAL_API_KEY !== '1' &&
|
||||
process.env.COPILOT_PERPLEXITY_API_KEY !== '1';
|
||||
|
||||
test.skip(() => !isCopilotConfigured, 'skip test if no copilot api key');
|
||||
|
||||
test('can open chat side panel', async ({ page }) => {
|
||||
await openHomePage(page);
|
||||
@@ -68,13 +72,17 @@ test('can open chat side panel', async ({ page }) => {
|
||||
await expect(page.getByTestId('sidebar-tab-content-chat')).toBeVisible();
|
||||
});
|
||||
|
||||
const makeChat = async (page: Page, content: string) => {
|
||||
const openChat = async (page: Page) => {
|
||||
if (await page.getByTestId('sidebar-tab-chat').isHidden()) {
|
||||
await page.getByTestId('right-sidebar-toggle').click({
|
||||
delay: 200,
|
||||
});
|
||||
}
|
||||
await page.getByTestId('sidebar-tab-chat').click();
|
||||
};
|
||||
|
||||
const makeChat = async (page: Page, content: string) => {
|
||||
await openChat(page);
|
||||
await page.getByTestId('chat-panel-input').focus();
|
||||
await page.keyboard.type(content);
|
||||
await page.keyboard.press('Enter');
|
||||
@@ -83,6 +91,7 @@ const makeChat = async (page: Page, content: string) => {
|
||||
const clearChat = async (page: Page) => {
|
||||
await page.getByTestId('chat-panel-clear').click();
|
||||
await page.getByTestId('confirm-modal-confirm').click();
|
||||
await page.waitForTimeout(500);
|
||||
};
|
||||
|
||||
const collectChat = async (page: Page) => {
|
||||
@@ -343,6 +352,48 @@ test.describe('chat panel', () => {
|
||||
expect(editorContent).toBe('');
|
||||
}
|
||||
});
|
||||
|
||||
test('can open and close network search', async ({ page }) => {
|
||||
await page.reload();
|
||||
await clickSideBarAllPageButton(page);
|
||||
await page.waitForTimeout(200);
|
||||
await createLocalWorkspace({ name: 'test' }, page);
|
||||
await clickNewPageButton(page);
|
||||
await clickSideBarUseAvatar(page);
|
||||
await page.getByTestId('workspace-modal-account-settings-option').click();
|
||||
await page.getByTestId('experimental-features-trigger').click();
|
||||
await page
|
||||
.getByTestId('experimental-prompt')
|
||||
.getByTestId('affine-checkbox')
|
||||
.click();
|
||||
await page.getByTestId('experimental-confirm-button').click();
|
||||
await page.getByTestId('enable_ai_network_search').click();
|
||||
await page.getByTestId('modal-close-button').click();
|
||||
await openChat(page);
|
||||
await page.getByTestId('chat-network-search').click();
|
||||
await makeChat(page, 'hello');
|
||||
let history = await collectChat(page);
|
||||
expect(history[0]).toEqual({
|
||||
name: 'You',
|
||||
content: 'hello',
|
||||
});
|
||||
expect(history[1].name).toBe('AFFiNE AI');
|
||||
expect(
|
||||
await page.locator('chat-panel affine-link').count()
|
||||
).toBeGreaterThan(0);
|
||||
|
||||
await clearChat(page);
|
||||
expect((await collectChat(page)).length).toBe(0);
|
||||
await page.getByTestId('chat-network-search').click();
|
||||
await makeChat(page, 'hello');
|
||||
history = await collectChat(page);
|
||||
expect(history[0]).toEqual({
|
||||
name: 'You',
|
||||
content: 'hello',
|
||||
});
|
||||
expect(history[1].name).toBe('AFFiNE AI');
|
||||
expect(await page.locator('chat-panel affine-link').count()).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('chat with block', () => {
|
||||
|
||||
Reference in New Issue
Block a user