feat: add copilot impl (#6230)

fix CLOUD-22
fix CLOUD-24
This commit is contained in:
darkskygit
2024-04-10 11:15:31 +00:00
parent 46a368d7f1
commit e6a576551a
23 changed files with 669 additions and 34 deletions

View File

@@ -5,8 +5,11 @@ import { PrismaClient } from '@prisma/client';
import { ChatPrompt, PromptService } from './prompt';
import {
AvailableModel,
ChatHistory,
ChatMessage,
ChatMessageSchema,
getTokenEncoder,
PromptMessage,
PromptParams,
} from './types';
@@ -27,6 +30,13 @@ export interface ChatSessionState
messages: ChatMessage[];
}
export type ListHistoriesOptions = {
action: boolean | undefined;
limit: number | undefined;
skip: number | undefined;
sessionId: string | undefined;
};
export class ChatSession implements AsyncDisposable {
constructor(
private readonly state: ChatSessionState,
@@ -39,6 +49,13 @@ export class ChatSession implements AsyncDisposable {
}
push(message: ChatMessage) {
if (
this.state.prompt.action &&
this.state.messages.length > 0 &&
message.role === 'user'
) {
throw new Error('Action has been taken, no more messages allowed');
}
this.state.messages.push(message);
}
@@ -167,6 +184,53 @@ export class ChatSessionService {
});
}
async listHistories(
workspaceId: string,
docId: string,
options: ListHistoriesOptions
): Promise<ChatHistory[]> {
return await this.db.aiSession
.findMany({
where: {
workspaceId: workspaceId,
docId: workspaceId === docId ? undefined : docId,
prompt: { action: { not: null } },
id: options.sessionId ? { equals: options.sessionId } : undefined,
},
select: {
id: true,
prompt: true,
messages: {
select: {
role: true,
content: true,
},
orderBy: {
createdAt: 'asc',
},
},
},
take: options.limit,
skip: options.skip,
orderBy: { createdAt: 'desc' },
})
.then(sessions =>
sessions
.map(({ id, prompt, messages }) => {
const ret = ChatMessageSchema.array().safeParse(messages);
if (ret.success) {
const encoder = getTokenEncoder(prompt.model as AvailableModel);
const tokens = ret.data
.map(m => encoder?.encode_ordinary(m.content).length || 0)
.reduce((total, length) => total + length, 0);
return { sessionId: id, tokens, messages: ret.data };
}
return undefined;
})
.filter((v): v is NonNullable<typeof v> => !!v)
);
}
async create(options: ChatSessionOptions): Promise<string> {
const sessionId = randomUUID();
const prompt = await this.prompt.get(options.promptName);