Vercel ai gateway (#7)
* feat: use vercel ai gateway * chore: update UI
This commit is contained in:
54
utils/aiGatewayClient.ts
Normal file
54
utils/aiGatewayClient.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { generateText } from 'ai';
|
||||
|
||||
interface AiGatewayResponse {
|
||||
text: string;
|
||||
tokensUsed: number;
|
||||
}
|
||||
|
||||
export async function queryAiGateway(
|
||||
text: string,
|
||||
model: string
|
||||
): Promise<AiGatewayResponse> {
|
||||
const requestId = Math.random().toString(36).substring(7);
|
||||
const startTime = Date.now();
|
||||
|
||||
console.info(`[AI-${requestId}] Starting Vercel Gateway AI request`, {
|
||||
promptLength: text.length,
|
||||
model,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
try {
|
||||
const response = await generateText({
|
||||
model,
|
||||
prompt: text
|
||||
});
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
const tokensUsed = response.usage?.totalTokens || 0;
|
||||
|
||||
console.info(
|
||||
`[AI-${requestId}] Vercel Gateway AI response received in ${duration}ms`,
|
||||
{
|
||||
responseLength: response.text.length,
|
||||
tokensUsed,
|
||||
usage: response.usage
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
text: response.text,
|
||||
tokensUsed
|
||||
};
|
||||
} catch (error) {
|
||||
const duration = Date.now() - startTime;
|
||||
console.error(
|
||||
`[AI-${requestId}] Vercel Gateway AI error after ${duration}ms:`,
|
||||
{
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
promptLength: text.length
|
||||
}
|
||||
);
|
||||
throw new Error(`Vercel Gateway AI error: ${JSON.stringify(error)}.`);
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
import Anthropic from '@anthropic-ai/sdk';
|
||||
|
||||
interface AnthropicResponse {
|
||||
text: string;
|
||||
tokensUsed: number;
|
||||
}
|
||||
|
||||
export async function getMessage(text: string): Promise<AnthropicResponse> {
|
||||
const anthropic = new Anthropic({
|
||||
apiKey: process.env.ANTHROPIC_API_KEY
|
||||
});
|
||||
|
||||
console.info('Anthropic request with text: ', text);
|
||||
|
||||
const response = await anthropic.messages.create({
|
||||
model: 'claude-3-5-sonnet-20241022',
|
||||
max_tokens: 2048,
|
||||
messages: [{ role: 'user', content: text }]
|
||||
});
|
||||
|
||||
console.info('Anthropic response: ', response);
|
||||
|
||||
try {
|
||||
const data = response.content as [{ type: string; text: string }];
|
||||
|
||||
const tokensUsed =
|
||||
(response.usage?.input_tokens || 0) +
|
||||
(response.usage?.output_tokens || 0);
|
||||
|
||||
console.info('Token usage:', {
|
||||
input_tokens: response.usage?.input_tokens,
|
||||
output_tokens: response.usage?.output_tokens,
|
||||
total: tokensUsed
|
||||
});
|
||||
|
||||
return {
|
||||
text: data[0].text,
|
||||
tokensUsed
|
||||
};
|
||||
} catch (error) {
|
||||
throw new Error(`Anthropic client error: ${JSON.stringify(error)}.`);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,27 @@
|
||||
import { getMessage } from '@utils/anthropicClient';
|
||||
import { queryAiGateway } from '@utils/aiGatewayClient';
|
||||
import { ShortcutsResponse } from '../types';
|
||||
import { dbOperations } from '@utils/db';
|
||||
|
||||
export async function anthropicCommand(
|
||||
parameters: Record<string, string> | undefined
|
||||
): Promise<ShortcutsResponse> {
|
||||
const commandId = Math.random().toString(36).substring(7);
|
||||
const startTime = Date.now();
|
||||
|
||||
let question = '';
|
||||
let response = '';
|
||||
let success = false;
|
||||
let errorMessage: string | undefined;
|
||||
let tokensUsed: number | undefined;
|
||||
|
||||
console.info(`[CMD-${commandId}] Anthropic command started`, {
|
||||
hasParameters: !!parameters,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
try {
|
||||
if (!parameters || !parameters['question']) {
|
||||
console.warn(`[CMD-${commandId}] Missing question parameter`);
|
||||
errorMessage = 'Need to provide a question.';
|
||||
return {
|
||||
success: false,
|
||||
@@ -21,16 +30,35 @@ export async function anthropicCommand(
|
||||
}
|
||||
|
||||
question = parameters['question'];
|
||||
console.info(`[CMD-${commandId}] Processing question`, {
|
||||
questionLength: question.length,
|
||||
question:
|
||||
question.substring(0, 100) + (question.length > 100 ? '...' : '')
|
||||
});
|
||||
|
||||
const prompt =
|
||||
'I want to know ' +
|
||||
question +
|
||||
'. Structure the response in a manner suitable for spoken communication.';
|
||||
|
||||
const anthropicResponse = await getMessage(prompt);
|
||||
const anthropicResponse = await queryAiGateway(
|
||||
prompt,
|
||||
'anthropic/claude-sonnet-4.5'
|
||||
);
|
||||
response = anthropicResponse.text;
|
||||
tokensUsed = anthropicResponse.tokensUsed;
|
||||
success = true;
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
console.info(
|
||||
`[CMD-${commandId}] Anthropic command completed in ${duration}ms`,
|
||||
{
|
||||
responseLength: response.length,
|
||||
tokensUsed,
|
||||
success: true
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: response,
|
||||
@@ -39,7 +67,11 @@ export async function anthropicCommand(
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Anthropic command error:', error);
|
||||
const duration = Date.now() - startTime;
|
||||
console.error(
|
||||
`[CMD-${commandId}] Anthropic command failed after ${duration}ms:`,
|
||||
error
|
||||
);
|
||||
success = false;
|
||||
errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||
response = 'Sorry. There was a problem with Anthropic.';
|
||||
@@ -51,6 +83,7 @@ export async function anthropicCommand(
|
||||
} finally {
|
||||
if (question) {
|
||||
try {
|
||||
console.info(`[CMD-${commandId}] Saving query to database`);
|
||||
await dbOperations.saveAnthropicQuery({
|
||||
question,
|
||||
response,
|
||||
@@ -58,8 +91,12 @@ export async function anthropicCommand(
|
||||
errorMessage,
|
||||
tokensUsed
|
||||
});
|
||||
console.info(`[CMD-${commandId}] Query saved to database successfully`);
|
||||
} catch (error) {
|
||||
console.error('Failed to log query to database:', error);
|
||||
console.error(
|
||||
`[CMD-${commandId}] Failed to log query to database:`,
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { z } from 'zod';
|
||||
|
||||
export const RequestSchema = z.object({
|
||||
command: z.string(),
|
||||
parameters: z.record(z.string()).optional(),
|
||||
parameters: z.record(z.string(), z.string()).optional(),
|
||||
apiKey: z.string()
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user