@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,7 +1,6 @@
|
|
|
1
1
|
import { z } from '../../deps/jsr.io/@zod/zod/4.3.6/src/index.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { dedent, formatRecordsAttrWise } from '../utils.js';
|
|
2
|
+
import { Tool } from '../tool.js';
|
|
3
|
+
import { dedent, formatRecordsAttrWise } from '../helpers/utils.js';
|
|
5
4
|
const PROMPT_TEMPLATE = dedent(`
|
|
6
5
|
# Instructions
|
|
7
6
|
|
|
@@ -36,7 +35,6 @@ if it matches multiple categories. Assign all relevant labels that apply to the
|
|
|
36
35
|
`);
|
|
37
36
|
/**
|
|
38
37
|
* Formats a record object into a human-readable text representation.
|
|
39
|
-
* Similar to the record_to_text.jinja template in Python.
|
|
40
38
|
*/
|
|
41
39
|
function formatRecord(record) {
|
|
42
40
|
return Object.entries(record)
|
|
@@ -53,7 +51,6 @@ function formatLabels(labels) {
|
|
|
53
51
|
}
|
|
54
52
|
/**
|
|
55
53
|
* Creates a dynamic Category schema based on provided labels.
|
|
56
|
-
* Each category literal includes its description, which helps the LLM understand the classification.
|
|
57
54
|
*/
|
|
58
55
|
function createLabelSchema(labels) {
|
|
59
56
|
const entries = Object.entries(labels);
|
|
@@ -66,7 +63,6 @@ function createLabelSchema(labels) {
|
|
|
66
63
|
label: z.literal(label).describe(description)
|
|
67
64
|
});
|
|
68
65
|
}
|
|
69
|
-
// TypeScript now knows entries.length >= 2
|
|
70
66
|
const literals = entries.map(([label, description]) => z.literal(label).describe(description));
|
|
71
67
|
return z.object({
|
|
72
68
|
label: z.union(literals)
|
|
@@ -74,7 +70,6 @@ function createLabelSchema(labels) {
|
|
|
74
70
|
}
|
|
75
71
|
/**
|
|
76
72
|
* Creates a dynamic multi-label schema based on provided labels.
|
|
77
|
-
* Returns a schema that accepts an array of labels, reusing the single label schema.
|
|
78
73
|
*/
|
|
79
74
|
function createMultiLabelSchema(labels) {
|
|
80
75
|
const singleLabelSchema = createLabelSchema(labels);
|
|
@@ -86,55 +81,55 @@ function createMultiLabelSchema(labels) {
|
|
|
86
81
|
});
|
|
87
82
|
}
|
|
88
83
|
/**
|
|
89
|
-
*
|
|
84
|
+
* A tool that classifies records into one of the provided categories.
|
|
90
85
|
*/
|
|
91
|
-
export
|
|
92
|
-
|
|
93
|
-
|
|
86
|
+
export class Classifier extends Tool {
|
|
87
|
+
labelSchema;
|
|
88
|
+
promptTemplate;
|
|
89
|
+
constructor(config, modelConfig) {
|
|
90
|
+
super(modelConfig);
|
|
91
|
+
const { labels, instructions = '' } = config;
|
|
92
|
+
this.labelSchema = createLabelSchema(labels);
|
|
93
|
+
this.promptTemplate = PROMPT_TEMPLATE
|
|
94
|
+
.replace('{labels}', formatLabels(labels))
|
|
95
|
+
.replace('{instructions}', instructions);
|
|
94
96
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
.replace('{labels}', formatLabels(labels))
|
|
98
|
-
.replace('{instructions}', instructions)
|
|
99
|
-
.replace('{record}', formatRecord(record));
|
|
100
|
-
const { parsed } = await askOpenAISafe(prompt, model, categorySchema);
|
|
101
|
-
if (!parsed) {
|
|
102
|
-
throw new Error('Failed to parse response from OpenAI');
|
|
97
|
+
schema() {
|
|
98
|
+
return this.labelSchema;
|
|
103
99
|
}
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Classifies multiple data records concurrently while preserving order.
|
|
108
|
-
*/
|
|
109
|
-
export function classifyBatch(records, labels, instructions = '', model = 'gpt-4.1-mini', maxConcurrency = 100) {
|
|
110
|
-
return mapParallel(records, maxConcurrency, record => classify(record, labels, instructions, model));
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Assigns one or more labels to a single data record using an LLM call.
|
|
114
|
-
*/
|
|
115
|
-
export async function label(record, labels, instructions = '', model = 'gpt-4.1-mini') {
|
|
116
|
-
if (record == null || Object.keys(record).length === 0) {
|
|
117
|
-
return null;
|
|
100
|
+
prompt(record) {
|
|
101
|
+
return this.promptTemplate.replace('{record}', formatRecord(record));
|
|
118
102
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
.replace('{labels}', formatLabels(labels))
|
|
122
|
-
.replace('{instructions}', instructions)
|
|
123
|
-
.replace('{record}', formatRecord(record));
|
|
124
|
-
const { parsed } = await askOpenAISafe(prompt, model, multiLabelSchema);
|
|
125
|
-
if (!parsed) {
|
|
126
|
-
throw new Error('Failed to parse response from OpenAI');
|
|
103
|
+
extractResult(parsed) {
|
|
104
|
+
return parsed.label;
|
|
127
105
|
}
|
|
128
|
-
return parsed.labels;
|
|
129
106
|
}
|
|
130
107
|
/**
|
|
131
|
-
*
|
|
108
|
+
* A tool that assigns one or more labels to records from provided options.
|
|
132
109
|
*/
|
|
133
|
-
export
|
|
134
|
-
|
|
110
|
+
export class Labeler extends Tool {
|
|
111
|
+
multiLabelSchema;
|
|
112
|
+
promptTemplate;
|
|
113
|
+
constructor(config, modelConfig) {
|
|
114
|
+
super(modelConfig);
|
|
115
|
+
const { labels, instructions = '' } = config;
|
|
116
|
+
this.multiLabelSchema = createMultiLabelSchema(labels);
|
|
117
|
+
this.promptTemplate = MULTI_LABEL_PROMPT_TEMPLATE
|
|
118
|
+
.replace('{labels}', formatLabels(labels))
|
|
119
|
+
.replace('{instructions}', instructions);
|
|
120
|
+
}
|
|
121
|
+
schema() {
|
|
122
|
+
return this.multiLabelSchema;
|
|
123
|
+
}
|
|
124
|
+
prompt(record) {
|
|
125
|
+
return this.promptTemplate.replace('{record}', formatRecord(record));
|
|
126
|
+
}
|
|
127
|
+
extractResult(parsed) {
|
|
128
|
+
return parsed.labels;
|
|
129
|
+
}
|
|
135
130
|
}
|
|
136
131
|
// =============================================================================
|
|
137
|
-
//
|
|
132
|
+
// LabelExtractor (extract classification labels from records)
|
|
138
133
|
// =============================================================================
|
|
139
134
|
const EXTRACT_LABELS_PROMPT = dedent(`
|
|
140
135
|
# Instructions
|
|
@@ -162,10 +157,6 @@ unless the user provides different instructions below.
|
|
|
162
157
|
|
|
163
158
|
{records}
|
|
164
159
|
`);
|
|
165
|
-
/**
|
|
166
|
-
* Schema for extracted labels - an array of label objects.
|
|
167
|
-
* Uses array format instead of record because OpenAI doesn't support propertyNames in JSON schema.
|
|
168
|
-
*/
|
|
169
160
|
const ExtractedLabelsSchema = z.object({
|
|
170
161
|
labels: z.array(z.object({
|
|
171
162
|
name: z.string(),
|
|
@@ -173,39 +164,36 @@ const ExtractedLabelsSchema = z.object({
|
|
|
173
164
|
}))
|
|
174
165
|
});
|
|
175
166
|
/**
|
|
176
|
-
*
|
|
167
|
+
* A tool that extracts classification labels from a set of records.
|
|
177
168
|
* Returns a Record<string, string> mapping label names to descriptions,
|
|
178
|
-
* which can be used directly with
|
|
169
|
+
* which can be used directly with Classifier and Labeler.
|
|
179
170
|
*/
|
|
180
|
-
export
|
|
181
|
-
|
|
182
|
-
|
|
171
|
+
export class LabelExtractor extends Tool {
|
|
172
|
+
maxSamples;
|
|
173
|
+
promptTemplate;
|
|
174
|
+
constructor(config = {}, modelConfig) {
|
|
175
|
+
super(modelConfig);
|
|
176
|
+
const { nLabels = 10, instructions = '', maxSamples = 500, language = 'The same language as the records' } = config;
|
|
177
|
+
this.maxSamples = maxSamples;
|
|
178
|
+
this.promptTemplate = EXTRACT_LABELS_PROMPT
|
|
179
|
+
.replace('{n_labels}', String(nLabels))
|
|
180
|
+
.replace('{instructions}', instructions)
|
|
181
|
+
.replace('{language}', language);
|
|
182
|
+
}
|
|
183
|
+
schema() {
|
|
184
|
+
return ExtractedLabelsSchema;
|
|
185
|
+
}
|
|
186
|
+
prompt(records) {
|
|
187
|
+
const sampledRecords = records.length > this.maxSamples
|
|
188
|
+
? records.slice(0, this.maxSamples)
|
|
189
|
+
: records;
|
|
190
|
+
const formattedRecords = formatRecordsAttrWise(sampledRecords);
|
|
191
|
+
return this.promptTemplate.replace('{records}', formattedRecords);
|
|
183
192
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
: records;
|
|
187
|
-
const formattedRecords = formatRecordsAttrWise(sampledRecords);
|
|
188
|
-
const prompt = EXTRACT_LABELS_PROMPT
|
|
189
|
-
.replace('{n_labels}', String(nLabels))
|
|
190
|
-
.replace('{instructions}', instructions)
|
|
191
|
-
.replace('{records}', formattedRecords)
|
|
192
|
-
.replace('{language}', language);
|
|
193
|
-
const { parsed, output_text, error } = await askOpenAISafe(prompt, model, ExtractedLabelsSchema, modelParams, maxRetries, 'return');
|
|
194
|
-
if (error != null) {
|
|
195
|
-
if (output_text == null) {
|
|
196
|
-
throw new Error('Failed to get response from OpenAI');
|
|
197
|
-
}
|
|
198
|
-
try {
|
|
199
|
-
const extracted = JSON.parse(output_text);
|
|
200
|
-
const { labels } = ExtractedLabelsSchema.parse(extracted);
|
|
201
|
-
return Object.fromEntries(labels.map(l => [l.name, l.description]));
|
|
202
|
-
}
|
|
203
|
-
catch (parseError) {
|
|
204
|
-
throw new Error(`Failed to parse response: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
|
|
205
|
-
}
|
|
193
|
+
isEmpty(records) {
|
|
194
|
+
return !records || records.length === 0;
|
|
206
195
|
}
|
|
207
|
-
|
|
208
|
-
|
|
196
|
+
extractResult(parsed) {
|
|
197
|
+
return Object.fromEntries(parsed.labels.map(l => [l.name, l.description]));
|
|
209
198
|
}
|
|
210
|
-
return Object.fromEntries(parsed.labels.map(l => [l.name, l.description]));
|
|
211
199
|
}
|
|
@@ -1,19 +1,30 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
import { type Entity } from '../schemas/entity.schema.js';
|
|
3
|
-
export declare const PROMPT: string;
|
|
1
|
+
import { Tool, type ModelConfig } from '../tool.js';
|
|
2
|
+
import { type Entity, type Entities } from '../schemas/entity.schema.js';
|
|
4
3
|
/**
|
|
5
|
-
*
|
|
6
|
-
* Extracts free-form entities from the given text (without enforced entity types).
|
|
4
|
+
* Configuration for the EntityExtractor tool.
|
|
7
5
|
*/
|
|
8
|
-
export
|
|
6
|
+
export interface EntityExtractorConfig {
|
|
7
|
+
/** Entity type definitions (string or map of type to description) */
|
|
8
|
+
entityDefinitions?: string | Record<string, string>;
|
|
9
|
+
/** Additional instructions */
|
|
10
|
+
instructions?: string;
|
|
11
|
+
}
|
|
9
12
|
/**
|
|
10
|
-
*
|
|
13
|
+
* A tool that extracts entities from text.
|
|
11
14
|
*/
|
|
12
|
-
export declare
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
export declare class EntityExtractor extends Tool<string | null, Entities, Array<Entity>> {
|
|
16
|
+
private readonly promptTemplate;
|
|
17
|
+
constructor(config: EntityExtractorConfig | undefined, modelConfig: ModelConfig);
|
|
18
|
+
protected schema(): import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodObject<{
|
|
19
|
+
entities: import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodArray<import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodObject<{
|
|
20
|
+
name: import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodString;
|
|
21
|
+
type: import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodString;
|
|
22
|
+
}, import("../../deps/jsr.io/@zod/zod/4.3.6/src/v4/core/schemas.js").$strip>>;
|
|
23
|
+
}, import("../../deps/jsr.io/@zod/zod/4.3.6/src/v4/core/schemas.js").$strip>;
|
|
24
|
+
protected prompt(text: string | null): string;
|
|
25
|
+
protected isEmpty(text: string | null): boolean;
|
|
26
|
+
protected extractResult(parsed: Entities): Array<Entity>;
|
|
27
|
+
}
|
|
17
28
|
export type { Entity, Entities } from '../schemas/entity.schema.js';
|
|
18
29
|
export { EntitySchema, EntitiesSchema } from '../schemas/entity.schema.js';
|
|
19
30
|
//# sourceMappingURL=entities.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entities.d.ts","sourceRoot":"","sources":["../../../src/src/tools/entities.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"entities.d.ts","sourceRoot":"","sources":["../../../src/src/tools/entities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAkB,KAAK,MAAM,EAAE,KAAK,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAkCzF;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACrC,qEAAqE;IACrE,iBAAiB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpD,8BAA8B;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,IAAI,CAAC,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAChF,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAE5B,MAAM,EAAE,qBAAqB,YAAK,EAAE,WAAW,EAAE,WAAW;cAgBrD,MAAM;;;;;;IAIzB,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;cAIjB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO;cAIrC,aAAa,CAAC,MAAM,EAAE,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC;CAGjE;AAGD,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { askOpenAISafe } from '../openai.js';
|
|
1
|
+
import { Tool } from '../tool.js';
|
|
3
2
|
import { EntitiesSchema } from '../schemas/entity.schema.js';
|
|
4
|
-
import { dedent } from '../utils.js';
|
|
5
|
-
|
|
3
|
+
import { dedent } from '../helpers/utils.js';
|
|
4
|
+
const PROMPT = dedent(`
|
|
6
5
|
# Instructions
|
|
7
6
|
|
|
8
7
|
From the Data Record section below extract entities in the following categories:
|
|
@@ -29,52 +28,33 @@ definitions include a "brand" category and a "product" category, the expected ou
|
|
|
29
28
|
{text}
|
|
30
29
|
`);
|
|
31
30
|
/**
|
|
32
|
-
*
|
|
33
|
-
* Extracts free-form entities from the given text (without enforced entity types).
|
|
31
|
+
* A tool that extracts entities from text.
|
|
34
32
|
*/
|
|
35
|
-
export
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
export class EntityExtractor extends Tool {
|
|
34
|
+
promptTemplate;
|
|
35
|
+
constructor(config = {}, modelConfig) {
|
|
36
|
+
super(modelConfig);
|
|
37
|
+
const { entityDefinitions = '', instructions = '' } = config;
|
|
38
|
+
const definitionsText = typeof entityDefinitions === 'string'
|
|
39
|
+
? entityDefinitions
|
|
40
|
+
: Object.entries(entityDefinitions)
|
|
41
|
+
.map(([type, description]) => `- ${type}: ${description}`)
|
|
42
|
+
.join('\n');
|
|
43
|
+
this.promptTemplate = PROMPT
|
|
44
|
+
.replace('{definitions}', definitionsText)
|
|
45
|
+
.replace('{instructions}', instructions);
|
|
43
46
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Extracts entities in pre-specified categories from a single text.
|
|
48
|
-
*/
|
|
49
|
-
export async function extractEntitiesFromText(text, entityDefinitions, instructions = '', model = 'gpt-4.1-mini', modelParams = {}) {
|
|
50
|
-
if (text === null) {
|
|
51
|
-
return [];
|
|
47
|
+
schema() {
|
|
48
|
+
return EntitiesSchema;
|
|
52
49
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
.
|
|
61
|
-
.replace('{instructions}', instructions);
|
|
62
|
-
const { parsed } = await askOpenAISafe(prompt, model, EntitiesSchema, modelParams);
|
|
63
|
-
if (!parsed) {
|
|
64
|
-
throw new Error('Failed to parse response from OpenAI');
|
|
50
|
+
prompt(text) {
|
|
51
|
+
return this.promptTemplate.replace('{text}', text ?? '');
|
|
52
|
+
}
|
|
53
|
+
isEmpty(text) {
|
|
54
|
+
return text == null || text.trim() === '';
|
|
55
|
+
}
|
|
56
|
+
extractResult(parsed) {
|
|
57
|
+
return parsed.entities;
|
|
65
58
|
}
|
|
66
|
-
return parsed.entities;
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Extracts entities from a batch of texts.
|
|
70
|
-
*/
|
|
71
|
-
export async function extractEntitiesBatch(texts, entityDefinitions, instructions = '', model = 'gpt-4.1-mini', maxConcurrency = 100, modelParams = {}) {
|
|
72
|
-
// Do this once outside the loop
|
|
73
|
-
const definitions = typeof entityDefinitions === 'string'
|
|
74
|
-
? entityDefinitions
|
|
75
|
-
: Object.entries(entityDefinitions)
|
|
76
|
-
.map(([type, description]) => `- ${type}: ${description}`)
|
|
77
|
-
.join('\n');
|
|
78
|
-
return mapParallel(texts, maxConcurrency, (text) => extractEntitiesFromText(text, definitions, instructions, model, modelParams));
|
|
79
59
|
}
|
|
80
60
|
export { EntitySchema, EntitiesSchema } from '../schemas/entity.schema.js';
|
package/esm/src/tools/funnel.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { mapParallel } from '../async.js';
|
|
2
|
-
import {
|
|
1
|
+
import { mapParallel } from '../helpers/async.js';
|
|
2
|
+
import { askLLMSafe } from '../llm.js';
|
|
3
3
|
import { FunnelWithExplanationSchema, SeedsSchema } from '../schemas/funnel.schema.js';
|
|
4
|
-
import { dedent } from '../utils.js';
|
|
4
|
+
import { dedent } from '../helpers/utils.js';
|
|
5
5
|
export { FunnelWithExplanationSchema };
|
|
6
6
|
/**
|
|
7
7
|
* Iterates over all categories in a funnel, yielding references to stage info and category objects.
|
|
@@ -294,9 +294,9 @@ export async function customizeFunnel(sector, language, userLanguage = null, cou
|
|
|
294
294
|
.replace('{language}', language)
|
|
295
295
|
.replace('{userLanguage}', userLanguage ?? language)
|
|
296
296
|
.replace('{funnel}', JSON.stringify(funnelData, null, 2));
|
|
297
|
-
const { parsed } = await
|
|
297
|
+
const { parsed } = await askLLMSafe({ prompt, model, schema: FunnelWithExplanationSchema });
|
|
298
298
|
if (!parsed) {
|
|
299
|
-
throw new Error('Failed to parse response from
|
|
299
|
+
throw new Error('Failed to parse response from LLM');
|
|
300
300
|
}
|
|
301
301
|
return parsed;
|
|
302
302
|
}
|
|
@@ -337,9 +337,9 @@ export async function generateSeedKeywords(stage, goal, category, sector, langua
|
|
|
337
337
|
.replace('{sector}', sector)
|
|
338
338
|
.replace('{market}', country)
|
|
339
339
|
.replace('{language}', language);
|
|
340
|
-
const { parsed } = await
|
|
340
|
+
const { parsed } = await askLLMSafe({ prompt, model, schema: SeedsSchema });
|
|
341
341
|
if (!parsed) {
|
|
342
|
-
throw new Error('Failed to parse seed keywords from
|
|
342
|
+
throw new Error('Failed to parse seed keywords from LLM');
|
|
343
343
|
}
|
|
344
344
|
return parsed.seeds;
|
|
345
345
|
}
|
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
* is either provided directly or inferred from the user's instructions using an LLM.
|
|
6
6
|
*/
|
|
7
7
|
import { z } from '../../deps/jsr.io/@zod/zod/4.3.6/src/index.js';
|
|
8
|
-
import { type
|
|
8
|
+
import { type LLMResponse, type ProviderParams } from '../llm.js';
|
|
9
|
+
import { BatchResponse } from '../response.js';
|
|
10
|
+
export type AIParams = ProviderParams;
|
|
9
11
|
/**
|
|
10
12
|
* Schema for the schema generation response.
|
|
11
13
|
*/
|
|
@@ -42,15 +44,18 @@ export interface GenericBatchOptions extends BaseLLMOptions {
|
|
|
42
44
|
records: Array<Record<string, unknown> | null>;
|
|
43
45
|
schema: Record<string, unknown>;
|
|
44
46
|
maxConcurrency?: number;
|
|
47
|
+
trackCost?: boolean;
|
|
45
48
|
}
|
|
46
49
|
/**
|
|
47
50
|
* Processes a single record using an LLM with a provided JSON schema.
|
|
51
|
+
* Returns both the result and usage information.
|
|
48
52
|
*/
|
|
49
|
-
export declare function generic<T = Record<string, unknown>>({ record, instructions, schema, model, modelParams, maxRetries }: GenericOptions): Promise<T | null
|
|
53
|
+
export declare function generic<T = Record<string, unknown>>({ record, instructions, schema, model, modelParams, maxRetries }: GenericOptions): Promise<LLMResponse<T | null>>;
|
|
50
54
|
/**
|
|
51
55
|
* Processes multiple records using an LLM with a provided JSON schema.
|
|
56
|
+
* Returns a BatchResponse with usage tracking.
|
|
52
57
|
*/
|
|
53
|
-
export declare function genericBatch<T = Record<string, unknown>>({ records, instructions, schema, model, modelParams, maxRetries, maxConcurrency }: GenericBatchOptions): Promise<
|
|
58
|
+
export declare function genericBatch<T = Record<string, unknown>>({ records, instructions, schema, model, modelParams, maxRetries, maxConcurrency, trackCost, }: GenericBatchOptions): Promise<BatchResponse<T | null>>;
|
|
54
59
|
/** Common options for auto functions */
|
|
55
60
|
interface BaseAutoOptions extends BaseLLMOptions {
|
|
56
61
|
schemaOrInstructions?: string | Record<string, unknown> | null;
|
|
@@ -78,11 +83,19 @@ export interface AutoResult<T> {
|
|
|
78
83
|
* 3. Processes the record using the generated schema
|
|
79
84
|
*/
|
|
80
85
|
export declare function auto<T = Record<string, unknown>>({ record, instructions, schemaOrInstructions, model, schemaModel, modelParams, maxRetries }: AutoOptions): Promise<AutoResult<T | null>>;
|
|
86
|
+
/**
|
|
87
|
+
* Result from autoBatch includes schema info and BatchResponse.
|
|
88
|
+
*/
|
|
89
|
+
export interface AutoBatchResult<T> {
|
|
90
|
+
data: BatchResponse<T | null>;
|
|
91
|
+
schema: Record<string, unknown>;
|
|
92
|
+
schemaReasoning: string;
|
|
93
|
+
}
|
|
81
94
|
/**
|
|
82
95
|
* Automatically generates a response schema and processes multiple records.
|
|
83
96
|
*
|
|
84
97
|
* The schema is generated once from the instructions, then used to process all records.
|
|
85
98
|
*/
|
|
86
|
-
export declare function autoBatch<T = Record<string, unknown>>({ records, instructions, schemaOrInstructions, model, schemaModel, modelParams, maxRetries, maxConcurrency }: AutoBatchOptions): Promise<
|
|
99
|
+
export declare function autoBatch<T = Record<string, unknown>>({ records, instructions, schemaOrInstructions, model, schemaModel, modelParams, maxRetries, maxConcurrency }: AutoBatchOptions): Promise<AutoBatchResult<T>>;
|
|
87
100
|
export {};
|
|
88
101
|
//# sourceMappingURL=generic.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generic.d.ts","sourceRoot":"","sources":["../../../src/src/tools/generic.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,+CAA+C,CAAC;AAElE,OAAO,
|
|
1
|
+
{"version":3,"file":"generic.d.ts","sourceRoot":"","sources":["../../../src/src/tools/generic.ts"],"names":[],"mappings":"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"}
|
package/esm/src/tools/generic.js
CHANGED
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
* is either provided directly or inferred from the user's instructions using an LLM.
|
|
6
6
|
*/
|
|
7
7
|
import { z } from '../../deps/jsr.io/@zod/zod/4.3.6/src/index.js';
|
|
8
|
-
import { mapParallel } from '../async.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
8
|
+
import { mapParallel } from '../helpers/async.js';
|
|
9
|
+
import { askLLMSafe } from '../llm.js';
|
|
10
|
+
import { BatchResponse } from '../response.js';
|
|
11
|
+
import { dedent } from '../helpers/utils.js';
|
|
11
12
|
// ============================================================================
|
|
12
13
|
// Prompts
|
|
13
14
|
// ============================================================================
|
|
@@ -108,7 +109,14 @@ export async function generateSchema({ instructions, model = 'gpt-4.1', modelPar
|
|
|
108
109
|
{ role: 'system', content: SCHEMA_GENERATION_SYSTEM_PROMPT },
|
|
109
110
|
{ role: 'user', content: SCHEMA_GENERATION_PROMPT.replace('{instructions}', instructions) }
|
|
110
111
|
];
|
|
111
|
-
const { parsed, error } = await
|
|
112
|
+
const { parsed, error } = await askLLMSafe({
|
|
113
|
+
prompt,
|
|
114
|
+
model,
|
|
115
|
+
schema: SchemaResponseSchema,
|
|
116
|
+
params: modelParams,
|
|
117
|
+
maxRetries,
|
|
118
|
+
onError: 'return',
|
|
119
|
+
});
|
|
112
120
|
if (error || !parsed) {
|
|
113
121
|
throw new Error(`Failed to generate schema: ${error?.message ?? 'Unknown error'}`);
|
|
114
122
|
}
|
|
@@ -120,7 +128,14 @@ export async function generateSchema({ instructions, model = 'gpt-4.1', modelPar
|
|
|
120
128
|
*/
|
|
121
129
|
async function convertToSchemaInstructions(instructions, model, modelParams, maxRetries) {
|
|
122
130
|
const prompt = SCHEMA_CONVERSION_PROMPT.replace('{instructions}', instructions);
|
|
123
|
-
const { parsed, error } = await
|
|
131
|
+
const { parsed, error } = await askLLMSafe({
|
|
132
|
+
prompt,
|
|
133
|
+
model,
|
|
134
|
+
schema: SchemaInstructionsSchema,
|
|
135
|
+
params: modelParams,
|
|
136
|
+
maxRetries,
|
|
137
|
+
onError: 'return',
|
|
138
|
+
});
|
|
124
139
|
if (error || !parsed) {
|
|
125
140
|
throw new Error(`Failed to convert instructions: ${error?.message ?? 'Unknown error'}`);
|
|
126
141
|
}
|
|
@@ -128,26 +143,36 @@ async function convertToSchemaInstructions(instructions, model, modelParams, max
|
|
|
128
143
|
}
|
|
129
144
|
/**
|
|
130
145
|
* Processes a single record using an LLM with a provided JSON schema.
|
|
146
|
+
* Returns both the result and usage information.
|
|
131
147
|
*/
|
|
132
148
|
export async function generic({ record, instructions, schema, model = 'gpt-4.1-mini', modelParams = {}, maxRetries = 3 }) {
|
|
133
149
|
if (record == null || Object.keys(record).length === 0) {
|
|
134
|
-
return null;
|
|
150
|
+
return { parsed: null, text: null, usage: null, error: null };
|
|
135
151
|
}
|
|
136
152
|
const zodSchema = z.fromJSONSchema(schema);
|
|
137
153
|
const prompt = GENERIC_PROMPT
|
|
138
154
|
.replace('{instructions}', instructions)
|
|
139
155
|
.replace('{record}', formatRecord(record));
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
156
|
+
const response = await askLLMSafe({
|
|
157
|
+
prompt,
|
|
158
|
+
model,
|
|
159
|
+
schema: zodSchema,
|
|
160
|
+
params: modelParams,
|
|
161
|
+
maxRetries,
|
|
162
|
+
onError: 'return',
|
|
163
|
+
});
|
|
164
|
+
if (response.error || response.parsed == null) {
|
|
165
|
+
throw new Error(`Failed to process record: ${response.error?.message ?? 'Unknown error'}`);
|
|
143
166
|
}
|
|
144
|
-
return parsed;
|
|
167
|
+
return { parsed: response.parsed, text: response.text, usage: response.usage, error: null };
|
|
145
168
|
}
|
|
146
169
|
/**
|
|
147
170
|
* Processes multiple records using an LLM with a provided JSON schema.
|
|
171
|
+
* Returns a BatchResponse with usage tracking.
|
|
148
172
|
*/
|
|
149
|
-
export function genericBatch({ records, instructions, schema, model = 'gpt-4.1-mini', modelParams = {}, maxRetries = 3, maxConcurrency = 100 }) {
|
|
150
|
-
|
|
173
|
+
export async function genericBatch({ records, instructions, schema, model = 'gpt-4.1-mini', modelParams = {}, maxRetries = 3, maxConcurrency = 100, trackCost = false, }) {
|
|
174
|
+
const responses = await mapParallel(records, maxConcurrency, (record) => generic({ record, instructions, schema, model, modelParams, maxRetries }));
|
|
175
|
+
return new BatchResponse(responses.map(r => r.parsed), trackCost ? responses.map(r => r.usage) : undefined, trackCost ? model : undefined);
|
|
151
176
|
}
|
|
152
177
|
/**
|
|
153
178
|
* Resolves a schema from various input types:
|
|
@@ -189,7 +214,7 @@ async function resolveSchema(schemaOrInstructions, taskInstructions, model, mode
|
|
|
189
214
|
*/
|
|
190
215
|
export async function auto({ record, instructions, schemaOrInstructions = null, model = 'gpt-4.1-mini', schemaModel = 'gpt-4.1', modelParams = {}, maxRetries = 3 }) {
|
|
191
216
|
const { schema, schemaReasoning } = await resolveSchema(schemaOrInstructions, instructions, schemaModel, modelParams, maxRetries);
|
|
192
|
-
const
|
|
217
|
+
const response = await generic({
|
|
193
218
|
record,
|
|
194
219
|
instructions,
|
|
195
220
|
schema,
|
|
@@ -197,7 +222,7 @@ export async function auto({ record, instructions, schemaOrInstructions = null,
|
|
|
197
222
|
modelParams,
|
|
198
223
|
maxRetries
|
|
199
224
|
});
|
|
200
|
-
return { data, schema, schemaReasoning };
|
|
225
|
+
return { data: response.parsed, schema, schemaReasoning };
|
|
201
226
|
}
|
|
202
227
|
/**
|
|
203
228
|
* Automatically generates a response schema and processes multiple records.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { mapParallel } from '../async.js';
|
|
2
|
-
import {
|
|
1
|
+
import { mapParallel } from '../helpers/async.js';
|
|
2
|
+
import { askLLMSafe } from '../llm.js';
|
|
3
3
|
import { buildBrandContext } from './brands.js';
|
|
4
4
|
import { KeywordsResponseSchema } from '../schemas/keyword.schema.js';
|
|
5
|
-
import { dedent } from '../utils.js';
|
|
5
|
+
import { dedent } from '../helpers/utils.js';
|
|
6
6
|
import { keywords as getGoogleAdsKeywords } from '../apis/googleAds/keywordPlanner.js';
|
|
7
7
|
export async function expandKeywords({ seedKeywords, url, urlAsExpandRelevanceContext, language = 'EN', countryISOCode, generateIdeasFromSeeds = false, includeSeedKeywords = false }) {
|
|
8
8
|
url = url?.trim();
|
|
@@ -163,9 +163,9 @@ export async function generateKeywords({ sector, market, brand, brandDomain, lan
|
|
|
163
163
|
.replaceAll('{brandsInfo}', brandsInfo || '')
|
|
164
164
|
.replaceAll('{personasInfo}', personasInfo || '')
|
|
165
165
|
.replaceAll('{funnelInfo}', funnelInfo || '');
|
|
166
|
-
const { parsed } = await
|
|
166
|
+
const { parsed } = await askLLMSafe({ prompt: content, model, schema: KeywordsResponseSchema });
|
|
167
167
|
if (!parsed) {
|
|
168
|
-
throw new Error('Failed to parse response from
|
|
168
|
+
throw new Error('Failed to parse response from LLM');
|
|
169
169
|
}
|
|
170
170
|
return parsed;
|
|
171
171
|
}
|