generated from nhcarrigan/template
feat: include cost in announcements
This commit is contained in:
@@ -10,8 +10,8 @@ import {
|
|||||||
announcementJsonSchema,
|
announcementJsonSchema,
|
||||||
announcementSystemMessage,
|
announcementSystemMessage,
|
||||||
} from "../config/announcements.js";
|
} from "../config/announcements.js";
|
||||||
import type { AnnouncementResponse }
|
import { getAiCost } from "../utils/getAiCost.js";
|
||||||
from "../interfaces/announcementResponse.js";
|
import type { AnnouncementResponse } from "../interfaces/announcementResponse.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates announcements for all platforms using AI.
|
* Generates announcements for all platforms using AI.
|
||||||
@@ -20,7 +20,7 @@ import type { AnnouncementResponse }
|
|||||||
*/
|
*/
|
||||||
export const generateAnnouncements = async(
|
export const generateAnnouncements = async(
|
||||||
content: string,
|
content: string,
|
||||||
): Promise<AnnouncementResponse | null> => {
|
): Promise<{ cost: string; response: AnnouncementResponse } | null> => {
|
||||||
if (process.env.ANTHROPIC_KEY === undefined) {
|
if (process.env.ANTHROPIC_KEY === undefined) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -46,12 +46,17 @@ export const generateAnnouncements = async(
|
|||||||
},
|
},
|
||||||
system: announcementSystemMessage,
|
system: announcementSystemMessage,
|
||||||
});
|
});
|
||||||
const text = response.content.find((m) => {
|
const { usage, content: responseContent } = response;
|
||||||
|
const text = responseContent.find((m) => {
|
||||||
return m.type === "text";
|
return m.type === "text";
|
||||||
});
|
});
|
||||||
if (text?.text === undefined) {
|
if (text?.text === undefined) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Being lazy.
|
|
||||||
return JSON.parse(text.text) as AnnouncementResponse;
|
return {
|
||||||
|
cost: getAiCost(usage),
|
||||||
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Being lazy.
|
||||||
|
response: JSON.parse(text.text) as AnnouncementResponse,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ export const announcementRoutes: FastifyPluginAsync = async(server) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const { bluesky, discord, reddit, twitter } = announcement;
|
const { bluesky, discord, reddit, twitter } = announcement.response;
|
||||||
const { title: discordTitle, content: discordContent } = discord;
|
const { title: discordTitle, content: discordContent } = discord;
|
||||||
const { title: redditTitle, content: redditContent } = reddit;
|
const { title: redditTitle, content: redditContent } = reddit;
|
||||||
|
|
||||||
@@ -111,8 +111,9 @@ export const announcementRoutes: FastifyPluginAsync = async(server) => {
|
|||||||
const blueskyPost = await announceOnBluesky(bluesky);
|
const blueskyPost = await announceOnBluesky(bluesky);
|
||||||
const twitterPost = await announceOnTwitter(twitter);
|
const twitterPost = await announceOnTwitter(twitter);
|
||||||
return await reply.status(201).send({
|
return await reply.status(201).send({
|
||||||
|
cost: announcement.cost,
|
||||||
message: `Announcement processed. Discord: ${discordPost}, Reddit: ${redditPost}, Bluesky: ${blueskyPost}, Twitter: ${twitterPost}`,
|
message: `Announcement processed. Discord: ${discordPost}, Reddit: ${redditPost}, Bluesky: ${blueskyPost}, Twitter: ${twitterPost}`,
|
||||||
rawPost: announcement,
|
rawPost: announcement.response,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* @copyright nhcarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { BetaUsage } from "@anthropic-ai/sdk/resources/beta.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the cost of an AI response.
|
||||||
|
* @param usage - The usage payload from Anthropic.
|
||||||
|
* @returns A description of the cost of the AI response.
|
||||||
|
*/
|
||||||
|
export const getAiCost = (usage: BetaUsage): string => {
|
||||||
|
const { input_tokens: inputTokens, output_tokens: outputTokens } = usage;
|
||||||
|
const costPerInputToken = 5 / 1_000_000;
|
||||||
|
const costPerOutputToken = 25 / 1_000_000;
|
||||||
|
const inputCost = inputTokens * costPerInputToken;
|
||||||
|
const outputCost = outputTokens * costPerOutputToken;
|
||||||
|
const totalCost = inputCost + outputCost;
|
||||||
|
return `Input cost: ${inputCost.toLocaleString("en-GB", {
|
||||||
|
currency: "USD",
|
||||||
|
style: "currency",
|
||||||
|
})} Output cost: ${outputCost.toLocaleString("en-GB", {
|
||||||
|
currency: "USD",
|
||||||
|
style: "currency",
|
||||||
|
})} Total cost: ${totalCost.toLocaleString("en-GB", {
|
||||||
|
currency: "USD",
|
||||||
|
style: "currency",
|
||||||
|
})}`;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user