@far-world-labs/verblets 0.2.0 → 0.3.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.
Files changed (330) hide show
  1. package/README.md +86 -213
  2. package/dist/index.browser.js +74 -0
  3. package/dist/index.js +548 -0
  4. package/dist/shared-C6kPWghF.js +7806 -0
  5. package/package.json +32 -11
  6. package/.cursor/launch.json +0 -30
  7. package/.cursor/settings.json +0 -20
  8. package/.github/workflows/branch-protection.yml +0 -22
  9. package/.github/workflows/ci.yml +0 -165
  10. package/.husky/pre-commit +0 -4
  11. package/.prettierrc +0 -6
  12. package/.release-it.json +0 -12
  13. package/.vitest.config.examples.js +0 -12
  14. package/.vitest.config.js +0 -8
  15. package/.vscode/launch.json +0 -31
  16. package/AGENTS.md +0 -220
  17. package/DEVELOPING.md +0 -105
  18. package/docker-compose.yml +0 -7
  19. package/eslint.config.js +0 -80
  20. package/scripts/clear-redis.js +0 -74
  21. package/scripts/generate-chain/index.js +0 -111
  22. package/scripts/generate-lib/index.js +0 -68
  23. package/scripts/generate-test/index.js +0 -137
  24. package/scripts/generate-verblet/README.md +0 -17
  25. package/scripts/generate-verblet/index.js +0 -110
  26. package/scripts/run.sh +0 -15
  27. package/scripts/runner/index.js +0 -56
  28. package/scripts/simple-editor/README.md +0 -34
  29. package/scripts/simple-editor/index.js +0 -79
  30. package/scripts/summarize-files/index.js +0 -70
  31. package/src/chains/README.md +0 -30
  32. package/src/chains/anonymize/README.md +0 -21
  33. package/src/chains/anonymize/index.examples.js +0 -75
  34. package/src/chains/anonymize/index.js +0 -121
  35. package/src/chains/anonymize/index.spec.js +0 -78
  36. package/src/chains/bulk-central-tendency/index.examples.js +0 -138
  37. package/src/chains/bulk-central-tendency/index.js +0 -91
  38. package/src/chains/bulk-filter/README.md +0 -21
  39. package/src/chains/bulk-filter/index.examples.js +0 -22
  40. package/src/chains/bulk-filter/index.js +0 -58
  41. package/src/chains/bulk-filter/index.spec.js +0 -38
  42. package/src/chains/bulk-find/README.md +0 -16
  43. package/src/chains/bulk-find/index.examples.js +0 -20
  44. package/src/chains/bulk-find/index.js +0 -30
  45. package/src/chains/bulk-find/index.spec.js +0 -26
  46. package/src/chains/bulk-group/README.md +0 -23
  47. package/src/chains/bulk-group/index.examples.js +0 -18
  48. package/src/chains/bulk-group/index.js +0 -34
  49. package/src/chains/bulk-group/index.spec.js +0 -41
  50. package/src/chains/bulk-map/README.md +0 -43
  51. package/src/chains/bulk-map/index.examples.js +0 -17
  52. package/src/chains/bulk-map/index.js +0 -86
  53. package/src/chains/bulk-map/index.spec.js +0 -44
  54. package/src/chains/bulk-reduce/README.md +0 -12
  55. package/src/chains/bulk-reduce/index.examples.js +0 -15
  56. package/src/chains/bulk-reduce/index.js +0 -13
  57. package/src/chains/bulk-reduce/index.spec.js +0 -25
  58. package/src/chains/bulk-score/README.md +0 -16
  59. package/src/chains/bulk-score/bulk-score-result.json +0 -18
  60. package/src/chains/bulk-score/index.examples.js +0 -22
  61. package/src/chains/bulk-score/index.js +0 -133
  62. package/src/chains/bulk-score/index.spec.js +0 -30
  63. package/src/chains/category-samples/README.md +0 -61
  64. package/src/chains/category-samples/index.examples.js +0 -103
  65. package/src/chains/category-samples/index.js +0 -134
  66. package/src/chains/collect-terms/README.md +0 -12
  67. package/src/chains/collect-terms/index.examples.js +0 -16
  68. package/src/chains/collect-terms/index.js +0 -44
  69. package/src/chains/collect-terms/index.spec.js +0 -25
  70. package/src/chains/conversation/README.md +0 -26
  71. package/src/chains/conversation/index.examples.js +0 -398
  72. package/src/chains/conversation/index.js +0 -126
  73. package/src/chains/conversation/index.spec.js +0 -148
  74. package/src/chains/conversation/turn-policies.js +0 -93
  75. package/src/chains/conversation/turn-policies.md +0 -123
  76. package/src/chains/conversation/turn-policies.spec.js +0 -135
  77. package/src/chains/date/README.md +0 -12
  78. package/src/chains/date/index.examples.js +0 -47
  79. package/src/chains/date/index.js +0 -74
  80. package/src/chains/date/index.spec.js +0 -62
  81. package/src/chains/disambiguate/README.md +0 -22
  82. package/src/chains/disambiguate/disambiguate-meanings-result.json +0 -16
  83. package/src/chains/disambiguate/index.examples.js +0 -18
  84. package/src/chains/disambiguate/index.js +0 -92
  85. package/src/chains/disambiguate/index.spec.js +0 -25
  86. package/src/chains/dismantle/README.md +0 -67
  87. package/src/chains/dismantle/dismantle.examples.js +0 -27
  88. package/src/chains/dismantle/index.examples.js +0 -30
  89. package/src/chains/dismantle/index.js +0 -303
  90. package/src/chains/dismantle/index.spec.js +0 -32
  91. package/src/chains/expect/README.md +0 -171
  92. package/src/chains/expect/index.examples.js +0 -146
  93. package/src/chains/expect/index.js +0 -207
  94. package/src/chains/expect/index.spec.js +0 -324
  95. package/src/chains/filter-ambiguous/README.md +0 -11
  96. package/src/chains/filter-ambiguous/index.examples.js +0 -20
  97. package/src/chains/filter-ambiguous/index.js +0 -49
  98. package/src/chains/filter-ambiguous/index.spec.js +0 -31
  99. package/src/chains/glossary/README.md +0 -19
  100. package/src/chains/glossary/index.examples.js +0 -386
  101. package/src/chains/glossary/index.js +0 -75
  102. package/src/chains/glossary/index.spec.js +0 -19
  103. package/src/chains/intersections/README.md +0 -166
  104. package/src/chains/intersections/index.examples.js +0 -280
  105. package/src/chains/intersections/index.js +0 -218
  106. package/src/chains/intersections/intersection-result.json +0 -38
  107. package/src/chains/list/index.examples.js +0 -68
  108. package/src/chains/list/index.js +0 -214
  109. package/src/chains/list/index.spec.js +0 -67
  110. package/src/chains/list/list-result.json +0 -16
  111. package/src/chains/list/schema.json +0 -24
  112. package/src/chains/llm-logger/README.md +0 -366
  113. package/src/chains/llm-logger/index.js +0 -591
  114. package/src/chains/llm-logger/index.spec.js +0 -391
  115. package/src/chains/llm-logger/schema.json +0 -105
  116. package/src/chains/questions/index.examples.js +0 -69
  117. package/src/chains/questions/index.js +0 -135
  118. package/src/chains/questions/index.spec.js +0 -29
  119. package/src/chains/scan-js/index.js +0 -116
  120. package/src/chains/set-interval/README.md +0 -81
  121. package/src/chains/set-interval/index.examples.js +0 -64
  122. package/src/chains/set-interval/index.js +0 -152
  123. package/src/chains/set-interval/index.spec.js +0 -70
  124. package/src/chains/socratic/README.md +0 -17
  125. package/src/chains/socratic/index.js +0 -64
  126. package/src/chains/socratic/index.spec.js +0 -24
  127. package/src/chains/sort/index.examples.js +0 -36
  128. package/src/chains/sort/index.js +0 -163
  129. package/src/chains/sort/index.spec.js +0 -112
  130. package/src/chains/sort/sort-result.json +0 -16
  131. package/src/chains/summary-map/README.md +0 -41
  132. package/src/chains/summary-map/index.examples.js +0 -64
  133. package/src/chains/summary-map/index.js +0 -226
  134. package/src/chains/summary-map/index.spec.js +0 -153
  135. package/src/chains/test/index.js +0 -114
  136. package/src/chains/test-advice/index.js +0 -35
  137. package/src/chains/themes/README.md +0 -20
  138. package/src/chains/themes/index.examples.js +0 -17
  139. package/src/chains/themes/index.js +0 -28
  140. package/src/chains/themes/index.spec.js +0 -19
  141. package/src/chains/veiled-variants/index.examples.js +0 -18
  142. package/src/chains/veiled-variants/index.js +0 -107
  143. package/src/chains/veiled-variants/index.spec.js +0 -40
  144. package/src/constants/common.js +0 -13
  145. package/src/constants/messages.js +0 -3
  146. package/src/constants/models.js +0 -184
  147. package/src/index.js +0 -203
  148. package/src/json-schemas/README.md +0 -13
  149. package/src/json-schemas/cars-test.json +0 -11
  150. package/src/json-schemas/index.js +0 -12
  151. package/src/json-schemas/intent.json +0 -38
  152. package/src/json-schemas/schema-dot-org-photograph.json +0 -133
  153. package/src/json-schemas/schema-dot-org-place.json +0 -129
  154. package/src/lib/README.md +0 -26
  155. package/src/lib/any-signal/index.js +0 -28
  156. package/src/lib/assert/README.md +0 -84
  157. package/src/lib/assert/index.js +0 -50
  158. package/src/lib/bulk-filter/README.md +0 -22
  159. package/src/lib/bulk-filter/index.examples.js +0 -27
  160. package/src/lib/bulk-filter/index.js +0 -63
  161. package/src/lib/bulk-filter/index.spec.js +0 -38
  162. package/src/lib/bulk-find/README.md +0 -18
  163. package/src/lib/bulk-find/index.examples.js +0 -19
  164. package/src/lib/bulk-find/index.js +0 -30
  165. package/src/lib/bulk-find/index.spec.js +0 -41
  166. package/src/lib/chatgpt/index.js +0 -163
  167. package/src/lib/combinations/index.js +0 -30
  168. package/src/lib/combinations/index.spec.js +0 -23
  169. package/src/lib/editor/index.js +0 -31
  170. package/src/lib/functional/index.js +0 -28
  171. package/src/lib/logger-service/index.js +0 -32
  172. package/src/lib/parse-js-parts/index.js +0 -321
  173. package/src/lib/parse-js-parts/index.spec.js +0 -156
  174. package/src/lib/parse-llm-list/README.md +0 -39
  175. package/src/lib/parse-llm-list/index.js +0 -54
  176. package/src/lib/parse-llm-list/index.spec.js +0 -59
  177. package/src/lib/path-aliases/index.js +0 -37
  178. package/src/lib/path-aliases/index.spec.js +0 -64
  179. package/src/lib/pave/index.js +0 -34
  180. package/src/lib/pave/index.spec.js +0 -76
  181. package/src/lib/prompt-cache/index.js +0 -50
  182. package/src/lib/retry/index.js +0 -66
  183. package/src/lib/retry/index.spec.js +0 -86
  184. package/src/lib/ring-buffer/README.md +0 -82
  185. package/src/lib/ring-buffer/index.js +0 -235
  186. package/src/lib/ring-buffer/index.spec.js +0 -388
  187. package/src/lib/search-best-first/city-walk.spec.js +0 -37
  188. package/src/lib/search-best-first/index.js +0 -97
  189. package/src/lib/search-best-first/index.spec.js +0 -35
  190. package/src/lib/search-js-files/code-features-property-definitions.json +0 -123
  191. package/src/lib/search-js-files/index.examples.js +0 -22
  192. package/src/lib/search-js-files/index.js +0 -155
  193. package/src/lib/search-js-files/index.spec.js +0 -34
  194. package/src/lib/search-js-files/scan-file.js +0 -242
  195. package/src/lib/shorten-text/index.js +0 -25
  196. package/src/lib/shorten-text/index.spec.js +0 -68
  197. package/src/lib/strip-numeric/index.js +0 -5
  198. package/src/lib/strip-response/index.js +0 -30
  199. package/src/lib/template-replace/index.js +0 -23
  200. package/src/lib/template-replace/index.spec.js +0 -60
  201. package/src/lib/timed-abort-controller/index.js +0 -41
  202. package/src/lib/to-bool/index.js +0 -8
  203. package/src/lib/to-date/index.js +0 -11
  204. package/src/lib/to-enum/index.js +0 -14
  205. package/src/lib/to-number/index.js +0 -12
  206. package/src/lib/to-number-with-units/index.js +0 -51
  207. package/src/lib/transcribe/index.js +0 -78
  208. package/src/prompts/README.md +0 -17
  209. package/src/prompts/as-enum.js +0 -5
  210. package/src/prompts/as-json-schema.js +0 -9
  211. package/src/prompts/as-object-with-schema.js +0 -26
  212. package/src/prompts/as-schema-org-text.js +0 -25
  213. package/src/prompts/as-schema-org-type.js +0 -1
  214. package/src/prompts/blog-post.js +0 -7
  215. package/src/prompts/code-features.js +0 -24
  216. package/src/prompts/constants.js +0 -101
  217. package/src/prompts/features-json-schema.js +0 -27
  218. package/src/prompts/generate-collection.js +0 -26
  219. package/src/prompts/generate-list.js +0 -48
  220. package/src/prompts/generate-questions.js +0 -19
  221. package/src/prompts/index.js +0 -20
  222. package/src/prompts/intent.js +0 -60
  223. package/src/prompts/output-succinct-names.js +0 -3
  224. package/src/prompts/select-from-threshold.js +0 -17
  225. package/src/prompts/sort.js +0 -31
  226. package/src/prompts/style.js +0 -38
  227. package/src/prompts/summarize.js +0 -13
  228. package/src/prompts/token-budget.js +0 -3
  229. package/src/prompts/wrap-list.js +0 -11
  230. package/src/prompts/wrap-variable.js +0 -36
  231. package/src/services/llm-model/global-overrides.spec.js +0 -432
  232. package/src/services/llm-model/index.js +0 -308
  233. package/src/services/llm-model/model.js +0 -21
  234. package/src/services/llm-model/negotiate.spec.js +0 -447
  235. package/src/services/redis/index.js +0 -147
  236. package/src/test/setup.js +0 -20
  237. package/src/verblets/README.md +0 -26
  238. package/src/verblets/auto/index.examples.js +0 -31
  239. package/src/verblets/auto/index.js +0 -28
  240. package/src/verblets/auto/index.spec.js +0 -32
  241. package/src/verblets/bool/README.md +0 -36
  242. package/src/verblets/bool/index.examples.js +0 -80
  243. package/src/verblets/bool/index.js +0 -25
  244. package/src/verblets/bool/index.schema.json +0 -14
  245. package/src/verblets/bool/index.spec.js +0 -33
  246. package/src/verblets/central-tendency/README.md +0 -166
  247. package/src/verblets/central-tendency/central-tendency-result.json +0 -24
  248. package/src/verblets/central-tendency/index.examples.js +0 -196
  249. package/src/verblets/central-tendency/index.js +0 -171
  250. package/src/verblets/central-tendency/index.spec.js +0 -148
  251. package/src/verblets/conversation-turn/README.md +0 -33
  252. package/src/verblets/conversation-turn/index.examples.js +0 -218
  253. package/src/verblets/conversation-turn/index.js +0 -68
  254. package/src/verblets/conversation-turn/index.spec.js +0 -77
  255. package/src/verblets/conversation-turn-multi/README.md +0 -31
  256. package/src/verblets/conversation-turn-multi/index.examples.js +0 -160
  257. package/src/verblets/conversation-turn-multi/index.js +0 -104
  258. package/src/verblets/conversation-turn-multi/index.spec.js +0 -63
  259. package/src/verblets/enum/index.examples.js +0 -30
  260. package/src/verblets/enum/index.js +0 -18
  261. package/src/verblets/enum/index.spec.js +0 -35
  262. package/src/verblets/expect/README.md +0 -64
  263. package/src/verblets/expect/index.examples.js +0 -109
  264. package/src/verblets/expect/index.js +0 -75
  265. package/src/verblets/expect/index.spec.js +0 -127
  266. package/src/verblets/intent/index.examples.js +0 -139
  267. package/src/verblets/intent/index.js +0 -60
  268. package/src/verblets/intent/index.spec.js +0 -31
  269. package/src/verblets/intersection/README.md +0 -16
  270. package/src/verblets/intersection/index.examples.js +0 -89
  271. package/src/verblets/intersection/index.js +0 -125
  272. package/src/verblets/intersection/index.spec.js +0 -60
  273. package/src/verblets/intersection/intersection-result.json +0 -16
  274. package/src/verblets/list-expand/README.md +0 -10
  275. package/src/verblets/list-expand/index.examples.js +0 -14
  276. package/src/verblets/list-expand/index.js +0 -104
  277. package/src/verblets/list-expand/index.spec.js +0 -18
  278. package/src/verblets/list-expand/list-expand-result.json +0 -16
  279. package/src/verblets/list-filter/README.md +0 -22
  280. package/src/verblets/list-filter/index.examples.js +0 -26
  281. package/src/verblets/list-filter/index.js +0 -18
  282. package/src/verblets/list-filter/index.spec.js +0 -19
  283. package/src/verblets/list-find/README.md +0 -11
  284. package/src/verblets/list-find/index.examples.js +0 -15
  285. package/src/verblets/list-find/index.js +0 -17
  286. package/src/verblets/list-find/index.spec.js +0 -19
  287. package/src/verblets/list-group/README.md +0 -16
  288. package/src/verblets/list-group/index.examples.js +0 -16
  289. package/src/verblets/list-group/index.js +0 -112
  290. package/src/verblets/list-group/index.spec.js +0 -35
  291. package/src/verblets/list-group/list-group-result.json +0 -16
  292. package/src/verblets/list-map/README.md +0 -11
  293. package/src/verblets/list-map/index.examples.js +0 -15
  294. package/src/verblets/list-map/index.js +0 -26
  295. package/src/verblets/list-map/index.spec.js +0 -17
  296. package/src/verblets/list-reduce/README.md +0 -10
  297. package/src/verblets/list-reduce/index.examples.js +0 -14
  298. package/src/verblets/list-reduce/index.js +0 -21
  299. package/src/verblets/list-reduce/index.spec.js +0 -27
  300. package/src/verblets/list-reduce/index.spec.jsx +0 -27
  301. package/src/verblets/name/README.md +0 -15
  302. package/src/verblets/name/index.examples.js +0 -28
  303. package/src/verblets/name/index.js +0 -19
  304. package/src/verblets/name/index.spec.js +0 -33
  305. package/src/verblets/name-similar-to/README.md +0 -26
  306. package/src/verblets/name-similar-to/index.examples.js +0 -18
  307. package/src/verblets/name-similar-to/index.js +0 -20
  308. package/src/verblets/name-similar-to/index.spec.js +0 -13
  309. package/src/verblets/number/index.examples.js +0 -199
  310. package/src/verblets/number/index.js +0 -25
  311. package/src/verblets/number/index.spec.js +0 -33
  312. package/src/verblets/number-with-units/index.examples.js +0 -38
  313. package/src/verblets/number-with-units/index.js +0 -84
  314. package/src/verblets/number-with-units/index.spec.js +0 -46
  315. package/src/verblets/number-with-units/number-with-units-result.json +0 -23
  316. package/src/verblets/people-list/README.md +0 -28
  317. package/src/verblets/people-list/index.examples.js +0 -184
  318. package/src/verblets/people-list/index.js +0 -44
  319. package/src/verblets/people-list/index.spec.js +0 -49
  320. package/src/verblets/schema-org/index.examples.js +0 -51
  321. package/src/verblets/schema-org/index.js +0 -37
  322. package/src/verblets/schema-org/index.spec.js +0 -39
  323. package/src/verblets/sentiment/README.md +0 -10
  324. package/src/verblets/sentiment/index.examples.js +0 -20
  325. package/src/verblets/sentiment/index.js +0 -9
  326. package/src/verblets/sentiment/index.spec.js +0 -20
  327. package/src/verblets/to-object/README.md +0 -38
  328. package/src/verblets/to-object/index.examples.js +0 -29
  329. package/src/verblets/to-object/index.js +0 -131
  330. package/src/verblets/to-object/index.spec.js +0 -71
