feat: improve prompt management (#7853)
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "ai_prompts_metadata" ADD COLUMN "modified" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
ADD COLUMN "updated_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP;
|
||||||
@@ -367,6 +367,9 @@ model AiPrompt {
|
|||||||
model String @db.VarChar
|
model String @db.VarChar
|
||||||
config Json? @db.Json
|
config Json? @db.Json
|
||||||
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
|
||||||
|
updatedAt DateTime @default(now()) @map("updated_at") @db.Timestamptz(3)
|
||||||
|
// whether the prompt is modified by the admin panel
|
||||||
|
modified Boolean @default(false)
|
||||||
|
|
||||||
messages AiPromptMessage[]
|
messages AiPromptMessage[]
|
||||||
sessions AiSession[]
|
sessions AiSession[]
|
||||||
|
|||||||
@@ -33,7 +33,10 @@ export class ChatPrompt {
|
|||||||
private readonly templateParams: PromptParams = {};
|
private readonly templateParams: PromptParams = {};
|
||||||
|
|
||||||
static createFromPrompt(
|
static createFromPrompt(
|
||||||
options: Omit<AiPrompt, 'id' | 'createdAt' | 'config'> & {
|
options: Omit<
|
||||||
|
AiPrompt,
|
||||||
|
'id' | 'createdAt' | 'updatedAt' | 'modified' | 'config'
|
||||||
|
> & {
|
||||||
messages: PromptMessage[];
|
messages: PromptMessage[];
|
||||||
config: PromptConfig | undefined;
|
config: PromptConfig | undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
|
import { Logger } from '@nestjs/common';
|
||||||
import { AiPrompt, PrismaClient } from '@prisma/client';
|
import { AiPrompt, PrismaClient } from '@prisma/client';
|
||||||
|
|
||||||
import { PromptConfig, PromptMessage } from '../types';
|
import { PromptConfig, PromptMessage } from '../types';
|
||||||
|
|
||||||
type Prompt = Omit<AiPrompt, 'id' | 'createdAt' | 'action' | 'config'> & {
|
type Prompt = Omit<
|
||||||
|
AiPrompt,
|
||||||
|
'id' | 'createdAt' | 'updatedAt' | 'modified' | 'action' | 'config'
|
||||||
|
> & {
|
||||||
action?: string;
|
action?: string;
|
||||||
messages: PromptMessage[];
|
messages: PromptMessage[];
|
||||||
config?: PromptConfig;
|
config?: PromptConfig;
|
||||||
@@ -830,7 +834,7 @@ const chat: Prompt[] = [
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'chat:gpt4',
|
name: 'Chat With AFFiNE AI',
|
||||||
model: 'gpt-4o',
|
model: 'gpt-4o',
|
||||||
messages: [
|
messages: [
|
||||||
{
|
{
|
||||||
@@ -845,7 +849,20 @@ const chat: Prompt[] = [
|
|||||||
export const prompts: Prompt[] = [...actions, ...chat, ...workflows];
|
export const prompts: Prompt[] = [...actions, ...chat, ...workflows];
|
||||||
|
|
||||||
export async function refreshPrompts(db: PrismaClient) {
|
export async function refreshPrompts(db: PrismaClient) {
|
||||||
|
const needToSkip = await db.aiPrompt
|
||||||
|
.findMany({
|
||||||
|
where: { modified: true },
|
||||||
|
select: { name: true },
|
||||||
|
})
|
||||||
|
.then(p => p.map(p => p.name));
|
||||||
|
|
||||||
for (const prompt of prompts) {
|
for (const prompt of prompts) {
|
||||||
|
// skip prompt update if already modified by admin panel
|
||||||
|
if (needToSkip.includes(prompt.name)) {
|
||||||
|
new Logger('CopilotPrompt').warn(`Skip modified prompt: ${prompt.name}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await db.aiPrompt.upsert({
|
await db.aiPrompt.upsert({
|
||||||
create: {
|
create: {
|
||||||
name: prompt.name,
|
name: prompt.name,
|
||||||
@@ -865,6 +882,7 @@ export async function refreshPrompts(db: PrismaClient) {
|
|||||||
update: {
|
update: {
|
||||||
action: prompt.action,
|
action: prompt.action,
|
||||||
model: prompt.model,
|
model: prompt.model,
|
||||||
|
updatedAt: new Date(),
|
||||||
messages: {
|
messages: {
|
||||||
deleteMany: {},
|
deleteMany: {},
|
||||||
create: prompt.messages.map((message, idx) => ({
|
create: prompt.messages.map((message, idx) => ({
|
||||||
|
|||||||
@@ -38,16 +38,11 @@ export class PromptService implements OnModuleInit {
|
|||||||
model: true,
|
model: true,
|
||||||
config: true,
|
config: true,
|
||||||
messages: {
|
messages: {
|
||||||
select: {
|
select: { role: true, content: true, params: true },
|
||||||
role: true,
|
orderBy: { idx: 'asc' },
|
||||||
content: true,
|
|
||||||
params: true,
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
idx: 'asc',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
orderBy: { action: { sort: 'asc', nulls: 'first' } },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,11 +116,18 @@ export class PromptService implements OnModuleInit {
|
|||||||
.then(ret => ret.id);
|
.then(ret => ret.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
async update(name: string, messages: PromptMessage[], config?: PromptConfig) {
|
async update(
|
||||||
|
name: string,
|
||||||
|
messages: PromptMessage[],
|
||||||
|
modifyByApi: boolean = false,
|
||||||
|
config?: PromptConfig
|
||||||
|
) {
|
||||||
const { id } = await this.db.aiPrompt.update({
|
const { id } = await this.db.aiPrompt.update({
|
||||||
where: { name },
|
where: { name },
|
||||||
data: {
|
data: {
|
||||||
config: config || undefined,
|
config: config || undefined,
|
||||||
|
updatedAt: new Date(),
|
||||||
|
modified: modifyByApi,
|
||||||
messages: {
|
messages: {
|
||||||
// cleanup old messages
|
// cleanup old messages
|
||||||
deleteMany: {},
|
deleteMany: {},
|
||||||
|
|||||||
@@ -517,7 +517,16 @@ export class PromptsManagementResolver {
|
|||||||
description: 'List all copilot prompts',
|
description: 'List all copilot prompts',
|
||||||
})
|
})
|
||||||
async listCopilotPrompts() {
|
async listCopilotPrompts() {
|
||||||
return this.promptService.list();
|
const prompts = await this.promptService.list();
|
||||||
|
return prompts.filter(
|
||||||
|
p =>
|
||||||
|
p.messages.length > 0 &&
|
||||||
|
// ignore internal prompts
|
||||||
|
!p.name.startsWith('workflow:') &&
|
||||||
|
!p.name.startsWith('debug:') &&
|
||||||
|
!p.name.startsWith('chat:') &&
|
||||||
|
!p.name.startsWith('action:')
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Mutation(() => CopilotPromptType, {
|
@Mutation(() => CopilotPromptType, {
|
||||||
@@ -544,7 +553,7 @@ export class PromptsManagementResolver {
|
|||||||
@Args('messages', { type: () => [CopilotPromptMessageType] })
|
@Args('messages', { type: () => [CopilotPromptMessageType] })
|
||||||
messages: CopilotPromptMessageType[]
|
messages: CopilotPromptMessageType[]
|
||||||
) {
|
) {
|
||||||
await this.promptService.update(name, messages);
|
await this.promptService.update(name, messages, true);
|
||||||
return this.promptService.get(name);
|
return this.promptService.get(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,10 +81,10 @@ export const router = _createBrowserRouter(
|
|||||||
path: 'accounts',
|
path: 'accounts',
|
||||||
lazy: () => import('./modules/accounts'),
|
lazy: () => import('./modules/accounts'),
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// path: 'ai',
|
path: 'ai',
|
||||||
// lazy: () => import('./modules/ai'),
|
lazy: () => import('./modules/ai'),
|
||||||
// },
|
},
|
||||||
{
|
{
|
||||||
path: 'config',
|
path: 'config',
|
||||||
lazy: () => import('./modules/config'),
|
lazy: () => import('./modules/config'),
|
||||||
|
|||||||
@@ -9,12 +9,23 @@ import { useRightPanel } from '../layout';
|
|||||||
import type { Prompt } from './prompts';
|
import type { Prompt } from './prompts';
|
||||||
import { usePrompt } from './use-prompt';
|
import { usePrompt } from './use-prompt';
|
||||||
|
|
||||||
export function EditPrompt({ item }: { item: Prompt }) {
|
export function EditPrompt({
|
||||||
|
item,
|
||||||
|
setCanSave,
|
||||||
|
}: {
|
||||||
|
item: Prompt;
|
||||||
|
setCanSave: (changed: boolean) => void;
|
||||||
|
}) {
|
||||||
const { closePanel } = useRightPanel();
|
const { closePanel } = useRightPanel();
|
||||||
|
|
||||||
const [messages, setMessages] = useState(item.messages);
|
const [messages, setMessages] = useState(item.messages);
|
||||||
const { updatePrompt } = usePrompt();
|
const { updatePrompt } = usePrompt();
|
||||||
|
|
||||||
|
const disableSave = useMemo(
|
||||||
|
() => JSON.stringify(messages) === JSON.stringify(item.messages),
|
||||||
|
[item.messages, messages]
|
||||||
|
);
|
||||||
|
|
||||||
const handleChange = useCallback(
|
const handleChange = useCallback(
|
||||||
(e: React.ChangeEvent<HTMLTextAreaElement>, index: number) => {
|
(e: React.ChangeEvent<HTMLTextAreaElement>, index: number) => {
|
||||||
const newMessages = [...messages];
|
const newMessages = [...messages];
|
||||||
@@ -23,8 +34,9 @@ export function EditPrompt({ item }: { item: Prompt }) {
|
|||||||
content: e.target.value,
|
content: e.target.value,
|
||||||
};
|
};
|
||||||
setMessages(newMessages);
|
setMessages(newMessages);
|
||||||
|
setCanSave(!disableSave);
|
||||||
},
|
},
|
||||||
[messages]
|
[disableSave, messages, setCanSave]
|
||||||
);
|
);
|
||||||
const handleClose = useCallback(() => {
|
const handleClose = useCallback(() => {
|
||||||
setMessages(item.messages);
|
setMessages(item.messages);
|
||||||
@@ -32,14 +44,11 @@ export function EditPrompt({ item }: { item: Prompt }) {
|
|||||||
}, [closePanel, item.messages]);
|
}, [closePanel, item.messages]);
|
||||||
|
|
||||||
const onConfirm = useCallback(() => {
|
const onConfirm = useCallback(() => {
|
||||||
updatePrompt({ name: item.name, messages });
|
if (!disableSave) {
|
||||||
|
updatePrompt({ name: item.name, messages });
|
||||||
|
}
|
||||||
handleClose();
|
handleClose();
|
||||||
}, [handleClose, item.name, messages, updatePrompt]);
|
}, [disableSave, handleClose, item.name, messages, updatePrompt]);
|
||||||
|
|
||||||
const disableSave = useMemo(
|
|
||||||
() => JSON.stringify(messages) === JSON.stringify(item.messages),
|
|
||||||
[item.messages, messages]
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setMessages(item.messages);
|
setMessages(item.messages);
|
||||||
@@ -71,74 +80,83 @@ export function EditPrompt({ item }: { item: Prompt }) {
|
|||||||
</div>
|
</div>
|
||||||
<Separator />
|
<Separator />
|
||||||
<ScrollArea>
|
<ScrollArea>
|
||||||
<div className="px-5 py-4 overflow-y-auto space-y-[10px] flex flex-col gap-5">
|
<div className="grid">
|
||||||
<div className="flex flex-col">
|
<div className="px-5 py-4 overflow-y-auto space-y-[10px] flex flex-col gap-5">
|
||||||
<div className="text-sm font-medium">Name</div>
|
|
||||||
<div className="text-sm font-normal text-zinc-500">{item.name}</div>
|
|
||||||
</div>
|
|
||||||
{item.action ? (
|
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<div className="text-sm font-medium">Action</div>
|
<div className="text-sm font-medium">Name</div>
|
||||||
<div className="text-sm font-normal text-zinc-500">
|
<div className="text-sm font-normal text-zinc-500">
|
||||||
{item.action}
|
{item.name}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
{item.action ? (
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<div className="text-sm font-medium">Model</div>
|
<div className="text-sm font-medium">Action</div>
|
||||||
<div className="text-sm font-normal text-zinc-500">
|
|
||||||
{item.model}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{item.config ? (
|
|
||||||
<div className="flex flex-col border rounded p-3">
|
|
||||||
<div className="text-sm font-medium">Config</div>
|
|
||||||
{Object.entries(item.config).map(([key, value], index) => (
|
|
||||||
<div key={key} className="flex flex-col">
|
|
||||||
{index !== 0 && <Separator />}
|
|
||||||
<span className="text-sm font-normal">{key}</span>
|
|
||||||
<span className="text-sm font-normal text-zinc-500">
|
|
||||||
{value?.toString()}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
<div className="px-5 py-4 overflow-y-auto space-y-[10px] flex flex-col">
|
|
||||||
<div className="text-sm font-medium">Messages</div>
|
|
||||||
{messages.map((message, index) => (
|
|
||||||
<div key={index} className="flex flex-col gap-3">
|
|
||||||
{index !== 0 && <Separator />}
|
|
||||||
<div>
|
|
||||||
<div className="text-sm font-normal">Role</div>
|
|
||||||
<div className="text-sm font-normal text-zinc-500">
|
<div className="text-sm font-normal text-zinc-500">
|
||||||
{message.role}
|
{item.action}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
) : null}
|
||||||
{message.params ? (
|
<div className="flex flex-col">
|
||||||
<div>
|
<div className="text-sm font-medium">Model</div>
|
||||||
<div className="text-sm font-medium">Params</div>
|
<div className="text-sm font-normal text-zinc-500">
|
||||||
{Object.entries(message.params).map(([key, value], index) => (
|
{item.model}
|
||||||
<div key={key} className="flex flex-col">
|
</div>
|
||||||
{index !== 0 && <Separator />}
|
|
||||||
<span className="text-sm font-normal">{key}</span>
|
|
||||||
<span className="text-sm font-normal text-zinc-500">
|
|
||||||
{value.toString()}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
<div className="text-sm font-normal">Content</div>
|
|
||||||
<Textarea
|
|
||||||
className=" min-h-48"
|
|
||||||
value={message.content}
|
|
||||||
onChange={e => handleChange(e, index)}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
{item.config ? (
|
||||||
|
<div className="flex flex-col border rounded p-3">
|
||||||
|
<div className="text-sm font-medium">Config</div>
|
||||||
|
{Object.entries(item.config).map(([key, value], index) => (
|
||||||
|
<div key={key} className="flex flex-col">
|
||||||
|
{index !== 0 && <Separator />}
|
||||||
|
<span className="text-sm font-normal">{key}</span>
|
||||||
|
<span className="text-sm font-normal text-zinc-500">
|
||||||
|
{value?.toString()}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
<div className="px-5 py-4 overflow-y-auto space-y-[10px] flex flex-col">
|
||||||
|
<div className="text-sm font-medium">Messages</div>
|
||||||
|
{messages.map((message, index) => (
|
||||||
|
<div key={index} className="flex flex-col gap-3">
|
||||||
|
{index !== 0 && <Separator />}
|
||||||
|
<div>
|
||||||
|
<div className="text-sm font-normal">Role</div>
|
||||||
|
<div className="text-sm font-normal text-zinc-500">
|
||||||
|
{message.role}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{message.params ? (
|
||||||
|
<div>
|
||||||
|
<div className="text-sm font-medium">Params</div>
|
||||||
|
{Object.entries(message.params).map(
|
||||||
|
([key, value], index) => (
|
||||||
|
<div key={key} className="flex flex-col">
|
||||||
|
{index !== 0 && <Separator />}
|
||||||
|
<span className="text-sm font-normal">{key}</span>
|
||||||
|
<span
|
||||||
|
className="text-sm font-normal text-zinc-500"
|
||||||
|
style={{ overflowWrap: 'break-word' }}
|
||||||
|
>
|
||||||
|
{value.toString()}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
<div className="text-sm font-normal">Content</div>
|
||||||
|
<Textarea
|
||||||
|
className=" min-h-48"
|
||||||
|
value={message.content}
|
||||||
|
onChange={e => handleChange(e, index)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,14 +4,7 @@ import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
|
|||||||
|
|
||||||
import { Prompts } from './prompts';
|
import { Prompts } from './prompts';
|
||||||
|
|
||||||
export function Ai() {
|
function AiPage() {
|
||||||
return null;
|
|
||||||
|
|
||||||
// hide ai config in admin until it's ready
|
|
||||||
// return <AiPage />;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function AiPage() {
|
|
||||||
return (
|
return (
|
||||||
<div className=" h-screen flex-1 flex-col flex">
|
<div className=" h-screen flex-1 flex-col flex">
|
||||||
<div className="flex items-center justify-between px-6 py-3 my-[2px] max-md:ml-9 max-md:mt-[2px]">
|
<div className="flex items-center justify-between px-6 py-3 my-[2px] max-md:ml-9 max-md:mt-[2px]">
|
||||||
@@ -38,4 +31,5 @@ export function AiPage() {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
export { Ai as Component };
|
|
||||||
|
export { AiPage as Component };
|
||||||
|
|||||||
@@ -54,14 +54,16 @@ export function Prompts() {
|
|||||||
export const PromptRow = ({ item, index }: { item: Prompt; index: number }) => {
|
export const PromptRow = ({ item, index }: { item: Prompt; index: number }) => {
|
||||||
const { setRightPanelContent, openPanel, isOpen } = useRightPanel();
|
const { setRightPanelContent, openPanel, isOpen } = useRightPanel();
|
||||||
const [dialogOpen, setDialogOpen] = useState(false);
|
const [dialogOpen, setDialogOpen] = useState(false);
|
||||||
|
const [canSave, setCanSave] = useState(false);
|
||||||
|
|
||||||
const handleDiscardChangesCancel = useCallback(() => {
|
const handleDiscardChangesCancel = useCallback(() => {
|
||||||
setDialogOpen(false);
|
setDialogOpen(false);
|
||||||
|
setCanSave(false);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleConfirm = useCallback(
|
const handleConfirm = useCallback(
|
||||||
(item: Prompt) => {
|
(item: Prompt) => {
|
||||||
setRightPanelContent(<EditPrompt item={item} />);
|
setRightPanelContent(<EditPrompt item={item} setCanSave={setCanSave} />);
|
||||||
if (dialogOpen) {
|
if (dialogOpen) {
|
||||||
handleDiscardChangesCancel();
|
handleDiscardChangesCancel();
|
||||||
}
|
}
|
||||||
@@ -81,13 +83,13 @@ export const PromptRow = ({ item, index }: { item: Prompt; index: number }) => {
|
|||||||
|
|
||||||
const handleEdit = useCallback(
|
const handleEdit = useCallback(
|
||||||
(item: Prompt) => {
|
(item: Prompt) => {
|
||||||
if (isOpen) {
|
if (isOpen && canSave) {
|
||||||
setDialogOpen(true);
|
setDialogOpen(true);
|
||||||
} else {
|
} else {
|
||||||
handleConfirm(item);
|
handleConfirm(item);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[handleConfirm, isOpen]
|
[canSave, handleConfirm, isOpen]
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -7,7 +7,12 @@ import {
|
|||||||
import { buttonVariants } from '@affine/admin/components/ui/button';
|
import { buttonVariants } from '@affine/admin/components/ui/button';
|
||||||
import { cn } from '@affine/admin/utils';
|
import { cn } from '@affine/admin/utils';
|
||||||
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
|
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
|
||||||
import { ClipboardListIcon, SettingsIcon, UsersIcon } from 'lucide-react';
|
import {
|
||||||
|
ClipboardListIcon,
|
||||||
|
CpuIcon,
|
||||||
|
SettingsIcon,
|
||||||
|
UsersIcon,
|
||||||
|
} from 'lucide-react';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
@@ -56,8 +61,7 @@ export function Nav() {
|
|||||||
<UsersIcon className="mr-2 h-4 w-4" />
|
<UsersIcon className="mr-2 h-4 w-4" />
|
||||||
Accounts
|
Accounts
|
||||||
</Link>
|
</Link>
|
||||||
{/* hide ai config in admin until it's ready */}
|
<Link
|
||||||
{/* <Link
|
|
||||||
to={'/admin/ai'}
|
to={'/admin/ai'}
|
||||||
className={cn(
|
className={cn(
|
||||||
buttonVariants({
|
buttonVariants({
|
||||||
@@ -72,7 +76,7 @@ export function Nav() {
|
|||||||
>
|
>
|
||||||
<CpuIcon className="mr-2 h-4 w-4" />
|
<CpuIcon className="mr-2 h-4 w-4" />
|
||||||
AI
|
AI
|
||||||
</Link> */}
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
to={'/admin/config'}
|
to={'/admin/config'}
|
||||||
className={cn(
|
className={cn(
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export const promptKeys = [
|
|||||||
'debug:action:fal-upscaler',
|
'debug:action:fal-upscaler',
|
||||||
'debug:action:fal-remove-bg',
|
'debug:action:fal-remove-bg',
|
||||||
'debug:action:fal-face-to-sticker',
|
'debug:action:fal-face-to-sticker',
|
||||||
'chat:gpt4',
|
'Chat With AFFiNE AI',
|
||||||
'Summary',
|
'Summary',
|
||||||
'Generate a caption',
|
'Generate a caption',
|
||||||
'Summary the webpage',
|
'Summary the webpage',
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export function createChatSession({
|
|||||||
return client.createSession({
|
return client.createSession({
|
||||||
workspaceId,
|
workspaceId,
|
||||||
docId,
|
docId,
|
||||||
promptName: 'chat:gpt4',
|
promptName: 'Chat With AFFiNE AI',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user