From 529d754e0a29c7a4ddfa04199dbbd0e7c5a3d33b Mon Sep 17 00:00:00 2001 From: babayaga Date: Sun, 23 Mar 2025 01:06:53 +0100 Subject: [PATCH] kbot lazy --- .kbot/params.json | 4 +- src/base/kbot.ts | 73 ++++++++++++- src/components/howtos/Detail2.astro | 163 +++++++++++++++++++--------- src/model/howto.ts | 8 +- 4 files changed, 189 insertions(+), 59 deletions(-) diff --git a/.kbot/params.json b/.kbot/params.json index 397098a..e842209 100644 --- a/.kbot/params.json +++ b/.kbot/params.json @@ -1,9 +1,9 @@ { - "model": "gpt-4o-mini", + "model": "google/gemini-exp-1206:free", "messages": [ { "role": "user", - "content": "use a formal tone\nspell check the text, fix any errors\nremove emojis\nremove personal preferences or biases\nshorten text if possible but preserve personality\nremove references to preciousplastic, bazar and Discord\nremove any brain/green washing as well suggestions not related to the craft\nContext: howto tutorials, for makers\ndont comment just return as Markdown : An experience review designing a broom hanger mold: These are some steps to design a mold for the injection machine." + "content": "Return a list of useful references (only with links), as Markdown, grouped : Articles, Books, Papers, Youtube, Opensource Designs, ... Dont comment ! : Injection mold design, broom hanger mold, plastic injection, mold making, CAD mold design, DIY injection mold, injection molding process, mold design criteria, plastic product design, custom mold design\n" }, { "role": "user", diff --git a/src/base/kbot.ts b/src/base/kbot.ts index 6e6c41a..68e271b 100644 --- a/src/base/kbot.ts +++ b/src/base/kbot.ts @@ -2,6 +2,7 @@ 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 { createMarkdownComponent } from "@/base/index.js"; +import { filters } from "@/model/howto.js"; export interface Props extends IKBotTask { language?: string; @@ -12,6 +13,10 @@ export interface Props extends IKBotTask { renderer?: string; } +///////////////////////////////////////////////////////////// +// +// Templates + export const template_simple = () => { return { router: "openai", @@ -21,6 +26,27 @@ export const template_simple = () => { }; } +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", @@ -36,6 +62,11 @@ export const template_research = () => { mode: "completion", } } + +///////////////////////////////////////////////////////////// +// +// Filters + export enum ToneFlags { None = 0, Formal = 1, @@ -128,7 +159,7 @@ export function templateLanguage( model: "gpt-4o-mini", preferences: "none", mode: "completion", - prompt, + prompt, filters: "code" } } @@ -137,7 +168,9 @@ export const templates = { simple: template_simple, code_simple: template_code_simple, research: template_research, - howto: templateLanguage + howto: templateLanguage, + keywords: keywords_simple, + references: references_simple } export const filter = async (content: string, tpl: string = 'howto', opts: any = {}) => { @@ -153,4 +186,40 @@ export const filter = async (content: string, tpl: string = 'howto', opts: any = 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; } \ No newline at end of file diff --git a/src/components/howtos/Detail2.astro b/src/components/howtos/Detail2.astro index 9f8ad55..92db43f 100644 --- a/src/components/howtos/Detail2.astro +++ b/src/components/howtos/Detail2.astro @@ -1,7 +1,7 @@ --- import fs from "fs"; import path from "path"; -import { decode } from 'html-entities' +import { decode } from "html-entities"; import { IHowto, asset_local_rel } from "@/model/howto.js"; import { Img } from "imagetools/components"; import { i18n as Translate } from "@polymech/astro-base"; @@ -12,9 +12,10 @@ import { files, forward_slash } from "@polymech/commons"; import pMap from "p-map"; import { sync as exists } from "@polymech/fs/exists"; import { sync as read } from "@polymech/fs/read"; -import { createMarkdownComponent } from "@/base/index.js"; +import { createHTMLComponent, createMarkdownComponent } from "@/base/index.js"; import { translate } from "@/base/i18n.js"; import { applyFilters, shortenUrl } from "@/model/howto.js"; +import { extract, references } from "@/base/kbot.js"; import { HOWTO_FILES_WEB, HOWTO_FILES_ABS, @@ -28,7 +29,7 @@ const { howto } = Astro.props; const howto_abs = HOWTO_FILES_ABS(howto.slug); const howto_resources_default = `# Resources`; const howto_resources_path = path.join(howto_abs, "resources.md"); -const howto_resources = exists(howto_resources_path) +let howto_resources = exists(howto_resources_path) ? read(howto_resources_path, "string") || howto_resources_default : howto_resources_default; @@ -36,15 +37,19 @@ let model_files: any = [...files(howto_abs, "**/**/*.(step|stp)")]; model_files = model_files.map((f) => forward_slash(`${howto.slug}/${path.relative(path.resolve(howto_abs), f)}`), ); -const content = async (str: string) =>{ +const content = async (str: string) => { const ret = await translate( await applyFilters(str), I18N_SOURCE_LANGUAGE, Astro.currentLocale, ); - return ret -} -const component = async (str: string) => await createMarkdownComponent(await content(str)) + return ret; +}; +const component = async (str: string) => + await createMarkdownComponent(await content(str)); + +const componentHTML = async (str: string) => + await createHTMLComponent(await content(str)); const stepsWithFilteredMarkdown = await pMap( howto.steps, @@ -56,16 +61,21 @@ const stepsWithFilteredMarkdown = await pMap( ); const Description = component(howto.description); -const Resources = component(howto_resources); - const authorGeo = howto?.user?.geo || { countryName: "Unknown", data: { urls: [] }, }; const authorLinks = (howto?.user?.data.urls || []).filter( - (l) => !l.url.includes("one_army") && !l.url.includes("bazar") + (l) => !l.url.includes("one_army") && !l.url.includes("bazar"), ); +////////////////////////////////////////////////////////////// +// Add references from the extracted keywords +const contentAll = `${howto.title} \n Description : ${howto.description} \n Steps: ${howto.steps.map((s) => s.text).join("\n")} \n`; +const keywords = await extract(contentAll) as string; +const references_extra = await references(keywords); +howto_resources = `${howto_resources}\n${references_extra}`; +const Resources = component(howto_resources); --- @@ -75,7 +85,7 @@ const authorLinks = (howto?.user?.data.urls || []).filter(

{howto.title}

- +
{ howto.tags.map((tag) => ( @@ -105,25 +115,44 @@ const authorLinks = (howto?.user?.data.urls || []).filter( Creator:{howto._createdBy}
  • - Country:{authorGeo.countryName} + Country:{ + authorGeo.countryName + }
  • Email: - link.name.toLowerCase()==="email")?.url.replace("mailto:","")}`}> - {authorLinks.find((link)=>link.name.toLowerCase()==="email")?.url.replace("mailto:","")} + link.name.toLowerCase() === "email")?.url.replace("mailto:", "")}`} + > + { + authorLinks + .find((link) => link.name.toLowerCase() === "email") + ?.url.replace("mailto:", "") + }
  • { - authorLinks.filter((l)=>l.name.toLowerCase()!=="email").map((link)=>( -
  • - {link.name}: - - {shortenUrl(link.url)} - -
  • - )) + authorLinks + .filter((l) => l.name.toLowerCase() !== "email") + .map((link) => ( +
  • + {link.name}: + + {shortenUrl(link.url)} + +
  • + )) } -
  • Downloads:{howto.total_downloads}
  • +
  • + Downloads:{ + howto.total_downloads + } +
  • @@ -131,41 +160,64 @@ const authorLinks = (howto?.user?.data.urls || []).filter(
    - Browse Files + Browse Files
    -

    Table of Contents

    +

    + Table of Contents +

    -

    Steps

    +

    + Steps +

      - {stepsWithFilteredMarkdown.map((step, idx) => ( -
    1. -
      - - {idx + 1} - -

      - {step.title} -

      -
      -
      - -
      - {step.images?.length > 0 && } -
    2. - ))} + { + stepsWithFilteredMarkdown.map((step, idx) => ( +
    3. +
      + + {idx + 1} + +

      + + {step.title} + +

      +
      +
      + +
      + {step.images?.length > 0 && } +
    4. + )) + }
    @@ -173,9 +225,16 @@ const authorLinks = (howto?.user?.data.urls || []).filter(
    - Created on: {new Date(howto._created).toLocaleDateString()} - {howto.votedUsefulBy.length} people found this useful + Created on: { + new Date(howto._created).toLocaleDateString() + } + {howto.votedUsefulBy.length} + people found this useful
    - \ No newline at end of file + diff --git a/src/model/howto.ts b/src/model/howto.ts index d4658d1..8cc2fce 100644 --- a/src/model/howto.ts +++ b/src/model/howto.ts @@ -78,6 +78,7 @@ export const asset_local_rel = async (item: IHowto, asset: Image) => { } return default_image().src } + export const howtos = async () => { const src = HOWTO_MIGRATION() const data = read(src, 'json') as any; @@ -99,11 +100,9 @@ export const howtos = async () => { label: 'uncategorized' } }) - howtos = howtos.filter((h) => { return h.steps.length > 0 && !blacklist.includes(h._createdBy); }); - return howtos } @@ -194,9 +193,11 @@ export function loader(): Loader { load }; } + //////////////////////////////// // -// Utils +// Filters + const urlBlacklist = ["thenounproject.com", "preciousplastic.com"]; const bannedWords = ["wizard", "magic2"]; const wordReplaceMap: Record = { @@ -252,6 +253,7 @@ export async function applyFilters(text: string): Promise { } return filtered; } + //////////////////////////////// // // Interfaces - Old