@far-world-labs/verblets 0.1.1 → 0.1.3
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/.cursor/launch.json +30 -0
- package/.cursor/settings.json +20 -0
- package/.github/workflows/branch-protection.yml +22 -0
- package/.github/workflows/ci.yml +120 -0
- package/.prettierrc +6 -0
- package/.release-it.json +4 -1
- package/.vscode/launch.json +31 -0
- package/AGENTS.md +220 -0
- package/DEVELOPING.md +105 -0
- package/README.md +254 -0
- package/eslint.config.js +80 -0
- package/package.json +29 -17
- package/scripts/generate-test/index.js +29 -3
- package/scripts/runner/index.js +26 -0
- package/scripts/simple-editor/index.js +29 -18
- package/scripts/summarize-files/index.js +28 -4
- package/src/chains/README.md +30 -0
- package/src/chains/anonymize/README.md +21 -0
- package/src/chains/anonymize/index.examples.js +75 -0
- package/src/chains/anonymize/index.js +121 -0
- package/src/chains/anonymize/index.spec.js +78 -0
- package/src/chains/bulk-central-tendency/index.examples.js +138 -0
- package/src/chains/bulk-central-tendency/index.js +91 -0
- package/src/chains/bulk-filter/README.md +21 -0
- package/src/chains/bulk-filter/index.examples.js +22 -0
- package/src/chains/bulk-filter/index.js +58 -0
- package/src/chains/bulk-filter/index.spec.js +38 -0
- package/src/chains/bulk-find/README.md +16 -0
- package/src/chains/bulk-find/index.examples.js +20 -0
- package/src/chains/bulk-find/index.js +30 -0
- package/src/chains/bulk-find/index.spec.js +26 -0
- package/src/chains/bulk-group/README.md +23 -0
- package/src/chains/bulk-group/index.examples.js +18 -0
- package/src/chains/bulk-group/index.js +34 -0
- package/src/chains/bulk-group/index.spec.js +41 -0
- package/src/chains/bulk-map/README.md +43 -0
- package/src/chains/bulk-map/index.examples.js +17 -0
- package/src/chains/bulk-map/index.js +86 -0
- package/src/chains/bulk-map/index.spec.js +44 -0
- package/src/chains/bulk-reduce/README.md +12 -0
- package/src/chains/bulk-reduce/index.examples.js +15 -0
- package/src/chains/bulk-reduce/index.js +13 -0
- package/src/chains/bulk-reduce/index.spec.js +25 -0
- package/src/chains/bulk-score/README.md +16 -0
- package/src/chains/bulk-score/bulk-score-result.json +18 -0
- package/src/chains/bulk-score/index.examples.js +22 -0
- package/src/chains/bulk-score/index.js +133 -0
- package/src/chains/bulk-score/index.spec.js +30 -0
- package/src/chains/category-samples/README.md +61 -0
- package/src/chains/category-samples/index.examples.js +103 -0
- package/src/chains/category-samples/index.js +134 -0
- package/src/chains/collect-terms/README.md +12 -0
- package/src/chains/collect-terms/index.examples.js +16 -0
- package/src/chains/collect-terms/index.js +44 -0
- package/src/chains/collect-terms/index.spec.js +25 -0
- package/src/chains/date/README.md +12 -0
- package/src/chains/date/index.examples.js +47 -0
- package/src/chains/date/index.js +74 -0
- package/src/chains/date/index.spec.js +62 -0
- package/src/chains/disambiguate/README.md +22 -0
- package/src/chains/disambiguate/disambiguate-meanings-result.json +16 -0
- package/src/chains/disambiguate/index.examples.js +18 -0
- package/src/chains/disambiguate/index.js +92 -0
- package/src/chains/disambiguate/index.spec.js +25 -0
- package/src/chains/dismantle/README.md +67 -0
- package/src/chains/dismantle/dismantle.examples.js +27 -0
- package/src/chains/dismantle/index.js +6 -17
- package/src/chains/dismantle/index.spec.js +1 -2
- package/src/chains/expect/README.md +171 -0
- package/src/chains/expect/index.examples.js +146 -0
- package/src/chains/expect/index.js +173 -0
- package/src/chains/expect/index.spec.js +324 -0
- package/src/chains/filter-ambiguous/README.md +11 -0
- package/src/chains/filter-ambiguous/index.examples.js +20 -0
- package/src/chains/filter-ambiguous/index.js +49 -0
- package/src/chains/filter-ambiguous/index.spec.js +31 -0
- package/src/chains/glossary/README.md +19 -0
- package/src/chains/glossary/index.examples.js +386 -0
- package/src/chains/glossary/index.js +75 -0
- package/src/chains/glossary/index.spec.js +19 -0
- package/src/chains/intersections/README.md +152 -0
- package/src/chains/intersections/index.examples.js +279 -0
- package/src/chains/intersections/index.js +366 -0
- package/src/chains/intersections/intersection-result.json +38 -0
- package/src/chains/list/index.examples.js +12 -16
- package/src/chains/list/index.js +106 -53
- package/src/chains/list/index.spec.js +8 -9
- package/src/chains/list/list-result.json +16 -0
- package/src/chains/llm-logger/README.md +208 -0
- package/src/chains/llm-logger/index.js +205 -0
- package/src/chains/llm-logger/index.spec.js +330 -0
- package/src/chains/questions/index.examples.js +2 -1
- package/src/chains/questions/index.js +14 -15
- package/src/chains/scan-js/index.js +6 -9
- package/src/chains/set-interval/README.md +81 -0
- package/src/chains/set-interval/index.examples.js +36 -0
- package/src/chains/set-interval/index.js +131 -0
- package/src/chains/set-interval/index.spec.js +70 -0
- package/src/chains/socratic/README.md +17 -0
- package/src/chains/socratic/index.js +64 -0
- package/src/chains/socratic/index.spec.js +24 -0
- package/src/chains/sort/index.examples.js +3 -7
- package/src/chains/sort/index.js +65 -15
- package/src/chains/sort/index.spec.js +5 -8
- package/src/chains/sort/sort-result.json +16 -0
- package/src/chains/summary-map/README.md +9 -1
- package/src/chains/summary-map/index.examples.js +9 -2
- package/src/chains/summary-map/index.js +43 -25
- package/src/chains/summary-map/index.spec.js +78 -3
- package/src/chains/test/index.js +9 -13
- package/src/chains/test-advice/index.js +4 -5
- package/src/chains/themes/README.md +20 -0
- package/src/chains/themes/index.examples.js +17 -0
- package/src/chains/themes/index.js +28 -0
- package/src/chains/themes/index.spec.js +19 -0
- package/src/chains/veiled-variants/index.examples.js +18 -0
- package/src/chains/veiled-variants/index.js +107 -0
- package/src/chains/veiled-variants/index.spec.js +40 -0
- package/src/constants/common.js +0 -2
- package/src/constants/models.js +172 -0
- package/src/index.js +178 -18
- package/src/json-schemas/README.md +13 -0
- package/src/json-schemas/index.js +8 -14
- package/src/json-schemas/schema-dot-org-photograph.json +11 -5
- package/src/json-schemas/schema-dot-org-place.json +78 -5
- package/src/lib/README.md +26 -0
- package/src/lib/bulk-filter/README.md +22 -0
- package/src/lib/bulk-filter/index.examples.js +27 -0
- package/src/lib/bulk-filter/index.js +63 -0
- package/src/lib/bulk-filter/index.spec.js +38 -0
- package/src/lib/bulk-find/README.md +18 -0
- package/src/lib/bulk-find/index.examples.js +19 -0
- package/src/lib/bulk-find/index.js +30 -0
- package/src/lib/bulk-find/index.spec.js +41 -0
- package/src/lib/chatgpt/index.js +63 -43
- package/src/lib/combinations/index.js +30 -0
- package/src/lib/combinations/index.spec.js +23 -0
- package/src/lib/functional/index.js +28 -0
- package/src/lib/logger-service/index.js +32 -0
- package/src/lib/parse-js-parts/index.js +9 -21
- package/src/lib/parse-llm-list/README.md +39 -0
- package/src/lib/parse-llm-list/index.js +54 -0
- package/src/lib/parse-llm-list/index.spec.js +59 -0
- package/src/lib/path-aliases/index.js +1 -3
- package/src/lib/path-aliases/index.spec.js +2 -8
- package/src/lib/pave/index.js +4 -4
- package/src/lib/pave/index.spec.js +6 -3
- package/src/lib/prompt-cache/index.js +14 -10
- package/src/lib/retry/index.js +11 -8
- package/src/lib/ring-buffer/README.md +460 -0
- package/src/lib/ring-buffer/index.js +1074 -0
- package/src/lib/search-best-first/city-walk.spec.js +37 -0
- package/src/lib/search-best-first/index.js +42 -11
- package/src/lib/search-best-first/index.spec.js +35 -0
- package/src/lib/search-js-files/index.js +44 -47
- package/src/lib/search-js-files/scan-file.js +10 -21
- package/src/lib/shorten-text/index.js +2 -7
- package/src/lib/shorten-text/index.spec.js +3 -3
- package/src/lib/strip-response/index.js +2 -7
- package/src/lib/template-replace/index.js +23 -0
- package/src/lib/template-replace/index.spec.js +60 -0
- package/src/lib/to-date/index.js +11 -0
- package/src/lib/to-number/index.js +1 -1
- package/src/lib/transcribe/index.js +26 -9
- package/src/prompts/README.md +3 -1
- package/src/prompts/as-object-with-schema.js +3 -8
- package/src/prompts/as-schema-org-text.js +10 -2
- package/src/prompts/code-features.js +1 -5
- package/src/prompts/constants.js +27 -27
- package/src/prompts/generate-collection.js +1 -1
- package/src/prompts/intent.js +16 -22
- package/src/prompts/select-from-threshold.js +1 -2
- package/src/prompts/sort.js +4 -8
- package/src/prompts/style.js +4 -7
- package/src/prompts/wrap-list.js +1 -4
- package/src/services/llm-model/global-overrides.spec.js +432 -0
- package/src/services/llm-model/index.js +234 -40
- package/src/services/llm-model/model.js +2 -2
- package/src/services/llm-model/negotiate.spec.js +447 -0
- package/src/services/redis/index.js +70 -7
- package/src/test/setup.js +20 -0
- package/src/verblets/README.md +26 -0
- package/src/verblets/auto/index.examples.js +12 -9
- package/src/verblets/auto/index.js +10 -10
- package/src/verblets/auto/index.spec.js +4 -6
- package/src/verblets/bool/README.md +36 -0
- package/src/verblets/bool/index.examples.js +53 -1
- package/src/verblets/bool/index.js +6 -9
- package/src/verblets/bool/index.spec.js +1 -3
- package/src/verblets/central-tendency/README.md +166 -0
- package/src/verblets/central-tendency/central-tendency-result.json +24 -0
- package/src/verblets/central-tendency/index.examples.js +196 -0
- package/src/verblets/central-tendency/index.js +171 -0
- package/src/verblets/central-tendency/index.spec.js +148 -0
- package/src/verblets/enum/index.examples.js +1 -4
- package/src/verblets/enum/index.js +7 -4
- package/src/verblets/expect/README.md +64 -0
- package/src/verblets/expect/index.examples.js +109 -0
- package/src/verblets/expect/index.js +75 -0
- package/src/verblets/expect/index.spec.js +127 -0
- package/src/verblets/intent/index.examples.js +95 -7
- package/src/verblets/intent/index.js +56 -68
- package/src/verblets/intersection/README.md +16 -0
- package/src/verblets/intersection/index.examples.js +89 -0
- package/src/verblets/intersection/index.js +84 -0
- package/src/verblets/intersection/index.spec.js +60 -0
- package/src/verblets/intersection/intersection-result.json +16 -0
- package/src/verblets/list-expand/README.md +10 -0
- package/src/verblets/list-expand/index.examples.js +14 -0
- package/src/verblets/list-expand/index.js +104 -0
- package/src/verblets/list-expand/index.spec.js +18 -0
- package/src/verblets/list-expand/list-expand-result.json +16 -0
- package/src/verblets/list-filter/README.md +22 -0
- package/src/verblets/list-filter/index.examples.js +26 -0
- package/src/verblets/list-filter/index.js +18 -0
- package/src/verblets/list-filter/index.spec.js +19 -0
- package/src/verblets/list-find/README.md +11 -0
- package/src/verblets/list-find/index.examples.js +15 -0
- package/src/verblets/list-find/index.js +17 -0
- package/src/verblets/list-find/index.spec.js +19 -0
- package/src/verblets/list-group/README.md +16 -0
- package/src/verblets/list-group/index.examples.js +16 -0
- package/src/verblets/list-group/index.js +112 -0
- package/src/verblets/list-group/index.spec.js +35 -0
- package/src/verblets/list-group/list-group-result.json +16 -0
- package/src/verblets/list-map/README.md +11 -0
- package/src/verblets/list-map/index.examples.js +15 -0
- package/src/verblets/list-map/index.js +26 -0
- package/src/verblets/list-map/index.spec.js +17 -0
- package/src/verblets/list-reduce/README.md +10 -0
- package/src/verblets/list-reduce/index.examples.js +14 -0
- package/src/verblets/list-reduce/index.js +21 -0
- package/src/verblets/list-reduce/index.spec.js +27 -0
- package/src/verblets/list-reduce/index.spec.jsx +27 -0
- package/src/verblets/name/README.md +15 -0
- package/src/verblets/name/index.examples.js +28 -0
- package/src/verblets/name/index.js +19 -0
- package/src/verblets/name/index.spec.js +33 -0
- package/src/verblets/name-similar-to/README.md +26 -0
- package/src/verblets/name-similar-to/index.examples.js +18 -0
- package/src/verblets/name-similar-to/index.js +20 -0
- package/src/verblets/name-similar-to/index.spec.js +13 -0
- package/src/verblets/number/index.examples.js +173 -7
- package/src/verblets/number/index.js +5 -2
- package/src/verblets/number/index.spec.js +1 -3
- package/src/verblets/number-with-units/index.examples.js +5 -1
- package/src/verblets/number-with-units/index.js +74 -9
- package/src/verblets/number-with-units/number-with-units-result.json +23 -0
- package/src/verblets/schema-org/index.examples.js +2 -7
- package/src/verblets/schema-org/index.js +32 -3
- package/src/verblets/sentiment/README.md +10 -0
- package/src/verblets/sentiment/index.examples.js +20 -0
- package/src/verblets/sentiment/index.js +9 -0
- package/src/verblets/sentiment/index.spec.js +20 -0
- package/src/verblets/to-object/index.js +10 -15
- package/src/verblets/to-object/index.spec.js +1 -4
- package/.eslintrc.json +0 -42
- package/docs/README.md +0 -41
- package/docs/babel.config.js +0 -3
- package/docs/blog/2019-05-28-first-blog-post.md +0 -12
- package/docs/blog/2019-05-29-long-blog-post.md +0 -44
- package/docs/blog/2021-08-01-mdx-blog-post.mdx +0 -20
- package/docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg +0 -0
- package/docs/blog/2021-08-26-welcome/index.md +0 -25
- package/docs/blog/authors.yml +0 -17
- package/docs/docs/api/bool.md +0 -74
- package/docs/docs/api/search.md +0 -51
- package/docs/docs/intro.md +0 -47
- package/docs/docs/tutorial-basics/_category_.json +0 -8
- package/docs/docs/tutorial-basics/congratulations.md +0 -23
- package/docs/docs/tutorial-basics/create-a-blog-post.md +0 -34
- package/docs/docs/tutorial-basics/create-a-document.md +0 -57
- package/docs/docs/tutorial-basics/create-a-page.md +0 -43
- package/docs/docs/tutorial-basics/deploy-your-site.md +0 -31
- package/docs/docs/tutorial-basics/markdown-features.mdx +0 -152
- package/docs/docs/tutorial-extras/_category_.json +0 -7
- package/docs/docs/tutorial-extras/img/docsVersionDropdown.png +0 -0
- package/docs/docs/tutorial-extras/img/localeDropdown.png +0 -0
- package/docs/docs/tutorial-extras/manage-docs-versions.md +0 -55
- package/docs/docs/tutorial-extras/translate-your-site.md +0 -88
- package/docs/docusaurus.config.js +0 -120
- package/docs/package.json +0 -44
- package/docs/sidebars.js +0 -31
- package/docs/src/components/HomepageFeatures/index.js +0 -61
- package/docs/src/components/HomepageFeatures/styles.module.css +0 -11
- package/docs/src/css/custom.css +0 -30
- package/docs/src/pages/index.js +0 -43
- package/docs/src/pages/index.module.css +0 -23
- package/docs/src/pages/markdown-page.md +0 -7
- package/docs/static/.nojekyll +0 -0
- package/docs/static/img/docusaurus-social-card.jpg +0 -0
- package/docs/static/img/docusaurus.png +0 -0
- package/docs/static/img/favicon.ico +0 -0
- package/docs/static/img/logo.svg +0 -1
- package/docs/static/img/undraw_docusaurus_mountain.svg +0 -171
- package/docs/static/img/undraw_docusaurus_react.svg +0 -170
- package/docs/static/img/undraw_docusaurus_tree.svg +0 -40
- package/src/constants/openai.js +0 -65
- /package/{.vite.config.examples.js → .vitest.config.examples.js} +0 -0
- /package/{.vite.config.js → .vitest.config.js} +0 -0
|
@@ -27,21 +27,15 @@ describe('List verblet', () => {
|
|
|
27
27
|
examples.forEach((example) => {
|
|
28
28
|
let jsonSchemaDisplay = '';
|
|
29
29
|
if (example.inputs.jsonSchemaQuery) {
|
|
30
|
-
const jsonSchemaEllipsis =
|
|
31
|
-
|
|
32
|
-
jsonSchemaDisplay = ` - ${example.inputs.jsonSchemaQuery.slice(
|
|
33
|
-
0,
|
|
34
|
-
10
|
|
35
|
-
)}${jsonSchemaEllipsis}`;
|
|
30
|
+
const jsonSchemaEllipsis = example.inputs.jsonSchemaQuery.length > 10 ? '...' : '';
|
|
31
|
+
jsonSchemaDisplay = ` - ${example.inputs.jsonSchemaQuery.slice(0, 10)}${jsonSchemaEllipsis}`;
|
|
36
32
|
}
|
|
37
33
|
it(
|
|
38
|
-
`${example.inputs.
|
|
34
|
+
`${example.inputs.description}${jsonSchemaDisplay}`,
|
|
39
35
|
async () => {
|
|
40
36
|
let schema;
|
|
41
37
|
if (example.inputs.jsonSchemaQuery) {
|
|
42
|
-
schema = await toObject(
|
|
43
|
-
await chatGPT(asJSONSchema(example.inputs.schemaQuery))
|
|
44
|
-
);
|
|
38
|
+
schema = await toObject(await chatGPT(asJSONSchema(example.inputs.jsonSchemaQuery)));
|
|
45
39
|
}
|
|
46
40
|
|
|
47
41
|
const result = await list(example.inputs.description, {
|
|
@@ -53,16 +47,18 @@ describe('List verblet', () => {
|
|
|
53
47
|
}
|
|
54
48
|
|
|
55
49
|
if (example.want.listContains) {
|
|
56
|
-
expect(
|
|
57
|
-
result.some((item) => item.includes(example.want.listContains))
|
|
58
|
-
).equals(true);
|
|
50
|
+
expect(result.some((item) => item.includes(example.want.listContains))).equals(true);
|
|
59
51
|
}
|
|
60
52
|
|
|
61
53
|
if (example.want.listModelContains) {
|
|
62
54
|
expect(
|
|
63
|
-
result.some((item) =>
|
|
64
|
-
|
|
65
|
-
|
|
55
|
+
result.some((item) => {
|
|
56
|
+
// Handle both string and object results
|
|
57
|
+
if (typeof item === 'string') {
|
|
58
|
+
return item.includes(example.want.listModelContains);
|
|
59
|
+
}
|
|
60
|
+
return item.model?.includes(example.want.listModelContains);
|
|
61
|
+
})
|
|
66
62
|
).equals(true);
|
|
67
63
|
}
|
|
68
64
|
},
|
package/src/chains/list/index.js
CHANGED
|
@@ -1,16 +1,58 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import {
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { operationTimeoutMultiplier } from '../../constants/models.js';
|
|
4
5
|
import chatGPT from '../../lib/chatgpt/index.js';
|
|
5
6
|
import {
|
|
6
|
-
constants as promptConstants,
|
|
7
7
|
asObjectWithSchema as asObjectWithSchemaPrompt,
|
|
8
8
|
generateList as generateListPrompt,
|
|
9
|
+
constants as promptConstants,
|
|
9
10
|
} from '../../prompts/index.js';
|
|
10
11
|
import modelService from '../../services/llm-model/index.js';
|
|
11
|
-
import toObject from '../../verblets/to-object/index.js';
|
|
12
12
|
|
|
13
|
-
const { onlyJSON, contentIsTransformationSource } = promptConstants;
|
|
13
|
+
const { onlyJSON, contentIsTransformationSource, onlyJSONArray } = promptConstants;
|
|
14
|
+
|
|
15
|
+
// Get the directory of this module
|
|
16
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
17
|
+
const __dirname = path.dirname(__filename);
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Load the JSON schema for list results
|
|
21
|
+
* @returns {Promise<Object>} JSON schema for validation
|
|
22
|
+
*/
|
|
23
|
+
async function getListSchema() {
|
|
24
|
+
const schemaPath = path.join(__dirname, 'list-result.json');
|
|
25
|
+
return JSON.parse(await fs.readFile(schemaPath, 'utf8'));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Create model options for structured outputs
|
|
30
|
+
* @param {string|Object} llm - LLM model name or configuration object
|
|
31
|
+
* @returns {Promise<Object>} Model options for chatGPT
|
|
32
|
+
*/
|
|
33
|
+
async function createModelOptions(llm = 'fastGoodCheap') {
|
|
34
|
+
const schema = await getListSchema();
|
|
35
|
+
|
|
36
|
+
const responseFormat = {
|
|
37
|
+
type: 'json_schema',
|
|
38
|
+
json_schema: {
|
|
39
|
+
name: 'list_result',
|
|
40
|
+
schema,
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
if (typeof llm === 'string') {
|
|
45
|
+
return {
|
|
46
|
+
modelName: llm,
|
|
47
|
+
response_format: responseFormat,
|
|
48
|
+
};
|
|
49
|
+
} else {
|
|
50
|
+
return {
|
|
51
|
+
...llm,
|
|
52
|
+
response_format: responseFormat,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
14
56
|
|
|
15
57
|
const outputTransformPrompt = (result, schema) => {
|
|
16
58
|
return `${contentIsTransformationSource} ${result}
|
|
@@ -28,22 +70,21 @@ const shouldStopDefault = ({ queryCount, startTime } = {}) => {
|
|
|
28
70
|
return (
|
|
29
71
|
queryCount > 5 ||
|
|
30
72
|
new Date() - startTime >
|
|
31
|
-
operationTimeoutMultiplier *
|
|
32
|
-
modelService.getBestAvailableModel().requestTimeout
|
|
73
|
+
operationTimeoutMultiplier * modelService.getBestPublicModel().requestTimeout
|
|
33
74
|
);
|
|
34
75
|
};
|
|
35
76
|
|
|
36
|
-
export const generateList = async function* generateListGenerator(
|
|
37
|
-
text,
|
|
38
|
-
options = {}
|
|
39
|
-
) {
|
|
77
|
+
export const generateList = async function* generateListGenerator(text, options = {}) {
|
|
40
78
|
const resultsAll = [];
|
|
41
79
|
const resultsAllMap = {};
|
|
42
80
|
let isDone = false;
|
|
43
81
|
const {
|
|
44
82
|
shouldSkip = shouldSkipDefault,
|
|
45
83
|
shouldStop = shouldStopDefault,
|
|
46
|
-
model =
|
|
84
|
+
model = 'fastGoodCheap',
|
|
85
|
+
// eslint-disable-next-line no-unused-vars
|
|
86
|
+
_schema,
|
|
87
|
+
...passThroughOptions
|
|
47
88
|
} = options;
|
|
48
89
|
|
|
49
90
|
const startTime = new Date();
|
|
@@ -55,26 +96,27 @@ export const generateList = async function* generateListGenerator(
|
|
|
55
96
|
existing: resultsAll,
|
|
56
97
|
});
|
|
57
98
|
|
|
58
|
-
const budget = model.budgetTokens(listPrompt);
|
|
59
|
-
|
|
60
99
|
let resultsNew = [];
|
|
61
100
|
try {
|
|
101
|
+
const modelOptions = await createModelOptions(model);
|
|
102
|
+
// eslint-disable-next-line no-await-in-loop
|
|
62
103
|
const results = await chatGPT(listPrompt, {
|
|
63
|
-
modelOptions
|
|
64
|
-
|
|
65
|
-
},
|
|
66
|
-
...options,
|
|
104
|
+
modelOptions,
|
|
105
|
+
...passThroughOptions,
|
|
67
106
|
});
|
|
68
107
|
|
|
69
|
-
//
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
108
|
+
// With structured outputs, response should already be parsed and validated
|
|
109
|
+
const parsed = typeof results === 'string' ? JSON.parse(results) : results;
|
|
110
|
+
// Extract items from the object structure
|
|
111
|
+
const resultArray = parsed?.items || parsed;
|
|
112
|
+
resultsNew = Array.isArray(resultArray) ? resultArray.filter(Boolean) : [];
|
|
73
113
|
} catch (error) {
|
|
74
114
|
if (/The operation was aborted/.test(error.message)) {
|
|
115
|
+
// eslint-disable-next-line no-console
|
|
75
116
|
console.error('Generate list [error]: Aborted');
|
|
76
117
|
resultsNew = []; // continue
|
|
77
118
|
} else {
|
|
119
|
+
// eslint-disable-next-line no-console
|
|
78
120
|
console.error(
|
|
79
121
|
`Generate list [error]: ${error.message}`,
|
|
80
122
|
listPrompt.slice(0, 100).replace('\n', '\\n')
|
|
@@ -84,9 +126,7 @@ export const generateList = async function* generateListGenerator(
|
|
|
84
126
|
}
|
|
85
127
|
}
|
|
86
128
|
|
|
87
|
-
const resultsNewUnique = resultsNew.filter(
|
|
88
|
-
(item) => !(item in resultsAllMap)
|
|
89
|
-
);
|
|
129
|
+
const resultsNewUnique = resultsNew.filter((item) => !(item in resultsAllMap));
|
|
90
130
|
|
|
91
131
|
queryCount += 1;
|
|
92
132
|
|
|
@@ -99,11 +139,13 @@ export const generateList = async function* generateListGenerator(
|
|
|
99
139
|
startTime,
|
|
100
140
|
};
|
|
101
141
|
|
|
142
|
+
// eslint-disable-next-line no-await-in-loop
|
|
102
143
|
if (await shouldStop(perResultControlFactors)) {
|
|
103
144
|
isDone = true;
|
|
104
145
|
break;
|
|
105
146
|
}
|
|
106
147
|
|
|
148
|
+
// eslint-disable-next-line no-await-in-loop
|
|
107
149
|
if (!(await shouldSkip(perResultControlFactors))) {
|
|
108
150
|
resultsAllMap[result] = true;
|
|
109
151
|
resultsAll.push(result);
|
|
@@ -123,39 +165,50 @@ export const generateList = async function* generateListGenerator(
|
|
|
123
165
|
startTime,
|
|
124
166
|
};
|
|
125
167
|
|
|
168
|
+
// eslint-disable-next-line no-await-in-loop
|
|
126
169
|
if (await shouldStop(perQueryControlFactors)) {
|
|
127
170
|
isDone = true;
|
|
128
171
|
}
|
|
129
172
|
}
|
|
130
173
|
};
|
|
131
174
|
|
|
132
|
-
export default async (
|
|
133
|
-
const
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
175
|
+
export default async function list(prompt, config = {}) {
|
|
176
|
+
const { llm, schema, ...options } = config;
|
|
177
|
+
const fullPrompt = `${prompt}\n\n${onlyJSONArray}`;
|
|
178
|
+
|
|
179
|
+
const modelOptions = await createModelOptions(llm);
|
|
180
|
+
const response = await chatGPT(fullPrompt, {
|
|
181
|
+
modelOptions,
|
|
182
|
+
...options,
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// With structured outputs, response should already be parsed and validated
|
|
186
|
+
const result = typeof response === 'string' ? JSON.parse(response) : response;
|
|
187
|
+
// Extract items from the object structure
|
|
188
|
+
const resultArray = result?.items || result;
|
|
189
|
+
const items = Array.isArray(resultArray) ? resultArray : [];
|
|
190
|
+
|
|
191
|
+
// If schema is provided, transform each item to match the schema
|
|
192
|
+
if (schema && items.length > 0) {
|
|
193
|
+
const transformedItems = [];
|
|
194
|
+
for (const item of items) {
|
|
195
|
+
const transformPrompt = outputTransformPrompt(item, schema);
|
|
196
|
+
const transformResponse = await chatGPT(transformPrompt, {
|
|
197
|
+
modelOptions: {
|
|
198
|
+
...llm,
|
|
199
|
+
},
|
|
153
200
|
...options,
|
|
154
201
|
});
|
|
202
|
+
try {
|
|
203
|
+
const transformedItem = JSON.parse(transformResponse);
|
|
204
|
+
transformedItems.push(transformedItem);
|
|
205
|
+
} catch {
|
|
206
|
+
// If transformation fails, keep the original item
|
|
207
|
+
transformedItems.push(item);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return transformedItems;
|
|
211
|
+
}
|
|
155
212
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
);
|
|
159
|
-
|
|
160
|
-
return resultObjects;
|
|
161
|
-
};
|
|
213
|
+
return items;
|
|
214
|
+
}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import { describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { dirname, join } from 'path';
|
|
3
5
|
|
|
4
6
|
import toObject from '../../verblets/to-object/index.js';
|
|
5
7
|
import list from './index.js';
|
|
6
8
|
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = dirname(__filename);
|
|
11
|
+
|
|
7
12
|
const loadSchema = async () => {
|
|
8
|
-
const file = (
|
|
9
|
-
await fs.readFile('./src/json-schemas/cars-test.json')
|
|
10
|
-
).toString();
|
|
13
|
+
const file = (await fs.readFile(join(__dirname, '../../json-schemas/cars-test.json'))).toString();
|
|
11
14
|
|
|
12
15
|
return toObject(file);
|
|
13
16
|
};
|
|
@@ -53,15 +56,11 @@ describe('List verblet', () => {
|
|
|
53
56
|
});
|
|
54
57
|
|
|
55
58
|
if (example.want.listContains) {
|
|
56
|
-
expect(
|
|
57
|
-
result.some((item) => example.want.listContains.test(item))
|
|
58
|
-
).equals(true);
|
|
59
|
+
expect(result.some((item) => example.want.listContains.test(item))).equals(true);
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
if (example.want.listModelContains) {
|
|
62
|
-
expect(
|
|
63
|
-
result.some((item) => example.want.listModelContains.test(item.model))
|
|
64
|
-
).equals(true);
|
|
63
|
+
expect(result.some((item) => example.want.listModelContains.test(item.model))).equals(true);
|
|
65
64
|
}
|
|
66
65
|
});
|
|
67
66
|
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"properties": {
|
|
5
|
+
"items": {
|
|
6
|
+
"type": "array",
|
|
7
|
+
"description": "Array of generated list items",
|
|
8
|
+
"items": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"description": "A generated list item"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"required": ["items"],
|
|
15
|
+
"additionalProperties": false
|
|
16
|
+
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# LLM Logger
|
|
2
|
+
|
|
3
|
+
The LLM Logger is an **advanced logger implementation** that you can use with the global logger service. It provides sophisticated features like ring buffers, multi-lane processing, and file context tracking.
|
|
4
|
+
|
|
5
|
+
## ⚠️ Important: Not Used Automatically
|
|
6
|
+
|
|
7
|
+
The LLM Logger is **NOT automatically used** by the application. You must:
|
|
8
|
+
|
|
9
|
+
1. **Create an LLM Logger instance** using `createLLMLogger()`
|
|
10
|
+
2. **Set it as the global logger** using `setLogger()`
|
|
11
|
+
|
|
12
|
+
The application uses a noop logger by default and will be silent unless you explicitly configure logging.
|
|
13
|
+
|
|
14
|
+
## Basic Usage
|
|
15
|
+
|
|
16
|
+
```javascript
|
|
17
|
+
import { setLogger } from 'verblets/lib/logger-service';
|
|
18
|
+
import { createLLMLogger, createConsoleWriter } from 'verblets/chains/llm-logger';
|
|
19
|
+
|
|
20
|
+
// Create an LLM logger instance
|
|
21
|
+
const llmLogger = createLLMLogger({
|
|
22
|
+
ringBufferSize: 1000,
|
|
23
|
+
lanes: [
|
|
24
|
+
{
|
|
25
|
+
laneId: 'console',
|
|
26
|
+
writer: createConsoleWriter('[LOG] ')
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Set it as the global logger
|
|
32
|
+
setLogger(llmLogger);
|
|
33
|
+
|
|
34
|
+
// Now all verblets and chains will use this logger
|
|
35
|
+
import { bulkMap } from 'verblets';
|
|
36
|
+
const result = await bulkMap(items, processor); // Will log using LLM logger
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Features
|
|
40
|
+
|
|
41
|
+
- **Ring Buffer**: Memory-efficient circular buffer for log storage
|
|
42
|
+
- **Multi-lane Processing**: Route logs to different outputs based on filters
|
|
43
|
+
- **File Context Tracking**: Automatically captures file and line information
|
|
44
|
+
- **Batch Processing**: Efficient batching of log outputs
|
|
45
|
+
- **Advanced Filtering**: Custom filter functions for sophisticated log routing
|
|
46
|
+
|
|
47
|
+
## Configuration
|
|
48
|
+
|
|
49
|
+
### Basic Configuration
|
|
50
|
+
|
|
51
|
+
```javascript
|
|
52
|
+
import { createLLMLogger, createConsoleWriter } from 'verblets/chains/llm-logger';
|
|
53
|
+
|
|
54
|
+
const logger = createLLMLogger({
|
|
55
|
+
ringBufferSize: 1000, // Size of the ring buffer
|
|
56
|
+
flushInterval: 100, // Flush interval in milliseconds
|
|
57
|
+
lanes: [ // Lane configurations
|
|
58
|
+
{
|
|
59
|
+
laneId: 'all',
|
|
60
|
+
writer: createConsoleWriter()
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Multi-lane Configuration
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
const logger = createLLMLogger({
|
|
70
|
+
ringBufferSize: 5000,
|
|
71
|
+
lanes: [
|
|
72
|
+
{
|
|
73
|
+
laneId: 'errors',
|
|
74
|
+
filters: (log) => log.meta.get('level') === 'error',
|
|
75
|
+
writer: createConsoleWriter('[ERROR] ')
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
laneId: 'structured',
|
|
79
|
+
filters: (log) => typeof log.raw === 'object',
|
|
80
|
+
writer: createConsoleWriter('[STRUCT] ')
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
laneId: 'all',
|
|
84
|
+
writer: createFileWriter('/tmp/all.log')
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Lane Configuration
|
|
91
|
+
|
|
92
|
+
Each lane can have:
|
|
93
|
+
|
|
94
|
+
- **`laneId`**: Unique identifier for the lane
|
|
95
|
+
- **`writer`**: Function that receives an array of log strings
|
|
96
|
+
- **`filters`** (optional): Function that determines if a log should be processed by this lane
|
|
97
|
+
|
|
98
|
+
### Filter Function
|
|
99
|
+
|
|
100
|
+
The filter function receives a log entry object:
|
|
101
|
+
|
|
102
|
+
```javascript
|
|
103
|
+
{
|
|
104
|
+
id: 'log_1234567890_abc123',
|
|
105
|
+
ts: 1234567890123,
|
|
106
|
+
raw: 'original log data',
|
|
107
|
+
fileContext: { filePath: '/path/to/file.js', line: 42 },
|
|
108
|
+
meta: Map { 'level' => 'info', 'fileContext' => {...} }
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Writers
|
|
113
|
+
|
|
114
|
+
### Console Writer
|
|
115
|
+
|
|
116
|
+
```javascript
|
|
117
|
+
import { createConsoleWriter } from 'verblets/chains/llm-logger';
|
|
118
|
+
|
|
119
|
+
const writer = createConsoleWriter('[PREFIX] ');
|
|
120
|
+
// Outputs: [PREFIX] log message
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### File Writer
|
|
124
|
+
|
|
125
|
+
```javascript
|
|
126
|
+
import { createFileWriter } from 'verblets/chains/llm-logger';
|
|
127
|
+
|
|
128
|
+
const writer = createFileWriter('/path/to/logfile.log');
|
|
129
|
+
// Currently a placeholder - shows: [FILE:/path/to/logfile.log] N lines
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Custom Writer
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
const customWriter = (logs) => {
|
|
136
|
+
logs.forEach(log => {
|
|
137
|
+
// Send to external service, database, etc.
|
|
138
|
+
sendToLogService(log);
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Advanced Usage
|
|
144
|
+
|
|
145
|
+
### Accessing Ring Buffer
|
|
146
|
+
|
|
147
|
+
```javascript
|
|
148
|
+
const logger = createLLMLogger({...});
|
|
149
|
+
|
|
150
|
+
// Get all logs
|
|
151
|
+
const allLogs = logger.ringBuffer.all();
|
|
152
|
+
|
|
153
|
+
// Get recent logs
|
|
154
|
+
const recentLogs = logger.ringBuffer.tail(10);
|
|
155
|
+
|
|
156
|
+
// Get oldest logs
|
|
157
|
+
const oldestLogs = logger.ringBuffer.head(5);
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Manual Flush
|
|
161
|
+
|
|
162
|
+
```javascript
|
|
163
|
+
// Force flush all lanes immediately
|
|
164
|
+
logger.flush();
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Clear Logs
|
|
168
|
+
|
|
169
|
+
```javascript
|
|
170
|
+
// Clear ring buffer and lane buffers
|
|
171
|
+
logger.clear();
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Integration with Global Logger Service
|
|
175
|
+
|
|
176
|
+
```javascript
|
|
177
|
+
import { setLogger, log, info, warn, error } from 'verblets';
|
|
178
|
+
import { createLLMLogger, createConsoleWriter } from 'verblets/chains/llm-logger';
|
|
179
|
+
|
|
180
|
+
// Create and set LLM logger
|
|
181
|
+
const llmLogger = createLLMLogger({
|
|
182
|
+
lanes: [
|
|
183
|
+
{
|
|
184
|
+
laneId: 'console',
|
|
185
|
+
writer: createConsoleWriter()
|
|
186
|
+
}
|
|
187
|
+
]
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
setLogger(llmLogger);
|
|
191
|
+
|
|
192
|
+
// Now you can use global logging functions
|
|
193
|
+
log('This goes through the LLM logger');
|
|
194
|
+
error('This is an error log');
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Examples
|
|
198
|
+
|
|
199
|
+
See `index.examples.js` for comprehensive examples including:
|
|
200
|
+
|
|
201
|
+
- Security monitoring systems
|
|
202
|
+
- Performance monitoring
|
|
203
|
+
- E-commerce transaction processing
|
|
204
|
+
- Bulk log analysis
|
|
205
|
+
|
|
206
|
+
## Legacy API (Deprecated)
|
|
207
|
+
|
|
208
|
+
The old `initLogger()` and `log(data, logger)` functions are still available for backward compatibility but are deprecated. Use `createLLMLogger()` and the global logger service instead.
|