@graphext/cuery 0.4.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/browser.d.ts +1 -1
- package/esm/browser.d.ts.map +1 -1
- package/esm/browser.js +1 -1
- package/esm/mod.d.ts +5 -2
- package/esm/mod.d.ts.map +1 -1
- package/esm/mod.js +7 -2
- package/esm/src/api.d.ts +36 -5
- package/esm/src/api.d.ts.map +1 -1
- package/esm/src/api.js +84 -37
- package/esm/src/apis/chatgptScraper/brightdata.js +1 -1
- package/esm/src/apis/chatgptScraper/oxy.js +1 -1
- package/esm/src/apis/chatgptScraper/scraper.js +2 -2
- package/esm/src/apis/hasdata/aim.js +1 -1
- package/esm/src/apis/hasdata/aio.js +1 -1
- package/esm/src/apis/hasdata/helpers.d.ts +1 -1
- package/esm/src/apis/hasdata/helpers.d.ts.map +1 -1
- package/esm/src/apis/hasdata/helpers.js +2 -2
- package/esm/src/assets/models.d.ts +60725 -0
- package/esm/src/assets/models.d.ts.map +1 -0
- package/esm/src/assets/models.js +71915 -0
- package/esm/src/helpers/async.d.ts.map +1 -0
- package/esm/src/{async.js → helpers/async.js} +1 -1
- package/esm/src/helpers/seedKeywords.d.ts.map +1 -0
- package/esm/src/helpers/urls.d.ts.map +1 -0
- package/esm/src/helpers/utils.d.ts.map +1 -0
- package/esm/src/llm.d.ts +35 -0
- package/esm/src/llm.d.ts.map +1 -0
- package/esm/src/llm.js +59 -0
- package/esm/src/providers/google.d.ts +12 -0
- package/esm/src/providers/google.d.ts.map +1 -0
- package/esm/src/providers/google.js +111 -0
- package/esm/src/providers/index.d.ts +13 -0
- package/esm/src/providers/index.d.ts.map +1 -0
- package/esm/src/providers/index.js +14 -0
- package/esm/src/providers/openai.d.ts +12 -0
- package/esm/src/providers/openai.d.ts.map +1 -0
- package/esm/src/providers/openai.js +141 -0
- package/esm/src/providers/pricing.d.ts +72 -0
- package/esm/src/providers/pricing.d.ts.map +1 -0
- package/esm/src/providers/pricing.js +88 -0
- package/esm/src/providers/registry.d.ts +20 -0
- package/esm/src/providers/registry.d.ts.map +1 -0
- package/esm/src/providers/registry.js +35 -0
- package/esm/src/providers/types.d.ts +49 -0
- package/esm/src/providers/types.d.ts.map +1 -0
- package/esm/src/providers/types.js +7 -0
- package/esm/src/response.d.ts +74 -0
- package/esm/src/response.d.ts.map +1 -0
- package/esm/src/response.js +110 -0
- package/esm/src/tool.d.ts +58 -0
- package/esm/src/tool.d.ts.map +1 -0
- package/esm/src/tool.js +91 -0
- package/esm/src/tools/brands.js +6 -6
- package/esm/src/tools/classifier.d.ts +80 -17
- package/esm/src/tools/classifier.d.ts.map +1 -1
- package/esm/src/tools/classifier.js +68 -80
- package/esm/src/tools/entities.d.ts +23 -12
- package/esm/src/tools/entities.d.ts.map +1 -1
- package/esm/src/tools/entities.js +27 -47
- package/esm/src/tools/funnel.js +7 -7
- package/esm/src/tools/generic.d.ts +17 -4
- package/esm/src/tools/generic.d.ts.map +1 -1
- package/esm/src/tools/generic.js +39 -14
- package/esm/src/tools/keywords.js +5 -5
- package/esm/src/tools/personas.d.ts +49 -2
- package/esm/src/tools/personas.d.ts.map +1 -1
- package/esm/src/tools/personas.js +59 -35
- package/esm/src/tools/scorer.d.ts +24 -6
- package/esm/src/tools/scorer.d.ts.map +1 -1
- package/esm/src/tools/scorer.js +27 -22
- package/esm/src/tools/search.d.ts.map +1 -1
- package/esm/src/tools/search.js +33 -9
- package/esm/src/tools/sentiment.d.ts +30 -8
- package/esm/src/tools/sentiment.d.ts.map +1 -1
- package/esm/src/tools/sentiment.js +33 -28
- package/esm/src/tools/sources.d.ts +5 -5
- package/esm/src/tools/sources.d.ts.map +1 -1
- package/esm/src/tools/sources.js +5 -6
- package/esm/src/tools/topics.d.ts +44 -16
- package/esm/src/tools/topics.d.ts.map +1 -1
- package/esm/src/tools/topics.js +77 -68
- package/esm/src/tools/translate.d.ts +22 -31
- package/esm/src/tools/translate.d.ts.map +1 -1
- package/esm/src/tools/translate.js +40 -36
- package/package.json +2 -1
- package/script/browser.d.ts +1 -1
- package/script/browser.d.ts.map +1 -1
- package/script/browser.js +1 -1
- package/script/mod.d.ts +5 -2
- package/script/mod.d.ts.map +1 -1
- package/script/mod.js +14 -2
- package/script/src/api.d.ts +36 -5
- package/script/src/api.d.ts.map +1 -1
- package/script/src/api.js +84 -35
- package/script/src/apis/chatgptScraper/brightdata.js +1 -1
- package/script/src/apis/chatgptScraper/oxy.js +1 -1
- package/script/src/apis/chatgptScraper/scraper.js +2 -2
- package/script/src/apis/hasdata/aim.js +1 -1
- package/script/src/apis/hasdata/aio.js +1 -1
- package/script/src/apis/hasdata/helpers.d.ts +1 -1
- package/script/src/apis/hasdata/helpers.d.ts.map +1 -1
- package/script/src/apis/hasdata/helpers.js +2 -2
- package/script/src/assets/models.d.ts +60725 -0
- package/script/src/assets/models.d.ts.map +1 -0
- package/script/src/assets/models.js +71917 -0
- package/script/src/helpers/async.d.ts.map +1 -0
- package/script/src/{async.js → helpers/async.js} +1 -1
- package/script/src/helpers/seedKeywords.d.ts.map +1 -0
- package/script/src/helpers/urls.d.ts.map +1 -0
- package/script/src/helpers/utils.d.ts.map +1 -0
- package/script/src/llm.d.ts +35 -0
- package/script/src/llm.d.ts.map +1 -0
- package/script/src/llm.js +65 -0
- package/script/src/providers/google.d.ts +12 -0
- package/script/src/providers/google.d.ts.map +1 -0
- package/script/src/providers/google.js +148 -0
- package/script/src/providers/index.d.ts +13 -0
- package/script/src/providers/index.d.ts.map +1 -0
- package/script/src/providers/index.js +24 -0
- package/script/src/providers/openai.d.ts +12 -0
- package/script/src/providers/openai.d.ts.map +1 -0
- package/script/src/providers/openai.js +181 -0
- package/script/src/providers/pricing.d.ts +72 -0
- package/script/src/providers/pricing.d.ts.map +1 -0
- package/script/src/providers/pricing.js +97 -0
- package/script/src/providers/registry.d.ts +20 -0
- package/script/src/providers/registry.d.ts.map +1 -0
- package/script/src/providers/registry.js +39 -0
- package/script/src/providers/types.d.ts +49 -0
- package/script/src/providers/types.d.ts.map +1 -0
- package/script/src/providers/types.js +8 -0
- package/script/src/response.d.ts +74 -0
- package/script/src/response.d.ts.map +1 -0
- package/script/src/response.js +114 -0
- package/script/src/tool.d.ts +58 -0
- package/script/src/tool.d.ts.map +1 -0
- package/script/src/tool.js +95 -0
- package/script/src/tools/brands.js +6 -6
- package/script/src/tools/classifier.d.ts +80 -17
- package/script/src/tools/classifier.d.ts.map +1 -1
- package/script/src/tools/classifier.js +72 -85
- package/script/src/tools/entities.d.ts +23 -12
- package/script/src/tools/entities.d.ts.map +1 -1
- package/script/src/tools/entities.js +29 -51
- package/script/src/tools/funnel.js +7 -7
- package/script/src/tools/generic.d.ts +17 -4
- package/script/src/tools/generic.d.ts.map +1 -1
- package/script/src/tools/generic.js +39 -14
- package/script/src/tools/keywords.js +5 -5
- package/script/src/tools/personas.d.ts +49 -2
- package/script/src/tools/personas.d.ts.map +1 -1
- package/script/src/tools/personas.js +63 -36
- package/script/src/tools/scorer.d.ts +24 -6
- package/script/src/tools/scorer.d.ts.map +1 -1
- package/script/src/tools/scorer.js +28 -24
- package/script/src/tools/search.d.ts.map +1 -1
- package/script/src/tools/search.js +69 -9
- package/script/src/tools/sentiment.d.ts +30 -8
- package/script/src/tools/sentiment.d.ts.map +1 -1
- package/script/src/tools/sentiment.js +37 -30
- package/script/src/tools/sources.d.ts +5 -5
- package/script/src/tools/sources.d.ts.map +1 -1
- package/script/src/tools/sources.js +4 -5
- package/script/src/tools/topics.d.ts +44 -16
- package/script/src/tools/topics.d.ts.map +1 -1
- package/script/src/tools/topics.js +80 -72
- package/script/src/tools/translate.d.ts +22 -31
- package/script/src/tools/translate.d.ts.map +1 -1
- package/script/src/tools/translate.js +43 -40
- package/esm/src/async.d.ts.map +0 -1
- package/esm/src/models.d.ts +0 -18
- package/esm/src/models.d.ts.map +0 -1
- package/esm/src/models.js +0 -48
- package/esm/src/openai.d.ts +0 -17
- package/esm/src/openai.d.ts.map +0 -1
- package/esm/src/openai.js +0 -136
- package/esm/src/tools/seedKeywords.d.ts.map +0 -1
- package/esm/src/urls.d.ts.map +0 -1
- package/esm/src/utils.d.ts.map +0 -1
- package/script/src/async.d.ts.map +0 -1
- package/script/src/models.d.ts +0 -18
- package/script/src/models.d.ts.map +0 -1
- package/script/src/models.js +0 -52
- package/script/src/openai.d.ts +0 -17
- package/script/src/openai.d.ts.map +0 -1
- package/script/src/openai.js +0 -175
- package/script/src/tools/seedKeywords.d.ts.map +0 -1
- package/script/src/urls.d.ts.map +0 -1
- package/script/src/utils.d.ts.map +0 -1
- /package/esm/src/{async.d.ts → helpers/async.d.ts} +0 -0
- /package/esm/src/{tools → helpers}/seedKeywords.d.ts +0 -0
- /package/esm/src/{tools → helpers}/seedKeywords.js +0 -0
- /package/esm/src/{urls.d.ts → helpers/urls.d.ts} +0 -0
- /package/esm/src/{urls.js → helpers/urls.js} +0 -0
- /package/esm/src/{utils.d.ts → helpers/utils.d.ts} +0 -0
- /package/esm/src/{utils.js → helpers/utils.js} +0 -0
- /package/script/src/{async.d.ts → helpers/async.d.ts} +0 -0
- /package/script/src/{tools → helpers}/seedKeywords.d.ts +0 -0
- /package/script/src/{tools → helpers}/seedKeywords.js +0 -0
- /package/script/src/{urls.d.ts → helpers/urls.d.ts} +0 -0
- /package/script/src/{urls.js → helpers/urls.js} +0 -0
- /package/script/src/{utils.d.ts → helpers/utils.d.ts} +0 -0
- /package/script/src/{utils.js → helpers/utils.js} +0 -0
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
5
|
-
const async_js_1 = require("../async.js");
|
|
6
|
-
const openai_js_1 = require("../openai.js");
|
|
3
|
+
exports.ABSentimentsSchema = exports.ABSentimentSchema = exports.SentimentExtractor = void 0;
|
|
4
|
+
const tool_js_1 = require("../tool.js");
|
|
7
5
|
const sentiment_schema_js_1 = require("../schemas/sentiment.schema.js");
|
|
8
|
-
const utils_js_1 = require("../utils.js");
|
|
6
|
+
const utils_js_1 = require("../helpers/utils.js");
|
|
9
7
|
const ABS_PROMPT_SYSTEM = (0, utils_js_1.dedent)(`
|
|
10
8
|
You're an expert in Aspect-Based Sentiment Analysis. Your task involves identifying specific
|
|
11
9
|
entities mentioned in a text (e.g. a person, product, service, or experience) and determining the
|
|
@@ -41,32 +39,41 @@ Return the entities and their sentiments with reasons from the following text se
|
|
|
41
39
|
{text}
|
|
42
40
|
`);
|
|
43
41
|
/**
|
|
44
|
-
*
|
|
42
|
+
* A tool that extracts aspect-based sentiments from text.
|
|
45
43
|
*/
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
class SentimentExtractor extends tool_js_1.Tool {
|
|
45
|
+
systemPrompt;
|
|
46
|
+
constructor(config = {}, modelConfig) {
|
|
47
|
+
super(modelConfig);
|
|
48
|
+
const { instructions = '', brand = null } = config;
|
|
49
|
+
const brandInstructions = brand
|
|
50
|
+
? (0, utils_js_1.dedent)(`
|
|
51
|
+
When analyzing the text, pay special attention to any mentions of the brand "${brand.shortName}"
|
|
52
|
+
or its products/services (${brand.portfolio}). Ensure that any sentiments expressed toward this
|
|
53
|
+
brand or its offerings are accurately captured in your output. Respond in language code ${brand.language}.
|
|
54
|
+
`)
|
|
55
|
+
: '';
|
|
56
|
+
const combinedInstructions = [instructions, brandInstructions].filter(Boolean).join('\n\n');
|
|
57
|
+
this.systemPrompt = ABS_PROMPT_SYSTEM.replace('{instructions}', combinedInstructions);
|
|
49
58
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
schema() {
|
|
60
|
+
return sentiment_schema_js_1.ABSentimentsSchema;
|
|
61
|
+
}
|
|
62
|
+
prompt(text) {
|
|
63
|
+
const userPrompt = ABS_PROMPT_USER.replace('{text}', text ?? '');
|
|
64
|
+
return [
|
|
65
|
+
{ role: 'system', content: this.systemPrompt },
|
|
66
|
+
{ role: 'user', content: userPrompt }
|
|
67
|
+
];
|
|
68
|
+
}
|
|
69
|
+
isEmpty(text) {
|
|
70
|
+
return text == null || text.trim() === '';
|
|
71
|
+
}
|
|
72
|
+
extractResult(parsed) {
|
|
73
|
+
return parsed.aspects;
|
|
59
74
|
}
|
|
60
|
-
return parsed.aspects;
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Classifies multiple data records concurrently while preserving order.
|
|
64
|
-
*/
|
|
65
|
-
async function extractABSForBrandBatch(texts, brand = null, model = 'gpt-4.1-mini', maxConcurrency = 100) {
|
|
66
|
-
const instructions = brand ? (0, utils_js_1.dedent)(`
|
|
67
|
-
When analyzing the text, pay special attention to any mentions of the brand "${brand.shortName}"
|
|
68
|
-
or its products/services (${brand.portfolio}). Ensure that any sentiments expressed toward this
|
|
69
|
-
brand or its offerings are accurately captured in your output. Respond in language code ${brand.language}.
|
|
70
|
-
`) : '';
|
|
71
|
-
return (0, async_js_1.mapParallel)(texts, maxConcurrency, (text) => extractAspectBasedSentiments(text, instructions, model));
|
|
72
75
|
}
|
|
76
|
+
exports.SentimentExtractor = SentimentExtractor;
|
|
77
|
+
var sentiment_schema_js_2 = require("../schemas/sentiment.schema.js");
|
|
78
|
+
Object.defineProperty(exports, "ABSentimentSchema", { enumerable: true, get: function () { return sentiment_schema_js_2.ABSentimentSchema; } });
|
|
79
|
+
Object.defineProperty(exports, "ABSentimentsSchema", { enumerable: true, get: function () { return sentiment_schema_js_2.ABSentimentsSchema; } });
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { FlaggedBrand } from '../schemas/brand.schema.js';
|
|
2
2
|
import type { CategorizedSource, EnrichedSource, Source } from '../schemas/sources.schema.js';
|
|
3
3
|
import { type TopicLabel } from './topics.js';
|
|
4
|
-
import type {
|
|
4
|
+
import type { ProviderParams } from '../llm.js';
|
|
5
5
|
import type { Entity } from './entities.js';
|
|
6
6
|
export type { Source, EnrichedSource, CategorizedSource } from '../schemas/sources.schema.js';
|
|
7
7
|
/**
|
|
@@ -27,13 +27,13 @@ export declare function collectURLs(sourceLists: Array<Array<Source>>, domains?:
|
|
|
27
27
|
/**
|
|
28
28
|
* Classifies an array of URLs into categories based on WEB_TAXONOMY.
|
|
29
29
|
*/
|
|
30
|
-
export declare function classifyURLs(urls: Array<string>, model?: string, modelParams?:
|
|
30
|
+
export declare function classifyURLs(urls: Array<string>, model?: string, modelParams?: ProviderParams, maxConcurrency?: number): Promise<Record<string, TopicLabel | null>>;
|
|
31
31
|
/**
|
|
32
32
|
* Creates a category mapper for sources by collecting unique URLs/domains and classifying them.
|
|
33
33
|
*/
|
|
34
|
-
export declare function makeCategoryMapper(sourceLists: Array<Array<Source>>, domains?: boolean, model?: string, modelParams?:
|
|
34
|
+
export declare function makeCategoryMapper(sourceLists: Array<Array<Source>>, domains?: boolean, model?: string, modelParams?: ProviderParams, maxConcurrency?: number): Promise<Record<string, TopicLabel | null>>;
|
|
35
35
|
/**
|
|
36
36
|
* Categorizes sources by assigning topic and subtopic to each EnrichedSource in-place(!).
|
|
37
37
|
*/
|
|
38
|
-
export declare function categorizeSources(sourceLists: Array<Array<EnrichedSource>>, domains?: boolean, model?: string, modelParams?:
|
|
38
|
+
export declare function categorizeSources(sourceLists: Array<Array<EnrichedSource>>, domains?: boolean, model?: string, modelParams?: ProviderParams, maxConcurrency?: number): Promise<Array<Array<CategorizedSource>>>;
|
|
39
39
|
//# sourceMappingURL=sources.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sources.d.ts","sourceRoot":"","sources":["../../../src/src/tools/sources.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sources.d.ts","sourceRoot":"","sources":["../../../src/src/tools/sources.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAC9F,OAAO,EAA2B,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C,YAAY,EAAE,MAAM,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAE9F;;GAEG;AACH,wBAAgB,YAAY,CAC3B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,KAAK,CAAC,YAAY,CAAC,EAC3B,QAAQ,GAAE,KAAK,CAAC,MAAM,CAAM,GAC1B,cAAc,CAoEhB;AAED,wBAAsB,aAAa,CAClC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,EACpC,MAAM,EAAE,KAAK,CAAC,YAAY,CAAC,EAC3B,QAAQ,GAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAM,GACjC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAIvC;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACtC,OAAO,EAAE,KAAK,CAAC,cAAc,CAAC,GAC5B;IAAE,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAAC,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;CAAE,CA8DjE;AAED,wBAAgB,qBAAqB,CACpC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,GACnC;IAAE,eAAe,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAAC,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;CAAE,CAc/E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAC1B,WAAW,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EACjC,OAAO,GAAE,OAAe,GACtB,KAAK,CAAC,MAAM,CAAC,CAgBf;AA+DD;;GAEG;AACH,wBAAsB,YAAY,CACjC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,EACnB,KAAK,GAAE,MAAkB,EACzB,WAAW,GAAE,cAAkD,EAC/D,cAAc,GAAE,MAAY,GAC1B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC,CAAC,CAc5C;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACvC,WAAW,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EACjC,OAAO,GAAE,OAAe,EACxB,KAAK,GAAE,MAAkB,EACzB,WAAW,GAAE,cAAkD,EAC/D,cAAc,GAAE,MAAY,GAC1B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC,CAAC,CAI5C;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACtC,WAAW,EAAE,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,EACzC,OAAO,GAAE,OAAe,EACxB,KAAK,GAAE,MAAkB,EACzB,WAAW,GAAE,cAAkD,EAC/D,cAAc,GAAE,MAAY,GAC1B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAiB1C"}
|
|
@@ -8,7 +8,6 @@ exports.collectURLs = collectURLs;
|
|
|
8
8
|
exports.classifyURLs = classifyURLs;
|
|
9
9
|
exports.makeCategoryMapper = makeCategoryMapper;
|
|
10
10
|
exports.categorizeSources = categorizeSources;
|
|
11
|
-
const async_js_1 = require("../async.js");
|
|
12
11
|
const brands_js_1 = require("./brands.js");
|
|
13
12
|
const topics_js_1 = require("./topics.js");
|
|
14
13
|
/**
|
|
@@ -232,16 +231,16 @@ const WEB_TAXONOMY = {
|
|
|
232
231
|
'Personal / Portfolio Site'
|
|
233
232
|
]
|
|
234
233
|
};
|
|
235
|
-
const
|
|
236
|
-
const WEB_TAXONOMY_SERIALIZED = JSON.stringify(WEB_TAXONOMY, null, 2);
|
|
234
|
+
const WEB_TAXONOMY_TOPICS = (0, topics_js_1.toTopics)(WEB_TAXONOMY);
|
|
237
235
|
/**
|
|
238
236
|
* Classifies an array of URLs into categories based on WEB_TAXONOMY.
|
|
239
237
|
*/
|
|
240
238
|
async function classifyURLs(urls, model = 'gpt-5.1', modelParams = { reasoning: { effort: 'none' } }, maxConcurrency = 100) {
|
|
241
|
-
const
|
|
239
|
+
const assigner = new topics_js_1.TopicAssigner({ taxonomy: WEB_TAXONOMY_TOPICS }, { model, modelParams, maxConcurrency });
|
|
240
|
+
const results = await assigner.batch(urls);
|
|
242
241
|
const urlToCategory = {};
|
|
243
242
|
urls.forEach((url, index) => {
|
|
244
|
-
urlToCategory[url] =
|
|
243
|
+
urlToCategory[url] = results.toArray()[index];
|
|
245
244
|
});
|
|
246
245
|
return urlToCategory;
|
|
247
246
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from '../../deps/jsr.io/@zod/zod/4.3.6/src/index.js';
|
|
2
|
-
import { type
|
|
2
|
+
import { Tool, type ModelConfig } from '../tool.js';
|
|
3
|
+
import type { Message } from '../llm.js';
|
|
3
4
|
import { type TopicType, type TaxonomyType, type TopicLabel } from '../schemas/topics.schema.js';
|
|
4
5
|
export type { TopicType, TaxonomyType, TopicLabel };
|
|
5
6
|
/**
|
|
@@ -48,27 +49,54 @@ export declare function createLabelSchema(taxonomy: TaxonomyType): z.ZodObject<{
|
|
|
48
49
|
[x: string]: string;
|
|
49
50
|
}>;
|
|
50
51
|
}, z.core.$strip>;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
*/
|
|
54
|
-
export declare function assignTopic(text: string | null, taxonomy: TaxonomyType | Array<TopicType> | string, labelSchema: z.ZodType<TopicLabel>, model?: string, modelParams?: AIParams): Promise<TopicLabel | null>;
|
|
55
|
-
/**
|
|
56
|
-
* Assigns topics to multiple texts concurrently while preserving order.
|
|
57
|
-
*/
|
|
58
|
-
export declare function assignTopics(texts: Array<string | null>, taxonomy: TaxonomyType | Array<TopicType>, model?: string, modelParams?: AIParams, maxConcurrency?: number): Promise<Array<TopicLabel | null>>;
|
|
59
|
-
export interface TopicExtractionOptions {
|
|
60
|
-
records: Array<Record<string, unknown>>;
|
|
52
|
+
export interface TopicExtractorConfig {
|
|
53
|
+
/** Maximum number of top-level topics (default: 10) */
|
|
61
54
|
nTopics?: number;
|
|
55
|
+
/** Maximum number of subtopics per topic (default: 5) */
|
|
62
56
|
nSubtopics?: number;
|
|
57
|
+
/** Additional instructions */
|
|
63
58
|
instructions?: string;
|
|
59
|
+
/** Maximum number of records to sample (default: 500) */
|
|
64
60
|
maxSamples?: number;
|
|
65
|
-
|
|
66
|
-
modelParams?: AIParams;
|
|
67
|
-
maxRetries?: number;
|
|
61
|
+
/** Language for topics (default: same as records) */
|
|
68
62
|
language?: string;
|
|
69
63
|
}
|
|
70
64
|
/**
|
|
71
|
-
*
|
|
65
|
+
* A tool that extracts a topic taxonomy from a set of records.
|
|
72
66
|
*/
|
|
73
|
-
export declare
|
|
67
|
+
export declare class TopicExtractor extends Tool<Array<Record<string, unknown>>, TaxonomyType, TaxonomyType> {
|
|
68
|
+
private readonly maxSamples;
|
|
69
|
+
private readonly promptTemplate;
|
|
70
|
+
constructor(config: TopicExtractorConfig | undefined, modelConfig: ModelConfig);
|
|
71
|
+
protected schema(): z.ZodObject<{
|
|
72
|
+
topics: z.ZodArray<z.ZodObject<{
|
|
73
|
+
topic: z.ZodString;
|
|
74
|
+
subtopics: z.ZodArray<z.ZodString>;
|
|
75
|
+
}, z.core.$strip>>;
|
|
76
|
+
}, z.core.$strip>;
|
|
77
|
+
protected prompt(records: Array<Record<string, unknown>>): string;
|
|
78
|
+
protected isEmpty(records: Array<Record<string, unknown>>): boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Not supported. TopicExtractor is an aggregation operation that extracts
|
|
81
|
+
* a single taxonomy from many records. Use invoke() instead.
|
|
82
|
+
*/
|
|
83
|
+
batch(): never;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Configuration for the TopicAssigner tool.
|
|
87
|
+
*/
|
|
88
|
+
export interface TopicAssignerConfig {
|
|
89
|
+
taxonomy: TaxonomyType | Array<TopicType>;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* A tool that assigns topic and subtopic labels to text based on a taxonomy.
|
|
93
|
+
*/
|
|
94
|
+
export declare class TopicAssigner extends Tool<string | null, TopicLabel, TopicLabel> {
|
|
95
|
+
private readonly labelSchema;
|
|
96
|
+
private readonly systemPrompt;
|
|
97
|
+
constructor(config: TopicAssignerConfig, modelConfig: ModelConfig);
|
|
98
|
+
protected schema(): z.ZodType<TopicLabel, unknown, z.core.$ZodTypeInternals<TopicLabel, unknown>>;
|
|
99
|
+
protected prompt(text: string | null): Message[];
|
|
100
|
+
protected isEmpty(text: string | null): boolean;
|
|
101
|
+
}
|
|
74
102
|
//# sourceMappingURL=topics.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"topics.d.ts","sourceRoot":"","sources":["../../../src/src/tools/topics.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,+CAA+C,CAAC;
|
|
1
|
+
{"version":3,"file":"topics.d.ts","sourceRoot":"","sources":["../../../src/src/tools/topics.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,+CAA+C,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,EAEN,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,MAAM,6BAA6B,CAAC;AAIrC,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;AA+EpD;;;GAGG;AACH,eAAO,MAAM,KAAK;;;iBAShB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,YAAY;;;;;iBAEvB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,QAAQ;;;;;iBAEnB,CAAC;AAEH;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;CAAE,CAAC,CAKpH;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,YAAY;;;;;;;kBAmBvD;AA+BD,MAAM,WAAW,oBAAoB;IACpC,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,IAAI,CACvC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAC9B,YAAY,EACZ,YAAY,CACZ;IACA,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAE5B,MAAM,EAAE,oBAAoB,YAAK,EAAE,WAAW,EAAE,WAAW;cAkBpD,MAAM;;;;;;IAIzB,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;cAQrC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO;IAI5E;;;OAGG;IACM,KAAK,IAAI,KAAK;CAOvB;AAyBD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC,QAAQ,EAAE,YAAY,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC;CAC1C;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,IAAI,CAAC,MAAM,GAAG,IAAI,EAAE,UAAU,EAAE,UAAU,CAAC;IAC7E,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAwB;IACpD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAE1B,MAAM,EAAE,mBAAmB,EAAE,WAAW,EAAE,WAAW;cAiB9C,MAAM;IAIzB,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,EAAE;cAQ7B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO;CAGxD"}
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Taxonomy = exports.TaxonomyBase = exports.Topic = void 0;
|
|
3
|
+
exports.TopicAssigner = exports.TopicExtractor = exports.Taxonomy = exports.TaxonomyBase = exports.Topic = void 0;
|
|
4
4
|
exports.toTopics = toTopics;
|
|
5
5
|
exports.createLabelSchema = createLabelSchema;
|
|
6
|
-
exports.assignTopic = assignTopic;
|
|
7
|
-
exports.assignTopics = assignTopics;
|
|
8
|
-
exports.extractTopics = extractTopics;
|
|
9
6
|
/* eslint no-console: ["warn", { allow: ["log", "warn", "error"] }] */
|
|
10
7
|
const index_js_1 = require("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js");
|
|
11
|
-
const
|
|
12
|
-
const openai_js_1 = require("../openai.js");
|
|
8
|
+
const tool_js_1 = require("../tool.js");
|
|
13
9
|
const topics_schema_js_1 = require("../schemas/topics.schema.js");
|
|
14
|
-
const utils_js_1 = require("../utils.js");
|
|
10
|
+
const utils_js_1 = require("../helpers/utils.js");
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// Helper Functions
|
|
13
|
+
// =============================================================================
|
|
15
14
|
/**
|
|
16
15
|
* Levenshtein distance implementation for string similarity validation
|
|
17
16
|
*/
|
|
@@ -69,6 +68,9 @@ function validateSubtopics(topic, subtopics) {
|
|
|
69
68
|
}
|
|
70
69
|
return errors;
|
|
71
70
|
}
|
|
71
|
+
// =============================================================================
|
|
72
|
+
// Schemas
|
|
73
|
+
// =============================================================================
|
|
72
74
|
/**
|
|
73
75
|
* Topic schema with subtopic validation
|
|
74
76
|
* Validates that subtopics are sufficiently distinct from each other and from the parent topic.
|
|
@@ -128,6 +130,9 @@ function createLabelSchema(taxonomy) {
|
|
|
128
130
|
}
|
|
129
131
|
});
|
|
130
132
|
}
|
|
133
|
+
// =============================================================================
|
|
134
|
+
// TopicExtractor
|
|
135
|
+
// =============================================================================
|
|
131
136
|
const TOPICS_PROMPT = (0, utils_js_1.dedent)(`
|
|
132
137
|
# Instructions
|
|
133
138
|
|
|
@@ -152,6 +157,49 @@ The taxonomy should follow the MECE framework (Mutually Exclusive, Collectively
|
|
|
152
157
|
|
|
153
158
|
{records}
|
|
154
159
|
`);
|
|
160
|
+
/**
|
|
161
|
+
* A tool that extracts a topic taxonomy from a set of records.
|
|
162
|
+
*/
|
|
163
|
+
class TopicExtractor extends tool_js_1.Tool {
|
|
164
|
+
maxSamples;
|
|
165
|
+
promptTemplate;
|
|
166
|
+
constructor(config = {}, modelConfig) {
|
|
167
|
+
super(modelConfig);
|
|
168
|
+
const { nTopics = 10, nSubtopics = 5, instructions = '', maxSamples = 500, language = 'The same language as the records' } = config;
|
|
169
|
+
this.maxSamples = maxSamples;
|
|
170
|
+
this.promptTemplate = TOPICS_PROMPT
|
|
171
|
+
.replace('{n_topics}', String(nTopics))
|
|
172
|
+
.replace('{n_subtopics}', String(nSubtopics))
|
|
173
|
+
.replace('{instructions}', instructions)
|
|
174
|
+
.replace('{language}', language);
|
|
175
|
+
}
|
|
176
|
+
schema() {
|
|
177
|
+
return exports.Taxonomy;
|
|
178
|
+
}
|
|
179
|
+
prompt(records) {
|
|
180
|
+
const sampledRecords = records.length > this.maxSamples
|
|
181
|
+
? records.slice(0, this.maxSamples)
|
|
182
|
+
: records;
|
|
183
|
+
const formattedRecords = (0, utils_js_1.formatRecordsAttrWise)(sampledRecords);
|
|
184
|
+
return this.promptTemplate.replace('{records}', formattedRecords);
|
|
185
|
+
}
|
|
186
|
+
isEmpty(records) {
|
|
187
|
+
return !records || records.length === 0;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Not supported. TopicExtractor is an aggregation operation that extracts
|
|
191
|
+
* a single taxonomy from many records. Use invoke() instead.
|
|
192
|
+
*/
|
|
193
|
+
batch() {
|
|
194
|
+
throw new Error('TopicExtractor.batch() is not supported. ' +
|
|
195
|
+
'This tool extracts a single taxonomy from many records (aggregation). ' +
|
|
196
|
+
'Use invoke() with all records instead.');
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
exports.TopicExtractor = TopicExtractor;
|
|
200
|
+
// =============================================================================
|
|
201
|
+
// TopicAssigner
|
|
202
|
+
// =============================================================================
|
|
155
203
|
const LABEL_PROMPT_SYSTEM = (0, utils_js_1.dedent)(`
|
|
156
204
|
You're task is to use the following hierarchy of topics and subtopics (in json format),
|
|
157
205
|
to assign the correct topic and subtopic to each text in the input.
|
|
@@ -170,74 +218,34 @@ Assign the correct topic and subtopic to the following text.
|
|
|
170
218
|
{text}
|
|
171
219
|
`);
|
|
172
220
|
/**
|
|
173
|
-
*
|
|
221
|
+
* A tool that assigns topic and subtopic labels to text based on a taxonomy.
|
|
174
222
|
*/
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
return null;
|
|
189
|
-
}
|
|
190
|
-
return parsed;
|
|
223
|
+
class TopicAssigner extends tool_js_1.Tool {
|
|
224
|
+
labelSchema;
|
|
225
|
+
systemPrompt;
|
|
226
|
+
constructor(config, modelConfig) {
|
|
227
|
+
super(modelConfig);
|
|
228
|
+
const { taxonomy } = config;
|
|
229
|
+
// Normalize taxonomy to TaxonomyType
|
|
230
|
+
const normalizedTaxonomy = Array.isArray(taxonomy)
|
|
231
|
+
? { topics: taxonomy }
|
|
232
|
+
: taxonomy;
|
|
233
|
+
// Build schema and system prompt once in constructor
|
|
234
|
+
this.labelSchema = createLabelSchema(normalizedTaxonomy);
|
|
235
|
+
this.systemPrompt = LABEL_PROMPT_SYSTEM.replace('{taxonomy}', JSON.stringify(normalizedTaxonomy, null, 2));
|
|
191
236
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
return null;
|
|
237
|
+
schema() {
|
|
238
|
+
return this.labelSchema;
|
|
195
239
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
const normalizedTaxonomy = Array.isArray(taxonomy)
|
|
203
|
-
? { topics: taxonomy }
|
|
204
|
-
: taxonomy;
|
|
205
|
-
const labelSchema = createLabelSchema(normalizedTaxonomy);
|
|
206
|
-
const serializedTaxonomy = JSON.stringify(normalizedTaxonomy, null, 2);
|
|
207
|
-
return (0, async_js_1.mapParallel)(texts, maxConcurrency, text => assignTopic(text, serializedTaxonomy, labelSchema, model, modelParams));
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* Extracts a topic hierarchy from an array of records using an LLM.
|
|
211
|
-
*/
|
|
212
|
-
async function extractTopics({ records, nTopics = 10, nSubtopics = 5, instructions = '', maxSamples = 500, model = 'gpt-4.1', modelParams = {}, maxRetries = 8, language = 'The same language as the records' }) {
|
|
213
|
-
if (!records || records.length === 0) {
|
|
214
|
-
return { topics: [] };
|
|
215
|
-
}
|
|
216
|
-
const sampledRecords = records.length > maxSamples
|
|
217
|
-
? records.slice(0, maxSamples)
|
|
218
|
-
: records;
|
|
219
|
-
const formattedRecords = (0, utils_js_1.formatRecordsAttrWise)(sampledRecords);
|
|
220
|
-
const prompt = TOPICS_PROMPT
|
|
221
|
-
.replace('{n_topics}', String(nTopics))
|
|
222
|
-
.replace('{n_subtopics}', String(nSubtopics))
|
|
223
|
-
.replace('{instructions}', instructions)
|
|
224
|
-
.replace('{records}', formattedRecords)
|
|
225
|
-
.replace('{language}', language);
|
|
226
|
-
const { parsed, output_text, error } = await (0, openai_js_1.askOpenAISafe)(prompt, model, exports.Taxonomy, modelParams, maxRetries, 'return');
|
|
227
|
-
if (error != null) {
|
|
228
|
-
if (output_text == null) {
|
|
229
|
-
throw new Error('Failed to get response from OpenAI');
|
|
230
|
-
}
|
|
231
|
-
try {
|
|
232
|
-
const taxonomy = JSON.parse(output_text);
|
|
233
|
-
return exports.TaxonomyBase.parse(taxonomy);
|
|
234
|
-
}
|
|
235
|
-
catch (parseError) {
|
|
236
|
-
throw new Error(`Failed to parse response even without validation: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
|
|
237
|
-
}
|
|
240
|
+
prompt(text) {
|
|
241
|
+
const userPrompt = LABEL_PROMPT_USER.replace('{text}', text ?? '');
|
|
242
|
+
return [
|
|
243
|
+
{ role: 'system', content: this.systemPrompt },
|
|
244
|
+
{ role: 'user', content: userPrompt }
|
|
245
|
+
];
|
|
238
246
|
}
|
|
239
|
-
|
|
240
|
-
|
|
247
|
+
isEmpty(text) {
|
|
248
|
+
return text == null || text.trim() === '';
|
|
241
249
|
}
|
|
242
|
-
return parsed;
|
|
243
250
|
}
|
|
251
|
+
exports.TopicAssigner = TopicAssigner;
|
|
@@ -1,44 +1,35 @@
|
|
|
1
|
+
import { Tool, type ModelConfig } from '../tool.js';
|
|
1
2
|
import type { BrandContext } from '../schemas/brand.schema.js';
|
|
2
|
-
export interface
|
|
3
|
-
|
|
3
|
+
export interface KeywordTranslatorConfig {
|
|
4
|
+
/** Brand context for disambiguation */
|
|
5
|
+
brandContext: BrandContext;
|
|
6
|
+
/** Language for the output prompt (default: 'en') */
|
|
4
7
|
language?: string;
|
|
5
|
-
|
|
8
|
+
/** Additional instructions */
|
|
6
9
|
instructions?: string;
|
|
7
|
-
brandContext: BrandContext;
|
|
8
10
|
}
|
|
9
11
|
/**
|
|
10
|
-
*
|
|
12
|
+
* A tool that converts Google search keywords into natural language LLM prompts.
|
|
13
|
+
* Uses raw text mode (no schema) since the output is plain text.
|
|
11
14
|
*/
|
|
12
|
-
export declare
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
keywords: Array<string>;
|
|
18
|
-
language?: string;
|
|
19
|
-
model?: string;
|
|
20
|
-
maxConcurrency?: number;
|
|
21
|
-
instructions?: string;
|
|
22
|
-
brandContext: BrandContext;
|
|
15
|
+
export declare class KeywordTranslator extends Tool<string | null, string, string> {
|
|
16
|
+
private readonly promptTemplate;
|
|
17
|
+
constructor(config: KeywordTranslatorConfig, modelConfig: ModelConfig);
|
|
18
|
+
protected prompt(keyword: string | null): string;
|
|
19
|
+
protected isEmpty(keyword: string | null): boolean;
|
|
23
20
|
}
|
|
24
|
-
export
|
|
25
|
-
|
|
26
|
-
prompt: string;
|
|
21
|
+
export interface PromptToKeywordConfig {
|
|
22
|
+
/** Language for the output keyword (default: 'en') */
|
|
27
23
|
language?: string;
|
|
28
|
-
model?: string;
|
|
29
24
|
}
|
|
30
25
|
/**
|
|
31
|
-
*
|
|
26
|
+
* A tool that converts natural language prompts into Google search keywords.
|
|
27
|
+
* Uses raw text mode (no schema) since the output is plain text.
|
|
32
28
|
*/
|
|
33
|
-
export declare
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
maxConcurrency?: number;
|
|
29
|
+
export declare class PromptToKeyword extends Tool<string | null, string, string> {
|
|
30
|
+
private readonly promptTemplate;
|
|
31
|
+
constructor(config: PromptToKeywordConfig | undefined, modelConfig: ModelConfig);
|
|
32
|
+
protected prompt(text: string | null): string;
|
|
33
|
+
protected isEmpty(text: string | null): boolean;
|
|
39
34
|
}
|
|
40
|
-
/**
|
|
41
|
-
* Converts multiple natural language prompts to Google search keywords concurrently while preserving order.
|
|
42
|
-
*/
|
|
43
|
-
export declare function reverseTranslateBatch(params: reverseTranslateBatchParams): Promise<Array<string>>;
|
|
44
35
|
//# sourceMappingURL=translate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translate.d.ts","sourceRoot":"","sources":["../../../src/src/tools/translate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"translate.d.ts","sourceRoot":"","sources":["../../../src/src/tools/translate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAEpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AA+C/D,MAAM,WAAW,uBAAuB;IACvC,uCAAuC;IACvC,YAAY,EAAE,YAAY,CAAC;IAC3B,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8BAA8B;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,IAAI,CAAC,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC;IACzE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAE5B,MAAM,EAAE,uBAAuB,EAAE,WAAW,EAAE,WAAW;IAarE,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;cAIpB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO;CAG3D;AAmCD,MAAM,WAAW,qBAAqB;IACrC,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,qBAAa,eAAgB,SAAQ,IAAI,CAAC,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC;IACvE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAE5B,MAAM,EAAE,qBAAqB,YAAK,EAAE,WAAW,EAAE,WAAW;IASxE,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;cAIjB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO;CAGxD"}
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
exports.reverseTranslateBatch = reverseTranslateBatch;
|
|
7
|
-
const async_js_1 = require("../async.js");
|
|
8
|
-
const openai_js_1 = require("../openai.js");
|
|
9
|
-
const utils_js_1 = require("../utils.js");
|
|
3
|
+
exports.PromptToKeyword = exports.KeywordTranslator = void 0;
|
|
4
|
+
const tool_js_1 = require("../tool.js");
|
|
5
|
+
const utils_js_1 = require("../helpers/utils.js");
|
|
10
6
|
const TRANSLATE_PROMPT = (0, utils_js_1.dedent)(`
|
|
11
7
|
You are an expert in understanding search intent and conversational AI interactions.
|
|
12
8
|
|
|
@@ -39,7 +35,7 @@ You will receive brand context (sector, country). Follow these rules strictly:
|
|
|
39
35
|
- WRONG: "Tell me about geography" (ignores sector context)
|
|
40
36
|
- CORRECT: "What is GEO in AI visibility and search optimization?" (uses sector to disambiguate the acronym)
|
|
41
37
|
|
|
42
|
-
{
|
|
38
|
+
{instructions}
|
|
43
39
|
|
|
44
40
|
# Keyword
|
|
45
41
|
|
|
@@ -52,25 +48,32 @@ You will receive brand context (sector, country). Follow these rules strictly:
|
|
|
52
48
|
Return only the converted prompt, nothing else.
|
|
53
49
|
`);
|
|
54
50
|
/**
|
|
55
|
-
*
|
|
51
|
+
* A tool that converts Google search keywords into natural language LLM prompts.
|
|
52
|
+
* Uses raw text mode (no schema) since the output is plain text.
|
|
56
53
|
*/
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
54
|
+
class KeywordTranslator extends tool_js_1.Tool {
|
|
55
|
+
promptTemplate;
|
|
56
|
+
constructor(config, modelConfig) {
|
|
57
|
+
super(modelConfig);
|
|
58
|
+
const { brandContext, language = 'en', instructions = '' } = config;
|
|
59
|
+
this.promptTemplate = TRANSLATE_PROMPT
|
|
60
|
+
.replace('{language}', language)
|
|
61
|
+
.replace('{sector}', brandContext.sector)
|
|
62
|
+
.replace('{country}', brandContext.country)
|
|
63
|
+
.replace('{instructions}', instructions);
|
|
64
|
+
}
|
|
65
|
+
// No schema() override - uses default null for raw text mode
|
|
66
|
+
prompt(keyword) {
|
|
67
|
+
return this.promptTemplate.replace('{keyword}', keyword ?? '');
|
|
68
|
+
}
|
|
69
|
+
isEmpty(keyword) {
|
|
70
|
+
return keyword == null || keyword.trim() === '';
|
|
67
71
|
}
|
|
68
|
-
return parsed;
|
|
69
|
-
}
|
|
70
|
-
async function translateBatch(params) {
|
|
71
|
-
const { keywords, language = 'en', model = 'gpt-4.1-mini', maxConcurrency = 100, brandContext, instructions = '' } = params;
|
|
72
|
-
return (0, async_js_1.mapParallel)(keywords, maxConcurrency, kwd => translate({ keyword: kwd, language, model, brandContext, instructions }));
|
|
73
72
|
}
|
|
73
|
+
exports.KeywordTranslator = KeywordTranslator;
|
|
74
|
+
// =============================================================================
|
|
75
|
+
// PromptToKeyword (LLM prompt → keyword)
|
|
76
|
+
// =============================================================================
|
|
74
77
|
const REVERSE_TRANSLATE_PROMPT = (0, utils_js_1.dedent)(`
|
|
75
78
|
You are an expert in understanding search intent.
|
|
76
79
|
|
|
@@ -100,22 +103,22 @@ Otherwise, Google keyword planner will not accept it.
|
|
|
100
103
|
Return only the keyword, nothing else.
|
|
101
104
|
`);
|
|
102
105
|
/**
|
|
103
|
-
*
|
|
106
|
+
* A tool that converts natural language prompts into Google search keywords.
|
|
107
|
+
* Uses raw text mode (no schema) since the output is plain text.
|
|
104
108
|
*/
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
109
|
+
class PromptToKeyword extends tool_js_1.Tool {
|
|
110
|
+
promptTemplate;
|
|
111
|
+
constructor(config = {}, modelConfig) {
|
|
112
|
+
super(modelConfig);
|
|
113
|
+
const { language = 'en' } = config;
|
|
114
|
+
this.promptTemplate = REVERSE_TRANSLATE_PROMPT.replace('{language}', language);
|
|
115
|
+
}
|
|
116
|
+
// No schema() override - uses default null for raw text mode
|
|
117
|
+
prompt(text) {
|
|
118
|
+
return this.promptTemplate.replace('{prompt}', text ?? '');
|
|
119
|
+
}
|
|
120
|
+
isEmpty(text) {
|
|
121
|
+
return text == null || text.trim() === '';
|
|
112
122
|
}
|
|
113
|
-
return parsed;
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Converts multiple natural language prompts to Google search keywords concurrently while preserving order.
|
|
117
|
-
*/
|
|
118
|
-
async function reverseTranslateBatch(params) {
|
|
119
|
-
const { prompts, language = 'en', model = 'gpt-5-mini', maxConcurrency = 100 } = params;
|
|
120
|
-
return (0, async_js_1.mapParallel)(prompts, maxConcurrency, p => reverseTranslate({ prompt: p, language, model }));
|
|
121
123
|
}
|
|
124
|
+
exports.PromptToKeyword = PromptToKeyword;
|