Sluzba byla v katalogu bez pristupovych udaju a s appId 'ai-text', tedy mirila na aplikaci, ktera neexistuje. Konektor nemel co vyplnit a krok nemel co vykonat. - sluzba stoji na api.openai.com/v1 stejne jako OpenAI, overeni GET /models - model se bere z konektoru (ctx.config.model), ne z kazdeho kroku zvlast - skripty ai-text.classify, ai-text.extract, ai-text.generate Proc to neni jedna sluzba s OpenAI: tam se posila volny dotaz a vraci volny text. Tady je uloha pevna a vystup taky - category a confidence, objekt s popsanymi poli, text s poctem slov. Na to jde ve strome navazat podminkou, na volny text ne. Zjisteno u toho a zapsane do 21-realne-sluzby.md: proxy vraci na neznamou aplikaci 200 s prazdnym telem, takze overeni konektoru u sluzby bez verifyPath projde i tam, kde nic nebezi. Zatim neopraveno. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
115 lines
3.6 KiB
JavaScript
115 lines
3.6 KiB
JavaScript
/**
|
|
* AI zpracovani textu: vytazeni udaju.
|
|
*
|
|
* Sluzba: https://api.openai.com/v1
|
|
* Endpoint: POST /chat/completions
|
|
*
|
|
* Vzor **vystupu, ktery si urcuje uzivatel**. Pole se popisou v kroku stromu
|
|
* a model je vrati jako objekt. Manifest je predem znat nemuze, proto se vraci
|
|
* jeden parametr typu `object` a vedle nej priznak, co se opravdu naslo.
|
|
*
|
|
* Nenalezeny udaj je `null`, ne vymysleny. Model, ktery hada, je horsi nez
|
|
* model, ktery rekne "nevim" - vymyslene IC se poznat neda.
|
|
*/
|
|
|
|
export const manifest = {
|
|
id: 'ai-text.extract',
|
|
name: 'Vytáhnout údaje',
|
|
description:
|
|
'Z volného textu získá strukturovaná data podle polí, která popíšete. ' +
|
|
'Co v textu není, vrátí prázdné, nedomýšlí si.',
|
|
|
|
inputs: [
|
|
{
|
|
id: 'fields',
|
|
label: 'Pole k vytažení',
|
|
type: 'string',
|
|
required: true,
|
|
multiline: true,
|
|
hint:
|
|
'Jedno pole na řádek ve tvaru nazev: popis. Například:\n' +
|
|
'cisloObjednavky: číslo objednávky, obvykle ve tvaru OBJ-1234\n' +
|
|
'castka: celková částka v korunách jako číslo',
|
|
},
|
|
{
|
|
id: 'text',
|
|
label: 'Text',
|
|
type: 'string',
|
|
required: true,
|
|
multiline: true,
|
|
},
|
|
],
|
|
|
|
outputs: [
|
|
{ id: 'data', label: 'Vytažené údaje', type: 'object', required: true },
|
|
{ id: 'found', label: 'Kolik polí se našlo', type: 'number', required: true },
|
|
{ id: 'missing', label: 'Co se nenašlo', type: 'string', required: false },
|
|
{ id: 'complete', label: 'Našlo se všechno', type: 'boolean', required: true },
|
|
],
|
|
|
|
timeoutMs: 45000,
|
|
};
|
|
|
|
export async function run(inputs, ctx) {
|
|
const { pick, first, text } = ctx.util;
|
|
|
|
const fields = inputs.fields
|
|
.split('\n')
|
|
.map((line) => line.trim())
|
|
.filter(Boolean)
|
|
.map((line) => {
|
|
const at = line.indexOf(':');
|
|
return at === -1
|
|
? { name: line, description: '' }
|
|
: { name: line.slice(0, at).trim(), description: line.slice(at + 1).trim() };
|
|
})
|
|
.filter((field) => field.name !== '');
|
|
|
|
if (fields.length === 0) ctx.fail('Nepopsali jste žádné pole, takže není co vytáhnout.');
|
|
|
|
const wanted = fields.map((f) => `- ${f.name}${f.description ? `: ${f.description}` : ''}`);
|
|
|
|
const system =
|
|
'Vytáhni z textu uvedená pole a vrať POUZE platný JSON objekt s přesně těmito klíči:\n' +
|
|
`${wanted.join('\n')}\n` +
|
|
'Co v textu není, vrať jako null. Nic si nedomýšlej a nic nedopočítávej.';
|
|
|
|
const { body } = await ctx.http.post('/chat/completions', {
|
|
model: ctx.config.model || 'gpt-4o-mini',
|
|
messages: [
|
|
{ role: 'system', content: system },
|
|
{ role: 'user', content: inputs.text },
|
|
],
|
|
response_format: { type: 'json_object' },
|
|
});
|
|
|
|
const content = text(pick(pick(first(pick(body, 'choices')), 'message'), 'content'));
|
|
if (!content) ctx.fail('Model nevrátil odpověď.', body);
|
|
|
|
let parsed;
|
|
try {
|
|
parsed = JSON.parse(content);
|
|
} catch {
|
|
ctx.fail(`Model nevrátil platný JSON: ${content}`);
|
|
}
|
|
|
|
// Vysledek se sklada podle **popsanych poli**, ne podle toho, co model poslal.
|
|
// Kdyby si pridal klic navic, strom by o nem nevedel a jen by mu zabiral misto.
|
|
const data = {};
|
|
const missing = [];
|
|
for (const field of fields) {
|
|
const value = parsed[field.name];
|
|
data[field.name] = value === undefined ? null : value;
|
|
if (value === undefined || value === null || value === '') missing.push(field.name);
|
|
}
|
|
|
|
if (missing.length > 0) ctx.log(`Nenašlo se: ${missing.join(', ')}.`);
|
|
|
|
return {
|
|
data,
|
|
found: fields.length - missing.length,
|
|
missing: missing.length > 0 ? missing.join(', ') : null,
|
|
complete: missing.length === 0,
|
|
};
|
|
}
|