108 lines
2.5 KiB
TypeScript
108 lines
2.5 KiB
TypeScript
import { Num, OpenAPIRoute } from "chanfana";
|
|
import { z } from "zod";
|
|
import { type AppContext } from "../types";
|
|
|
|
export class CondenseTextEndpoint extends OpenAPIRoute {
|
|
schema = {
|
|
tags: ["AltText"],
|
|
summary: "Condense a given text based on a directive",
|
|
security: [
|
|
{
|
|
apiKey: [],
|
|
},
|
|
],
|
|
request: {
|
|
body: {
|
|
content: {
|
|
"application/json": {
|
|
schema: z.object({
|
|
text: z.string({
|
|
description: "The text to be condensed.",
|
|
required_error:
|
|
"Text is required for condensation.",
|
|
}).min(1, "Text cannot be empty."),
|
|
directive: z.string({
|
|
description:
|
|
"Instructions for condensing the text (e.g., 'Summarize this article', 'Extract keywords').",
|
|
required_error:
|
|
"A condensation directive is required.",
|
|
}).min(1, "Directive cannot be empty."),
|
|
targetLength: Num({
|
|
description:
|
|
"The approximate target length for the condensed text (e.g., number of sentences, characters, or words).",
|
|
default: 200,
|
|
}).optional(),
|
|
}),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
responses: {
|
|
"200": {
|
|
description: "Returns the condensed text",
|
|
content: {
|
|
"application/json": {
|
|
schema: z.object({
|
|
success: z.boolean(),
|
|
condensedText: z.string().nullable(),
|
|
error: z.string().optional(),
|
|
}),
|
|
},
|
|
},
|
|
},
|
|
"500": {
|
|
description:
|
|
"Internal Server Error - Issue with Cloud Function or API call",
|
|
content: {
|
|
"application/json": {
|
|
schema: z.object({
|
|
success: z.boolean(),
|
|
message: z.string(),
|
|
}),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
async handle(c: AppContext) {
|
|
const data = await this.getValidatedData<typeof this.schema>();
|
|
const { text, directive, targetLength } = data.body;
|
|
|
|
try {
|
|
const res = await c.var.gemini.models.generateContent({
|
|
// * Original cloud function used "gemini-2.0-flash", but I think the lite version should work fine too.
|
|
model: "gemini-2.0-flash-lite",
|
|
contents: [{
|
|
parts: [
|
|
{ text: directive },
|
|
{ text: text },
|
|
],
|
|
}],
|
|
config: {
|
|
temperature: 0.2,
|
|
maxOutputTokens: 1024,
|
|
},
|
|
});
|
|
|
|
const condensedText = res.candidates?.[0]?.content?.parts?.[0]
|
|
?.text;
|
|
if (!condensedText) {
|
|
return {
|
|
success: false,
|
|
error: "Failed to condense text.",
|
|
};
|
|
}
|
|
|
|
return {
|
|
success: true,
|
|
altText: condensedText,
|
|
};
|
|
} catch (e) {
|
|
return {
|
|
success: false,
|
|
message: e,
|
|
};
|
|
}
|
|
}
|
|
}
|