@@ -1,214 +0,0 @@
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';
5
- import chatGPT from '../../lib/chatgpt/index.js';
6
- import {
7
- asObjectWithSchema as asObjectWithSchemaPrompt,
8
- generateList as generateListPrompt,
9
- constants as promptConstants,
10
- } from '../../prompts/index.js';
11
- import modelService from '../../services/llm-model/index.js';
12
-
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
- }
56
-
57
- const outputTransformPrompt = (result, schema) => {
58
- return `${contentIsTransformationSource} ${result}
59
-
60
- ${asObjectWithSchemaPrompt(schema)}
61
-
62
- ${onlyJSON}`;
63
- };
64
-
65
- const shouldSkipDefault = ({ result, resultsAll } = {}) => {
66
- return resultsAll.includes(result);
67
- };
68
-
69
- const shouldStopDefault = ({ queryCount, startTime } = {}) => {
70
- return (
71
- queryCount > 5 ||
72
- new Date() - startTime >
73
- operationTimeoutMultiplier * modelService.getBestPublicModel().requestTimeout
74
- );
75
- };
76
-
77
- export const generateList = async function* generateListGenerator(text, options = {}) {
78
- const resultsAll = [];
79
- const resultsAllMap = {};
80
- let isDone = false;
81
- const {
82
- shouldSkip = shouldSkipDefault,
83
- shouldStop = shouldStopDefault,
84
- model = 'fastGoodCheap',
85
- // eslint-disable-next-line no-unused-vars
86
- _schema,
87
- ...passThroughOptions
88
- } = options;
89
-
90
- const startTime = new Date();
91
- let queryCount = 0;
92
-
93
- while (!isDone) {
94
- const listPrompt = generateListPrompt(text, {
95
- ...options,
96
- existing: resultsAll,
97
- });
98
-
99
- let resultsNew = [];
100
- try {
101
- const modelOptions = await createModelOptions(model);
102
- // eslint-disable-next-line no-await-in-loop
103
- const results = await chatGPT(listPrompt, {
104
- modelOptions,
105
- ...passThroughOptions,
106
- });
107
-
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) : [];
113
- } catch (error) {
114
- if (/The operation was aborted/.test(error.message)) {
115
- // eslint-disable-next-line no-console
116
- console.error('Generate list [error]: Aborted');
117
- resultsNew = []; // continue
118
- } else {
119
- // eslint-disable-next-line no-console
120
- console.error(
121
- `Generate list [error]: ${error.message}`,
122
- listPrompt.slice(0, 100).replace('\n', '\\n')
123
- );
124
- isDone = true;
125
- break;
126
- }
127
- }
128
-
129
- const resultsNewUnique = resultsNew.filter((item) => !(item in resultsAllMap));
130
-
131
- queryCount += 1;
132
-
133
- for (const result of resultsNewUnique) {
134
- const perResultControlFactors = {
135
- result,
136
- resultsAll,
137
- resultsNew,
138
- queryCount,
139
- startTime,
140
- };
141
-
142
- // eslint-disable-next-line no-await-in-loop
143
- if (await shouldStop(perResultControlFactors)) {
144
- isDone = true;
145
- break;
146
- }
147
-
148
- // eslint-disable-next-line no-await-in-loop
149
- if (!(await shouldSkip(perResultControlFactors))) {
150
- resultsAllMap[result] = true;
151
- resultsAll.push(result);
152
-
153
- // debug helper:
154
- // console.error(R.sort((a, b) => a.localeCompare(b), resultsAll));
155
-
156
- yield result;
157
- }
158
- }
159
-
160
- const perQueryControlFactors = {
161
- result: undefined,
162
- resultsAll: [],
163
- resultsNew: [],
164
- queryCount,
165
- startTime,
166
- };
167
-
168
- // eslint-disable-next-line no-await-in-loop
169
- if (await shouldStop(perQueryControlFactors)) {
170
- isDone = true;
171
- }
172
- }
173
- };
174
-
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
- },
200
- ...options,
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
- }
212
-
213
- return items;
214
- }
@@ -1,67 +0,0 @@
1
- import fs from 'node:fs/promises';
2
- import { describe, expect, it, vi } from 'vitest';
3
- import { fileURLToPath } from 'url';
4
- import { dirname, join } from 'path';
5
-
6
- import toObject from '../../verblets/to-object/index.js';
7
- import list from './index.js';
8
-
9
- const __filename = fileURLToPath(import.meta.url);
10
- const __dirname = dirname(__filename);
11
-
12
- const loadSchema = async () => {
13
- const file = (await fs.readFile(join(__dirname, '../../json-schemas/cars-test.json'))).toString();
14
-
15
- return toObject(file);
16
- };
17
-
18
- vi.mock('../../lib/chatgpt/index.js', () => ({
19
- default: vi.fn().mockImplementation((text) => {
20
- if (/Transform/.test(text) && /Model Y/.test(text)) {
21
- return '{"make":"Tesla", "model": "Model Y"}';
22
- }
23
- if (/EV cars/.test(text)) {
24
- return '["Tesla Model Y"]';
25
- }
26
- return 'undefined';
27
- }),
28
- }));
29
-
30
- const examples = [
31
- {
32
- name: 'Basic usage',
33
- inputs: { description: '2021 EV cars' },
34
- want: { listContains: /Model Y/ },
35
- },
36
- {
37
- name: 'Basic usage with schema',
38
- inputs: {
39
- description: '2021 EV cars',
40
- schema: loadSchema,
41
- },
42
- want: { listModelContains: /Model Y/ },
43
- },
44
- ];
45
-
46
- describe('List verblet', () => {
47
- examples.forEach((example) => {
48
- it(example.name, async () => {
49
- let schema;
50
- if (example.inputs.schema) {
51
- schema = await example.inputs.schema();
52
- }
53
- const result = await list(example.inputs.description, {
54
- shouldStop: ({ queryCount }) => queryCount > 1,
55
- schema,
56
- });
57
-
58
- if (example.want.listContains) {
59
- expect(result.some((item) => example.want.listContains.test(item))).equals(true);
60
- }
61
-
62
- if (example.want.listModelContains) {
63
- expect(result.some((item) => example.want.listModelContains.test(item.model))).equals(true);
64
- }
65
- });
66
- });
67
- });
@@ -1,16 +0,0 @@
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
- }
@@ -1,24 +0,0 @@
1
- {
2
- "name": "list",
3
- "description": "Generate a list based on the input text, optionally specifying a JSON schema for the subsequent output to conform to",
4
- "parameters": {
5
- "type": "object",
6
- "properties": {
7
- "name": {
8
- "type": "string",
9
- "description": "Name or description of the list to be generated"
10
- },
11
- "options": {
12
- "type": "object",
13
- "description": "Options for list generation and transformation",
14
- "properties": {
15
- "jsonSchema": {
16
- "type": "object",
17
- "description": "The JSONSchema used for transforming list results"
18
- }
19
- }
20
- }
21
- },
22
- "required": []
23
- }
24
- }
@@ -1,366 +0,0 @@
1
- # Enhanced LLM Logger
2
-
3
- Advanced logging system with non-destructive parallel processing, designed for AI/LLM applications that need to enhance logs without modifying original data.
4
-
5
- ## 🚀 Key Features
6
-
7
- ### Core Innovations
8
- - **Fully Parallel Processing**: No coordination overhead - processors run independently
9
- - **Non-Destructive Enhancement**: Original logs remain unchanged, enhancements stored as attachments
10
- - **NDJSON Bulk Processing**: Efficient batch processing for LLM interaction
11
- - **Smart Filtering**: AI metadata controls output without affecting stored data
12
- - **Ordered Adjustments**: Processor order determines adjustment priority
13
-
14
- ### Architecture
15
- - **Ring Buffer**: High-performance circular buffer for log storage
16
- - **Parallel Processors**: Independent processors with individual read offsets
17
- - **Attachment System**: JSON-path syntax for non-destructive data enhancement
18
- - **Lane System**: Multiple output channels with independent filtering
19
- - **AI Metadata**: Separate metadata layer for AI-specific flags
20
-
21
- ## 📋 Quick Start
22
-
23
- ```javascript
24
- import { createLLMLogger, createConsoleWriter } from './index.js';
25
-
26
- // Create logger with processors
27
- const logger = createLLMLogger({
28
- ringBufferSize: 1000,
29
- processors: [
30
- {
31
- processorId: 'sentiment-analyzer',
32
- description: 'Analyzes log sentiment',
33
- batchSize: 10,
34
- async process(ndjsonInput) {
35
- // Process NDJSON batch and return bulk adjustments
36
- const logs = parseNDJSON(ndjsonInput);
37
- return logs.map(log => ({
38
- logId: log.id,
39
- adjustments: {
40
- 'analysis.sentiment': analyzeSentiment(log.data),
41
- 'analysis.confidence': 0.95
42
- },
43
- aiMeta: {
44
- skip: shouldSkip(log),
45
- confidence: 0.95
46
- }
47
- }));
48
- }
49
- }
50
- ],
51
- lanes: [
52
- {
53
- laneId: 'console',
54
- writer: createConsoleWriter('[LOG] '),
55
- filters: (log) => log.meta.get('level') !== 'debug'
56
- }
57
- ]
58
- });
59
-
60
- // Use the logger
61
- logger.info('User logged in');
62
- logger.error('Database error');
63
- ```
64
-
65
- ## 🔧 API Reference
66
-
67
- ### Logger Creation
68
-
69
- ```javascript
70
- createLLMLogger(config)
71
- ```
72
-
73
- **Config Options:**
74
- - `ringBufferSize` (number): Ring buffer capacity (default: 5000)
75
- - `processors` (LogProcessor[]): Array of log processors
76
- - `lanes` (LogLaneConfig[]): Output lane configurations
77
- - `flushInterval` (number): Flush interval in ms (default: 1000)
78
- - `immediateFlush` (boolean): Immediate vs batched flushing (default: false)
79
-
80
- ### Log Processors
81
-
82
- ```javascript
83
- {
84
- processorId: 'unique-id',
85
- description: 'Human readable description',
86
- batchSize: 10,
87
- async process(ndjsonInput) {
88
- // Return array of BulkAdjustment objects
89
- return [{
90
- logId: 'log-id',
91
- adjustments: {
92
- 'path.to.field': 'value'
93
- },
94
- aiMeta: {
95
- skip: false,
96
- confidence: 0.95
97
- }
98
- }];
99
- }
100
- }
101
- ```
102
-
103
- ### Lane Configuration
104
-
105
- ```javascript
106
- {
107
- laneId: 'unique-lane-id',
108
- writer: (logs) => { /* write logs array */ },
109
- filters: (log) => { /* return boolean */ }
110
- }
111
- ```
112
-
113
- ### Logger Methods
114
-
115
- #### Standard Logging
116
- ```javascript
117
- logger.log(data)
118
- logger.info(data)
119
- logger.warn(data)
120
- logger.error(data)
121
- logger.debug(data)
122
- logger.trace(data)
123
- logger.fatal(data)
124
- ```
125
-
126
- #### Enhancement API
127
- ```javascript
128
- // Attach data to specific log
129
- logger.attachToLog(logId, 'path.to.field', value)
130
-
131
- // Get attachment data
132
- logger.getLogAttachment(logId, 'path.to.field')
133
-
134
- // Mark log as skippable
135
- logger.markLogSkippable(logId, true)
136
- ```
137
-
138
- #### Ring Buffer Access
139
- ```javascript
140
- logger.ringBuffer.all() // Get all logs
141
- logger.ringBuffer.tail(n) // Get last n logs
142
- logger.ringBuffer.head(n) // Get first n logs
143
- logger.ringBuffer.filter(fn) // Filter logs
144
- logger.ringBuffer.clear() // Clear buffer
145
- ```
146
-
147
- #### Utility Methods
148
- ```javascript
149
- logger.flush() // Force flush all lanes
150
- logger.clear() // Clear all data
151
- logger.getStats() // Get processing statistics
152
- logger.getProcessorOffsets() // Get processor progress
153
- ```
154
-
155
- ## 🔄 Processing Flow
156
-
157
- 1. **Log Entry**: Log data enters the system
158
- 2. **Ring Buffer**: Stored in circular buffer with metadata
159
- 3. **Parallel Processing**: Multiple processors work independently
160
- 4. **NDJSON Conversion**: Logs converted to NDJSON for LLM processing
161
- 5. **Bulk Adjustments**: Processors return structured adjustments
162
- 6. **Attachment Application**: Adjustments applied as attachments
163
- 7. **Lane Filtering**: Logs filtered through output lanes
164
- 8. **AI Metadata Filtering**: Skip flags respected during output
165
- 9. **Writer Output**: Final logs sent to configured writers
166
-
167
- ## 📊 Data Structures
168
-
169
- ### LogEntry
170
- ```javascript
171
- {
172
- id: 'unique-id',
173
- ts: Date,
174
- raw: 'original-data',
175
- meta: Map,
176
- attachments: {}, // Non-destructive enhancements
177
- aiMeta: {} // AI-specific metadata (not output)
178
- }
179
- ```
180
-
181
- ### BulkAdjustment
182
- ```javascript
183
- {
184
- logId: 'target-log-id',
185
- adjustments: {
186
- 'path.to.field': 'value',
187
- 'nested.object': { key: 'value' }
188
- },
189
- aiMeta: {
190
- skip: false,
191
- confidence: 0.95,
192
- // ... other AI metadata
193
- }
194
- }
195
- ```
196
-
197
- ### NDJSON Format
198
- ```
199
- {"id":"log-1","ts":"2024-01-01T00:00:00Z","level":"info","data":"message","attachments":{}}
200
- {"id":"log-2","ts":"2024-01-01T00:00:01Z","level":"error","data":"error","attachments":{}}
201
- ```
202
-
203
- ## 🎯 Use Cases
204
-
205
- ### AI Log Analysis
206
- ```javascript
207
- const aiProcessor = {
208
- processorId: 'ai-analyzer',
209
- description: 'AI-powered log analysis',
210
- batchSize: 20,
211
- async process(ndjsonInput) {
212
- const analysis = await callLLM(ndjsonInput);
213
- return analysis.map(item => ({
214
- logId: item.logId,
215
- adjustments: {
216
- 'ai.category': item.category,
217
- 'ai.severity': item.severity,
218
- 'ai.suggestions': item.suggestions
219
- },
220
- aiMeta: {
221
- skip: item.severity === 'low',
222
- confidence: item.confidence
223
- }
224
- }));
225
- }
226
- };
227
- ```
228
-
229
- ### Multi-Stage Processing
230
- ```javascript
231
- const processors = [
232
- sentimentProcessor, // Order 0: First to process
233
- categoryProcessor, // Order 1: Sees sentiment results
234
- priorityProcessor // Order 2: Sees all previous results
235
- ];
236
- ```
237
-
238
- ### Conditional Output
239
- ```javascript
240
- const lanes = [
241
- {
242
- laneId: 'all-logs',
243
- writer: fileWriter('all.log'),
244
- filters: () => true
245
- },
246
- {
247
- laneId: 'errors-only',
248
- writer: alertWriter,
249
- filters: (log) => log.meta.get('level') === 'error'
250
- },
251
- {
252
- laneId: 'high-confidence',
253
- writer: analyticsWriter,
254
- filters: (log) => log.attachments?.ai?.confidence > 0.8
255
- }
256
- ];
257
- ```
258
-
259
- ## 🔍 Monitoring & Debugging
260
-
261
- ### Statistics
262
- ```javascript
263
- const stats = logger.getStats();
264
- console.log('Ring buffer usage:', stats.writeIndex, '/', stats.maxSize);
265
- console.log('Processors:', stats.processors);
266
- ```
267
-
268
- ### Processor Progress
269
- ```javascript
270
- const offsets = logger.getProcessorOffsets();
271
- for (const [processorId, offset] of offsets) {
272
- console.log(`${processorId}: processed up to offset ${offset}`);
273
- }
274
- ```
275
-
276
- ### Log Inspection
277
- ```javascript
278
- const recentLogs = logger.ringBuffer.tail(10);
279
- recentLogs.forEach(log => {
280
- console.log('Original:', log.raw);
281
- console.log('Enhanced:', log.attachments);
282
- console.log('AI Meta:', log.aiMeta);
283
- });
284
- ```
285
-
286
- ## ⚡ Performance Characteristics
287
-
288
- - **Parallel Processing**: No blocking between processors
289
- - **Ring Buffer**: O(1) write operations
290
- - **Batch Processing**: Configurable batch sizes for efficiency
291
- - **Memory Bounded**: Fixed memory usage via ring buffer
292
- - **Non-Blocking**: Async processing doesn't block logging
293
-
294
- ## 🔧 Configuration Examples
295
-
296
- ### High-Throughput Setup
297
- ```javascript
298
- const logger = createLLMLogger({
299
- ringBufferSize: 10000,
300
- flushInterval: 100,
301
- processors: processors.map(p => ({
302
- ...p,
303
- batchSize: 50
304
- }))
305
- });
306
- ```
307
-
308
- ### Real-Time Setup
309
- ```javascript
310
- const logger = createLLMLogger({
311
- immediateFlush: true,
312
- processors: processors.map(p => ({
313
- ...p,
314
- batchSize: 1
315
- }))
316
- });
317
- ```
318
-
319
- ### Development Setup
320
- ```javascript
321
- const logger = createLLMLogger({
322
- ringBufferSize: 100,
323
- immediateFlush: true,
324
- lanes: [{
325
- laneId: 'console',
326
- writer: createConsoleWriter('[DEV] ')
327
- }]
328
- });
329
- ```
330
-
331
- ## 🚨 Error Handling
332
-
333
- Processors handle errors gracefully:
334
- - Failed processors retry after delay
335
- - Other processors continue unaffected
336
- - Original logs always preserved
337
- - Error logs available in statistics
338
-
339
- ## 📈 Migration Guide
340
-
341
- ### From Basic Logger
342
- ```javascript
343
- // Before
344
- const logger = createBasicLogger();
345
- logger.info('message');
346
-
347
- // After
348
- const logger = createLLMLogger({
349
- lanes: [{ laneId: 'console', writer: createConsoleWriter() }]
350
- });
351
- logger.info('message');
352
- ```
353
-
354
- ### Adding Processors
355
- ```javascript
356
- // Add processors incrementally
357
- const logger = createLLMLogger({
358
- // ... existing config
359
- processors: [
360
- ...existingProcessors,
361
- newProcessor
362
- ]
363
- });
364
- ```
365
-
366
- This enhanced logger provides a powerful foundation for AI-driven log processing while maintaining compatibility with existing logging patterns.