llm basics

This commit is contained in:
lovebird 2025-03-26 23:54:44 +01:00
parent bfe361c704
commit a91ee1be3b
10 changed files with 98 additions and 122 deletions

View File

@ -23,7 +23,7 @@
"format": "unix-time"
}
],
"default": "2025-03-26T19:46:20.703Z"
"default": "2025-03-26T22:54:00.163Z"
},
"description": {
"type": "string",

File diff suppressed because one or more lines are too long

View File

@ -1,9 +1,9 @@
{
"model": "google/gemini-exp-1206:free",
"model": "gpt-4o",
"messages": [
{
"role": "user",
"content": "Return a list of max. 10 keywords that can be used for SEO purposes, separated by commas (dont comment, just the list) : : El Tornillo Motor Injection Machine \n Description : This injection machine runs with a motor to save some labor and output more pressure to make more detailed products. \n Steps: Machine design:\nMotor Injection Machine\n\nMachine size:\nHeigth: 195CM; Wide: 50CM; Large: 50CM\n\nMachine cost:\nIn Colombia, Bill Of Material = COP$4,700,000\n\nWhat makes your machine different to others: \nThis machine has a motor that will apply the pressure (versus a hand powered lever on older versions). It can be considered an upgrade to Precious Plastic Basic Injection Machine, available on the academy.\n\nCompatible with: \nThis machine is suitable for injection moulds.\n\nType of plastic: \nPP, HDPE, LDPE, PS\nTo build this machine, you will need:\n\n-- Turning (machining on a lathe)\n-- Milling (machining on a mill)\n-- General metalworking (cutting, drilling)\n-- Welding\n-- Advanced assembly work (require specific tools, measurement instruments and tolerances knowledge to align and assemble)\n-- General electrical work (wiring safety switch, temperature controllers…)\n-- Motor electrical work (wiring motor, contactor, overload protection…)\nWatch this video to find out how to build this machine!\n\n0:00 Before you start\n3:09 Motor Injection Machine intro\n3:36 Chapter I: Build the frame\n7:12 Chapter II: Build the mould area\n8:25 Chapter III: Build the piston system\n14:39 Chapter IV: Build the heating barrel\n17:51 Chapter V: Electrical wiring\n18:56 Chapter VI: Connect the motor\n20:10 Chapter VII: Assembly\nHow to use the machine\n1. Turn on the machine and fill the barrel with plastic.\n2. For the first injection, wait 25 minutes since the machine was turned on and filled.\n3. Place the mould over the jack surface and press it against the nozzle tightly.\n4. Turn on the motor to move down the piston, pushing the molten plastic inside the mold until the belt starts slipping in the pulley.\n5. Turn off the motor and wait around 5 seconds maintaining the piston pressure.\n6. Then turn the motor backwards to move the piston up\n7. For continuous injections refill the barrel before removing the mold from the nozzle\n8. Remove the mold by lowering the jack \n9. Open the mold and take out the injected part\n10. Close the mold and repeat the process from step 3\n\nRecommendations\nFor this machine, you will need molds that have a connical nozzle connection or create an adapter to fit with you mold nozzle. This machine can create a lot of pressure so you will be able to inject products with very thin walls.\nSo this is how you make a Motor Injection Machine!\n\nIf you cannot replicate the machine or simply want to buy some of the other machines or moulds I create, make sure to visit my Bazar shop 🤑 !\n\nhttps://bazar.preciousplastic.com/machines/injection/injection-fully-built/motor-injection-machine/ \n"
"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, eg: sustainable, circular, recycling ... inflated prospects\nContext: howto tutorials, for makers\nConvert units, from metric to imperial and vice versa (in braces)\ndont comment just return as Markdown\n\nText to process:\nYou can try this project with other types of CNC machines, even manual Routers or manual saw, as I did on this video: <a class=\"text-orange-600 underline\" href=\"https://youtu.be/gxkcffQD3eQ,\" target=\"_blank\" rel=\"noopener noreferrer\">youtu.be/gxkcffQD3eQ,</a> but the important thing is that you share what you do and help this community to grow!!!\n\nShare your ideas and comments!"
},
{
"role": "user",

View File

@ -33,14 +33,6 @@ const TemplateConfigSchema = z.object({
type TemplateConfig = z.infer<typeof TemplateConfigSchema>;
interface TemplateFunction {
(opts?: Partial<TemplateConfig>): TemplateConfig;
}
interface TemplateMap {
[key: string]: TemplateFunction | TemplateConfig;
}
const LLMConfigSchema = z.object({
templates: z.record(TemplateConfigSchema),
instructions: InstructionSetSchema.optional(),
@ -49,13 +41,11 @@ const LLMConfigSchema = z.object({
type LLMConfig = z.infer<typeof LLMConfigSchema>;
// Context enum for template switching
export const enum TemplateContext {
COMMONS = 'commons',
HOWTO = 'howto',
MARKETPLACE = 'marketplace'
}
// Default configuration
export const DEFAULT_CONFIG: LLMConfig = {
templates: {},
@ -152,18 +142,14 @@ const DEFAULT_PROMPTS: PromptRegistry = {
template: "Markdown chapter (h4) with a list of local resources, services & suppliers, max. 5, with links, group by category. dont comment, just the list",
format: 'markdown'
}
};
// Helper function to render prompt
}
const renderPrompt = (prompt: Prompt, variables: Record<string, string> = {}): string => {
let result = prompt.template;
for (const [key, value] of Object.entries(variables)) {
result = result.replace(new RegExp(`\\{${key}\\}`, 'g'), value);
}
return result;
};
// Template definitions
}
const createTemplate = (config: LLMConfig, name: string, defaults: Partial<TemplateConfig>, promptKey?: keyof PromptRegistry) => {
return (opts: Partial<TemplateConfig> = {}) => {
const template = config.templates[name] || defaults;
@ -171,15 +157,14 @@ const createTemplate = (config: LLMConfig, name: string, defaults: Partial<Templ
config.instructions || {},
config.defaults || {},
opts.overrides || template.overrides
);
)
const merged = {
...template,
...opts,
prompt
};
return merged;
};
return merged
}
};
export const createTemplates = (context: TemplateContext = TemplateContext.COMMONS) => {
@ -211,17 +196,14 @@ export const createTemplates = (context: TemplateContext = TemplateContext.COMMO
case TemplateContext.HOWTO:
return {
keywords: createTemplate(config, 'keywords', {
_router: "openai",
model: "google/gemini-exp-1206:free",
...DEFAULT_TEMPLATE_OPTIONS
}, 'keywords'),
references: createTemplate(config, 'references', {
_router: "openai",
model: "google/gemini-exp-1206:free",
...DEFAULT_TEMPLATE_OPTIONS
}, 'references'),
toolsAndHardware: createTemplate(config, 'toolsAndHardware', {
router: "openai",
model: "perplexity/sonar-deep-research",
...DEFAULT_TEMPLATE_OPTIONS
}, 'toolsAndHardware'),

View File

@ -1,12 +1,8 @@
import { sync as read } from "@polymech/fs/read"
import { sync as exists } from "@polymech/fs/exists"
import { get_cached_object, set_cached_object } from "@polymech/cache"
import { run, OptionsSchema } from "@polymech/kbot-d";
import {
templates as templateRegistry,
import { resolveVariables } from "@polymech/commons/variables"
import {
TemplateProps,
DEFAULT_CONFIG,
buildPrompt,
TemplateContext,
createTemplates
} from "./kbot-templates.js";
@ -15,36 +11,75 @@ export interface Props extends TemplateProps {
context?: TemplateContext;
}
// Helper function to remove empty values from object
const removeEmpty = (obj: any) => {
return Object.fromEntries(
Object.entries(obj).filter(([_, v]) => v != null && v !== '')
);
};
export const filter = async (content: string, tpl: string = 'howto', opts: Props = {}) => {
if (!content || content.length < 20) {
return content;
}
const context = opts.context || TemplateContext.COMMONS;
const templates = createTemplates(context);
if (!templates[tpl]) {
return content;
}
const template = typeof templates[tpl] === 'function' ? templates[tpl]() : templates[tpl];
const options = getFilterOptions(content, template, opts);
const cache_key_obj = {
content,
tpl,
context,
...options,
filters: [],
tools: []
};
const ca_options = JSON.parse(JSON.stringify(removeEmpty(cache_key_obj)));
const cached = await get_cached_object({ ca_options }, 'kbot');
if (cached) {
return cached;
}
const result = await run(options);
// Handle JSON format responses
if (template.format === 'json') {
try {
return JSON.parse(result[0] as string);
const jsonResult = JSON.parse(result[0] as string);
await set_cached_object(content, ca_options, jsonResult, 'kbot');
return jsonResult;
} catch (e) {
console.error('Failed to parse JSON response:', e);
return result[0];
}
}
await set_cached_object({ ca_options }, 'kbot', result[0], {});
return result[0] as string;
};
export const template_filter = async (text: string, template: string, context: TemplateContext = TemplateContext.COMMONS, environment: any = {}) => {
const templates = createTemplates(context);
if (!templates[template]) {
return text;
}
const templateConfig = templates[template]();
const resolvedTemplate = Object.fromEntries(
Object.entries(templateConfig).map(([key, value]) => [
key,
typeof value === 'string' ? resolveVariables(value, true) : value
])
);
const resolvedText = resolveVariables(text, true);
return await filter(resolvedText, template, {
context,
...resolvedTemplate,
prompt: `${resolvedTemplate.prompt}\n\nText to process:\n${resolvedText}`,
variables: environment.variables
});
};
export const getFilterOptions = (content: string, template: any, opts: Props = {}) => {
return OptionsSchema().parse({
...template,

View File

@ -24,8 +24,8 @@ export const HOWTO_GLOB = '**/config.json'
export const FILES_WEB = 'https://files.polymech.io/files/machines/howtos/'
export const HOWTO_FILTER_LLM = true
export const HOWTO_ANNOTATIONS = false
export const HOWTO_ANNOTATIONS_CACHE = true
export const HOWTO_COMPLETE_RESOURCES = true
export const HOWTO_ANNOTATIONS_CACHE = false
export const HOWTO_COMPLETE_RESOURCES = false
export const HOWTO_ADD_HARDWARE = false
export const HOWTO_COMPLETE_SKILLS = false
export const HOWTO_LOCAL_RESOURCES = false

View File

@ -1,65 +0,0 @@
{
"templates": {
"simple": {
"router": "openai",
"model": "gpt-4o",
"mode": "completion",
"preferences": "none",
"filters": "code"
},
"keywords": {
"router": "openai",
"model": "google/gemini-exp-1206:free",
"mode": "completion",
"preferences": "none",
"filters": "code"
},
"references": {
"router": "openai",
"model": "google/gemini-exp-1206:free",
"mode": "completion",
"preferences": "none",
"filters": "code"
},
"codeSimple": {
"model": "gpt-4o",
"mode": "completion",
"preferences": "none",
"filters": "code"
},
"research": {
"router": "openai",
"model": "gpt-4.5-preview",
"mode": "completion",
"preferences": "none",
"filters": "code"
}
},
"instructions": {
"tone": [
{ "flag": "formal", "text": "Use formal and professional language" },
{ "flag": "casual", "text": "Use casual and friendly language" },
{ "flag": "technical", "text": "Use technical and precise language" }
],
"content": [
{ "flag": "spellCheck", "text": "Ensure proper spelling and grammar" },
{ "flag": "removeEmojis", "text": "Remove any emojis or informal symbols" },
{ "flag": "removePersonalPrefs", "text": "Remove personal preferences and subjective statements" },
{ "flag": "shorten", "text": "Keep responses concise and to the point" }
],
"moderation": [
{ "flag": "mafiaFilter", "text": "Filter out inappropriate or harmful content" },
{ "flag": "deprogramming", "text": "Remove any manipulative or biased content" }
],
"format": [
{ "flag": "markdown", "text": "Format response in Markdown" },
{ "flag": "plain", "text": "Use plain text formatting" }
]
},
"defaults": {
"tone": ["formal"],
"content": ["spellCheck", "removeEmojis", "removePersonalPrefs", "shorten"],
"moderation": ["mafiaFilter", "deprogramming"],
"format": ["markdown"]
}
}

View File

@ -4,7 +4,8 @@
"router": "openai",
"model": "gpt-4o",
"preferences": "none",
"mode": "completion"
"mode": "completion",
"filters": "code"
},
"codeSimple": {
"model": "gpt-4o",

View File

@ -9,7 +9,7 @@ import { sync as exists } from '@polymech/fs/exists'
import { sync as mkdir } from '@polymech/fs/dir'
import { sync as rm } from '@polymech/fs/remove'
import type { Loader, LoaderContext } from 'astro/loaders'
import { resolveVariables } from "@polymech/commons/variables"
export * from './howto-model.js'
export * from './filters.js'
@ -33,14 +33,13 @@ import {
HOWTO_ANNOTATIONS
} from "config/config.js"
import { logger } from '@/base/index.js'
import { env, logger } from '@/base/index.js'
import { applyFilters, default_filters, FilterFunction } from './filters.js'
import { TemplateContext } from '@/base/kbot-templates.js';
import { TemplateContext, buildPrompt, LLMConfig, createTemplates } from '@/base/kbot-templates.js';
import { template_filter } from '@/base/kbot.js'
//export const load = () => get(`${HOWTO_ROOT()}/${HOWTO_GLOB}`, HOWTO_ROOT(), ITEM_TYPE)
export const item_path = (item: any) => `${HOWTO_ROOT()}/${item.data.slug}`
export const asset_local_abs = async (item: IHowto, asset: IImage) => {
const sanitizedFilename = sanitizeFilename(asset.name)
const asset_path = path.join(HOWTO_ROOT(), item.slug, sanitizedFilename)
@ -71,9 +70,7 @@ export const downloadFiles = async (dst: string, howto: IHowto) => {
return;
}
if (exists(zipout)) {
//logger.info(`Removing existing directory: ${zipout}`);
// rm(zipout);
logger.info(`already extracted: ${zipout}`)
logger.debug(`already extracted: ${zipout}`)
return
}
return new Promise<boolean>((resolve, reject) => {
@ -131,9 +128,10 @@ export const raw = async () => {
howtos = howtos.filter((h: IHowto) => {
return h.steps.length > 0 && !blacklist.includes(h._createdBy);
});
howtos = howtos.slice(0, 1)
return howtos
}
export const defaults = async (data: any, cwd: string, root: string) => {
let defaultsJSON = await findUp('defaults.json', {
stopAt: root,
@ -151,13 +149,19 @@ export const defaults = async (data: any, cwd: string, root: string) => {
return data;
}
const commons = async (text: string): Promise<string> => {
const environment = env();
return await template_filter(text, 'simple', TemplateContext.COMMONS, environment);
};
const content = async (str: string, filters: FilterFunction[] = default_filters) => await applyFilters(str, filters)
const complete = async (item: IHowto) => {
if (!HOWTO_ANNOTATIONS) {
return item
// return item
}
// default pass, links, words, formatting, ...
// default pass, links, words, formatting, ...
item.steps = await pMap(
item.steps,
async (step) => ({
@ -165,12 +169,13 @@ const complete = async (item: IHowto) => {
text: await content(step.text)
})
)
// commons: language, tone, bullshit filter, and a piece of love, just a bit, at least :)
if (HOWTO_FILTER_LLM) {
item.steps = await pMap(
item.steps,
async (step) => ({
...step,
text: await content(step.text, [(text) => filter(text, 'howto')])
text: await commons(step.text)
})
)
}

18
temp/cache.ts Normal file
View File

@ -0,0 +1,18 @@
let cache_key_obj: any = {
sw: options.sw,
src,
target,
configuration
}
const ca_options = JSON.parse(JSON.stringify(removeEmpty(cache_key_obj)))
let cached = await get_cached(src, ca_options, MODULE_NAME)
const cachedPath = await get_path_cached(src, ca_options, MODULE_NAME)
if (cached && cachedPath && options.cache == true) {
if (!exists(target) || !equalFiles(target, cachedPath)) {
write(target, Buffer.from(cached))
}
logger.debug(`[${MODULE_NAME}] Skipping conversion of ${src} to ${target}`)
await onNode({ src, target, options })
return Promise.resolve()
}