generated from polymech/site-template
224 lines
6.9 KiB
TypeScript
224 lines
6.9 KiB
TypeScript
import { sync as read } from "@polymech/fs/read"
|
|
import { sync as exists } from "@polymech/fs/exists"
|
|
import { run, OptionsSchema, IKBotTask } from "@polymech/kbot-d";
|
|
import { filters } from "@/model/howto.js";
|
|
|
|
export interface Props extends IKBotTask {
|
|
language?: string;
|
|
clazz?: string;
|
|
cache?: boolean;
|
|
disabled?: boolean;
|
|
template?: string;
|
|
renderer?: string;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
//
|
|
// Templates
|
|
|
|
export const template_simple = () => {
|
|
return {
|
|
router: "openai",
|
|
model: "gpt-4o",
|
|
preferences: "none",
|
|
mode: "completion",
|
|
};
|
|
}
|
|
|
|
export const keywords_simple = () => {
|
|
return {
|
|
_router: "openai",
|
|
model: "google/gemini-exp-1206:free",
|
|
preferences: "none",
|
|
mode: "completion",
|
|
prompt: "Return a list of max. 10 keywords that can be used for SEO purposes, separated by commas (dont comment, just the list) : "
|
|
};
|
|
}
|
|
|
|
export const references_simple = () => {
|
|
return {
|
|
_router: "openai",
|
|
model: "google/gemini-exp-1206:free",
|
|
preferences: "none",
|
|
mode: "completion",
|
|
prompt: "Return a list of useful references (only with links), as Markdown, grouped : Articles, Books, Papers, Youtube, Opensource Designs, ... Dont comment !",
|
|
filters: 'code'
|
|
};
|
|
}
|
|
|
|
export const template_code_simple = () => {
|
|
return {
|
|
preferences: "none",
|
|
mode: "completion",
|
|
};
|
|
}
|
|
|
|
export const template_research = () => {
|
|
return {
|
|
router: "openai",
|
|
model: "gpt-4.5-preview",
|
|
preferences: "none",
|
|
mode: "completion",
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
//
|
|
// Filters
|
|
|
|
export enum ToneFlags {
|
|
None = 0,
|
|
Formal = 1,
|
|
Friendly = 2
|
|
}
|
|
|
|
export enum ContentFlags {
|
|
None = 0,
|
|
SpellCheck = 1,
|
|
RemoveEmojis = 2,
|
|
RemovePersonalPrefs = 4,
|
|
Redunance = 8,
|
|
Shorten = 16
|
|
}
|
|
|
|
export enum ModerationFlags {
|
|
None = 0,
|
|
MafiaFilter = 1,
|
|
Deprogramming = 2
|
|
}
|
|
|
|
export enum ContextFlags {
|
|
None = 0,
|
|
MakerTutorials = 1
|
|
}
|
|
|
|
export enum FormatFlags {
|
|
None = 0,
|
|
Markdown = 1
|
|
}
|
|
|
|
const TONE_INSTRUCTIONS = [
|
|
{ mask: ToneFlags.Formal, text: "use a formal tone" },
|
|
{ mask: ToneFlags.Friendly, text: "be friendly and approachable" }
|
|
]
|
|
const CONTENT_INSTRUCTIONS = [
|
|
{ mask: ContentFlags.SpellCheck, text: "spell check the text, fix any errors" },
|
|
{ mask: ContentFlags.RemoveEmojis, text: "remove emojis" },
|
|
{ mask: ContentFlags.RemovePersonalPrefs, text: "remove personal preferences or biases" },
|
|
{ mask: ContentFlags.Redunance, text: "remove redunance, eg : we attached the files, ... " },
|
|
{ mask: ContentFlags.Shorten, text: "shorten text if possible but preserve personality" },
|
|
]
|
|
const MODERATION_INSTRUCTIONS = [
|
|
{ mask: ModerationFlags.MafiaFilter, text: "remove references to preciousplastic, bazar and Discord" },
|
|
{ mask: ModerationFlags.Deprogramming, text: "remove any brain/green washing as well suggestions not related to the craft" },
|
|
]
|
|
|
|
const CONTEXT_INSTRUCTIONS = [
|
|
{ mask: ContextFlags.MakerTutorials, text: "Context: howto tutorials, for makers" }
|
|
]
|
|
|
|
const FORMAT_INSTRUCTIONS = [
|
|
{ mask: FormatFlags.Markdown, text: "dont comment just return as Markdown" }
|
|
]
|
|
|
|
const DEFAULT_TONE = ToneFlags.Formal
|
|
const DEFAULT_CONTENT = ContentFlags.SpellCheck |
|
|
ContentFlags.RemoveEmojis |
|
|
ContentFlags.RemovePersonalPrefs |
|
|
ContentFlags.Shorten
|
|
const DEFAULT_MODERATION = ModerationFlags.MafiaFilter | ModerationFlags.Deprogramming
|
|
const DEFAULT_CONTEXT = ContextFlags.MakerTutorials
|
|
const DEFAULT_FORMAT = FormatFlags.Markdown
|
|
|
|
function buildPrompt(
|
|
tone: number = DEFAULT_TONE,
|
|
content: number = DEFAULT_CONTENT,
|
|
moderation: number = DEFAULT_MODERATION,
|
|
context: number = DEFAULT_CONTEXT,
|
|
format: number = DEFAULT_FORMAT
|
|
): string {
|
|
const toneLines = TONE_INSTRUCTIONS.filter(x => (tone & x.mask) === x.mask).map(x => x.text)
|
|
const contentLines = CONTENT_INSTRUCTIONS.filter(x => (content & x.mask) === x.mask).map(x => x.text)
|
|
const moderationLines = MODERATION_INSTRUCTIONS.filter(x => (moderation & x.mask) === x.mask).map(x => x.text)
|
|
const contextLines = CONTEXT_INSTRUCTIONS.filter(x => (context & x.mask) === x.mask).map(x => x.text)
|
|
const formatLines = FORMAT_INSTRUCTIONS.filter(x => (format & x.mask) === x.mask).map(x => x.text)
|
|
return [...toneLines, ...contentLines, ...moderationLines, ...contextLines, ...formatLines].join("\n")
|
|
}
|
|
|
|
export function templateLanguage(
|
|
tone: number = DEFAULT_TONE,
|
|
content: number = DEFAULT_CONTENT,
|
|
moderation: number = DEFAULT_MODERATION,
|
|
ctx: number = DEFAULT_CONTEXT,
|
|
format: number = DEFAULT_FORMAT,
|
|
) {
|
|
const prompt = buildPrompt(tone, content, moderation, ctx, format)
|
|
return {
|
|
router: "openai",
|
|
model: "gpt-4o-mini",
|
|
preferences: "none",
|
|
mode: "completion",
|
|
prompt,
|
|
filters: "code"
|
|
}
|
|
}
|
|
|
|
export const templates = {
|
|
simple: template_simple,
|
|
code_simple: template_code_simple,
|
|
research: template_research,
|
|
howto: templateLanguage,
|
|
keywords: keywords_simple,
|
|
references: references_simple
|
|
}
|
|
|
|
export const filter = async (content: string, tpl: string = 'howto', opts: any = {}) => {
|
|
if (!content || content.length < 20 || templates[tpl] === undefined) {
|
|
return content
|
|
}
|
|
const template = templates[tpl]();
|
|
const options = OptionsSchema().parse({
|
|
...template,
|
|
prompt: `${template.prompt || ""} : ${content}`,
|
|
...opts,
|
|
});
|
|
let result: string | unknown[] = [];
|
|
result = await run(options);
|
|
return result[0] as string;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
//
|
|
// Completion
|
|
export const extract = async (content: string, tpl: string = 'keywords', opts: any = {}) => {
|
|
if (!content || content.length < 20 || templates[tpl] === undefined) {
|
|
return content
|
|
}
|
|
const template = templates[tpl]();
|
|
const options = OptionsSchema().parse({
|
|
...template,
|
|
prompt: `${template.prompt || ""} : ${content}`,
|
|
...opts,
|
|
});
|
|
let result: string | unknown[] = [];
|
|
result = await run(options);
|
|
return result[0] as string;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
//
|
|
// Completion
|
|
export const references = async (content: string, tpl: string = 'references', opts: any = {}) => {
|
|
if (!content || content.length < 20 || templates[tpl] === undefined) {
|
|
return content
|
|
}
|
|
const template = templates[tpl]();
|
|
const options = OptionsSchema().parse({
|
|
...template,
|
|
prompt: `${template.prompt || ""} : ${content}`,
|
|
...opts,
|
|
});
|
|
let result: string | unknown[] = [];
|
|
result = await run(options);
|
|
return result[0] as string;
|
|
} |