site-library/src/base/kbot.ts
2025-03-23 11:36:45 +01:00

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;
}