feat: add copilot metrics (#8455)

fix CLOUD-73
This commit is contained in:
darkskygit
2024-10-18 03:30:02 +00:00
parent 4122cec096
commit fa554b1054
14 changed files with 198 additions and 112 deletions

View File

@@ -30,10 +30,12 @@ import {
import { CurrentUser, Public } from '../../core/auth';
import {
BlobNotFound,
CallMetric,
Config,
CopilotFailedToGenerateText,
CopilotSessionNotFound,
mapSseError,
metrics,
NoCopilotProviderAvailable,
UnsplashIsNotConfigured,
} from '../../fundamentals';
@@ -178,6 +180,7 @@ export class CopilotController {
}
@Get('/chat/:sessionId')
@CallMetric('ai', 'chat', { timer: true })
async chat(
@CurrentUser() user: CurrentUser,
@Req() req: Request,
@@ -185,6 +188,7 @@ export class CopilotController {
@Query() params: Record<string, string | string[]>
): Promise<string> {
const { messageId } = this.prepareParams(params);
const provider = await this.chooseTextProvider(
user.id,
sessionId,
@@ -192,8 +196,8 @@ export class CopilotController {
);
const session = await this.appendSessionMessage(sessionId, messageId);
try {
metrics.ai.counter('chat_calls').add(1, { model: session.model });
const content = await provider.generateText(
session.finish(params),
session.model,
@@ -213,27 +217,30 @@ export class CopilotController {
return content;
} catch (e: any) {
metrics.ai.counter('chat_errors').add(1, { model: session.model });
throw new CopilotFailedToGenerateText(e.message);
}
}
@Sse('/chat/:sessionId/stream')
@CallMetric('ai', 'chat_stream', { timer: true })
async chatStream(
@CurrentUser() user: CurrentUser,
@Req() req: Request,
@Param('sessionId') sessionId: string,
@Query() params: Record<string, string>
): Promise<Observable<ChatEvent>> {
const { messageId } = this.prepareParams(params);
const provider = await this.chooseTextProvider(
user.id,
sessionId,
messageId
);
const session = await this.appendSessionMessage(sessionId, messageId);
try {
const { messageId } = this.prepareParams(params);
const provider = await this.chooseTextProvider(
user.id,
sessionId,
messageId
);
const session = await this.appendSessionMessage(sessionId, messageId);
metrics.ai.counter('chat_stream_calls').add(1, { model: session.model });
const source$ = from(
provider.generateTextStream(session.finish(params), session.model, {
...session.config.promptConfig,
@@ -262,25 +269,34 @@ export class CopilotController {
)
)
),
catchError(mapSseError)
catchError(e => {
metrics.ai
.counter('chat_stream_errors')
.add(1, { model: session.model });
return mapSseError(e);
})
);
return this.mergePingStream(messageId, source$);
} catch (err) {
metrics.ai.counter('chat_stream_errors').add(1, { model: session.model });
return mapSseError(err);
}
}
@Sse('/chat/:sessionId/workflow')
@CallMetric('ai', 'chat_workflow', { timer: true })
async chatWorkflow(
@CurrentUser() user: CurrentUser,
@Req() req: Request,
@Param('sessionId') sessionId: string,
@Query() params: Record<string, string>
): Promise<Observable<ChatEvent>> {
const { messageId } = this.prepareParams(params);
const session = await this.appendSessionMessage(sessionId, messageId);
try {
const { messageId } = this.prepareParams(params);
const session = await this.appendSessionMessage(sessionId, messageId);
metrics.ai.counter('workflow_calls').add(1, { model: session.model });
const latestMessage = session.stashMessages.findLast(
m => m.role === 'user'
);
@@ -347,41 +363,51 @@ export class CopilotController {
)
)
),
catchError(mapSseError)
catchError(e => {
metrics.ai
.counter('workflow_errors')
.add(1, { model: session.model });
return mapSseError(e);
})
);
return this.mergePingStream(messageId, source$);
} catch (err) {
metrics.ai.counter('workflow_errors').add(1, { model: session.model });
return mapSseError(err);
}
}
@Sse('/chat/:sessionId/images')
@CallMetric('ai', 'chat_images', { timer: true })
async chatImagesStream(
@CurrentUser() user: CurrentUser,
@Req() req: Request,
@Param('sessionId') sessionId: string,
@Query() params: Record<string, string>
): Promise<Observable<ChatEvent>> {
const { messageId } = this.prepareParams(params);
const { model, hasAttachment } = await this.checkRequest(
user.id,
sessionId,
messageId
);
const provider = await this.provider.getProviderByCapability(
hasAttachment
? CopilotCapability.ImageToImage
: CopilotCapability.TextToImage,
model
);
if (!provider) {
throw new NoCopilotProviderAvailable();
}
const session = await this.appendSessionMessage(sessionId, messageId);
try {
const { messageId } = this.prepareParams(params);
const { model, hasAttachment } = await this.checkRequest(
user.id,
sessionId,
messageId
);
const provider = await this.provider.getProviderByCapability(
hasAttachment
? CopilotCapability.ImageToImage
: CopilotCapability.TextToImage,
model
);
if (!provider) {
throw new NoCopilotProviderAvailable();
}
const session = await this.appendSessionMessage(sessionId, messageId);
metrics.ai
.counter('images_stream_calls')
.add(1, { model: session.model });
const handleRemoteLink = this.storage.handleRemoteLink.bind(
this.storage,
user.id,
@@ -423,15 +449,24 @@ export class CopilotController {
)
)
),
catchError(mapSseError)
catchError(e => {
metrics.ai
.counter('images_stream_errors')
.add(1, { model: session.model });
return mapSseError(e);
})
);
return this.mergePingStream(messageId, source$);
} catch (err) {
metrics.ai
.counter('images_stream_errors')
.add(1, { model: session.model });
return mapSseError(err);
}
}
@CallMetric('ai', 'unsplash')
@Get('/unsplash/photos')
async unsplashPhotos(
@Req() req: Request,