@delofarag/ai-utils 1.4.3 → 1.5.0

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 (122) hide show
  1. package/README.md +354 -216
  2. package/dist/heart/agent.d.ts +1 -1
  3. package/dist/heart/agent.d.ts.map +1 -1
  4. package/dist/heart/agent.js +3 -8
  5. package/dist/heart/agent.js.map +1 -1
  6. package/dist/heart/chain.d.ts +1 -1
  7. package/dist/heart/chain.d.ts.map +1 -1
  8. package/dist/heart/chain.js +4 -4
  9. package/dist/heart/chain.js.map +1 -1
  10. package/dist/heart/chatbot.d.ts +1 -1
  11. package/dist/heart/memorychain.d.ts +2 -2
  12. package/dist/heart/memorychain.js +6 -6
  13. package/dist/heart/memorychain.js.map +1 -1
  14. package/dist/heart/tools/zodios/ZodiosToolRegistry.d.ts +1 -1
  15. package/dist/heart/tools/zodios/ZodiosToolRegistry.d.ts.map +1 -1
  16. package/dist/helpers/chatbot.d.ts +33 -0
  17. package/dist/helpers/chatbot.d.ts.map +1 -0
  18. package/dist/helpers/chatbot.js +72 -0
  19. package/dist/helpers/chatbot.js.map +1 -0
  20. package/dist/helpers/helpers.d.ts +25 -0
  21. package/dist/helpers/helpers.d.ts.map +1 -0
  22. package/dist/helpers/helpers.js +43 -0
  23. package/dist/helpers/helpers.js.map +1 -0
  24. package/dist/helpers/llms.d.ts +92 -0
  25. package/dist/helpers/llms.d.ts.map +1 -0
  26. package/dist/helpers/llms.js +49 -0
  27. package/dist/helpers/llms.js.map +1 -0
  28. package/dist/helpers/memory.d.ts +91 -0
  29. package/dist/helpers/memory.d.ts.map +1 -0
  30. package/dist/helpers/memory.js +351 -0
  31. package/dist/helpers/memory.js.map +1 -0
  32. package/dist/helpers/rag.d.ts +42 -0
  33. package/dist/helpers/rag.d.ts.map +1 -0
  34. package/dist/helpers/rag.js +66 -0
  35. package/dist/helpers/rag.js.map +1 -0
  36. package/dist/helpers.d.ts +3 -3
  37. package/dist/index.d.ts +10 -9
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +10 -9
  40. package/dist/index.js.map +1 -1
  41. package/dist/magic-funcs/answerers/ask.d.ts +18 -2
  42. package/dist/magic-funcs/answerers/ask.d.ts.map +1 -1
  43. package/dist/magic-funcs/answerers/ask.js +20 -9
  44. package/dist/magic-funcs/answerers/ask.js.map +1 -1
  45. package/dist/magic-funcs/answerers/websearch.d.ts +15 -0
  46. package/dist/magic-funcs/answerers/websearch.d.ts.map +1 -1
  47. package/dist/magic-funcs/answerers/websearch.js +15 -0
  48. package/dist/magic-funcs/answerers/websearch.js.map +1 -1
  49. package/dist/magic-funcs/evaluators/classify.d.ts +20 -1
  50. package/dist/magic-funcs/evaluators/classify.d.ts.map +1 -1
  51. package/dist/magic-funcs/evaluators/classify.js +22 -3
  52. package/dist/magic-funcs/evaluators/classify.js.map +1 -1
  53. package/dist/magic-funcs/evaluators/decide.d.ts +18 -0
  54. package/dist/magic-funcs/evaluators/decide.d.ts.map +1 -1
  55. package/dist/magic-funcs/evaluators/decide.js +21 -3
  56. package/dist/magic-funcs/evaluators/decide.js.map +1 -1
  57. package/dist/magic-funcs/optimizers/promptify.d.ts +18 -0
  58. package/dist/magic-funcs/optimizers/promptify.d.ts.map +1 -1
  59. package/dist/magic-funcs/optimizers/promptify.js +21 -3
  60. package/dist/magic-funcs/optimizers/promptify.js.map +1 -1
  61. package/dist/magic-funcs/optimizers/ragify.d.ts +16 -0
  62. package/dist/magic-funcs/optimizers/ragify.d.ts.map +1 -1
  63. package/dist/magic-funcs/optimizers/ragify.js +19 -3
  64. package/dist/magic-funcs/optimizers/ragify.js.map +1 -1
  65. package/dist/magic-funcs/parsers/extract.d.ts +23 -0
  66. package/dist/magic-funcs/parsers/extract.d.ts.map +1 -1
  67. package/dist/magic-funcs/parsers/extract.js +26 -3
  68. package/dist/magic-funcs/parsers/extract.js.map +1 -1
  69. package/dist/magic-funcs/parsers/rewrite.d.ts +19 -0
  70. package/dist/magic-funcs/parsers/rewrite.d.ts.map +1 -1
  71. package/dist/magic-funcs/parsers/rewrite.js +22 -2
  72. package/dist/magic-funcs/parsers/rewrite.js.map +1 -1
  73. package/dist/magic-funcs/parsers/structure.d.ts +22 -0
  74. package/dist/magic-funcs/parsers/structure.d.ts.map +1 -1
  75. package/dist/magic-funcs/parsers/structure.js +27 -4
  76. package/dist/magic-funcs/parsers/structure.js.map +1 -1
  77. package/dist/magic-funcs/parsers/summarize.d.ts +20 -0
  78. package/dist/magic-funcs/parsers/summarize.d.ts.map +1 -1
  79. package/dist/magic-funcs/parsers/summarize.js +23 -3
  80. package/dist/magic-funcs/parsers/summarize.js.map +1 -1
  81. package/dist/memory.d.ts +1 -1
  82. package/dist/modalities/image-gen/generateImages.d.ts +56 -0
  83. package/dist/modalities/image-gen/generateImages.d.ts.map +1 -0
  84. package/dist/modalities/image-gen/generateImages.js +66 -0
  85. package/dist/modalities/image-gen/generateImages.js.map +1 -0
  86. package/dist/modalities/image-gen/helpers.d.ts +15 -0
  87. package/dist/modalities/image-gen/helpers.d.ts.map +1 -0
  88. package/dist/modalities/image-gen/helpers.js +17 -0
  89. package/dist/modalities/image-gen/helpers.js.map +1 -0
  90. package/dist/modalities/openrouter.d.ts +11 -0
  91. package/dist/modalities/openrouter.d.ts.map +1 -0
  92. package/dist/modalities/openrouter.js +39 -0
  93. package/dist/modalities/openrouter.js.map +1 -0
  94. package/dist/modalities/speech/VoiceEngine.d.ts +3 -0
  95. package/dist/modalities/speech/VoiceEngine.d.ts.map +1 -0
  96. package/dist/modalities/speech/VoiceEngine.js +3 -0
  97. package/dist/modalities/speech/VoiceEngine.js.map +1 -0
  98. package/dist/modalities/speech/stt/helpers.d.ts +3 -0
  99. package/dist/modalities/speech/stt/helpers.d.ts.map +1 -0
  100. package/dist/modalities/speech/stt/helpers.js +28 -0
  101. package/dist/modalities/speech/stt/helpers.js.map +1 -0
  102. package/dist/modalities/speech/stt/stt.d.ts +113 -0
  103. package/dist/modalities/speech/stt/stt.d.ts.map +1 -0
  104. package/dist/modalities/speech/stt/stt.js +177 -0
  105. package/dist/modalities/speech/stt/stt.js.map +1 -0
  106. package/dist/modalities/speech/tts/helpers.d.ts +12 -0
  107. package/dist/modalities/speech/tts/helpers.d.ts.map +1 -0
  108. package/dist/modalities/speech/tts/helpers.js +10 -0
  109. package/dist/modalities/speech/tts/helpers.js.map +1 -0
  110. package/dist/modalities/speech/tts/tts.d.ts +115 -0
  111. package/dist/modalities/speech/tts/tts.d.ts.map +1 -0
  112. package/dist/modalities/speech/tts/tts.js +142 -0
  113. package/dist/modalities/speech/tts/tts.js.map +1 -0
  114. package/dist/modalities/vision/helpers.d.ts +3 -0
  115. package/dist/modalities/vision/helpers.d.ts.map +1 -0
  116. package/dist/modalities/vision/helpers.js +7 -0
  117. package/dist/modalities/vision/helpers.js.map +1 -0
  118. package/dist/modalities/vision/vision.d.ts +55 -0
  119. package/dist/modalities/vision/vision.d.ts.map +1 -0
  120. package/dist/modalities/vision/vision.js +71 -0
  121. package/dist/modalities/vision/vision.js.map +1 -0
  122. package/package.json +7 -7
package/README.md CHANGED
@@ -1,369 +1,507 @@
1
1
  # @delofarag/ai-utils
2
2
 
3
- Ein Bauskasten für LLM-basierte Anwendungen: Chains, Agents, Memory, RAG, Magic-Funcs und mehr.
3
+ Ein praktisches Utility-Package für LLM-Apps mit LangChain:
4
+
5
+ - `Chain`, `MemoryChain`, `Agent`
6
+ - RAG-Helper (FAISS, Supabase, In-Memory)
7
+ - Tooling (`ToolRegistry`, `createRAGTool`, `tavilySearchTool`)
8
+ - Magic-Funcs (Parser, Evaluator, Optimizer, Answerer)
9
+ - Modalities (STT, TTS, Vision, Image Generation)
4
10
 
5
11
  ---
6
12
 
7
- ## ⚠️ Disclaimer: Default-LLM & getLLM()
13
+ ## Standard-Default (wichtig)
8
14
 
9
- (btw. nutz zod/v3, neuere versionen sind buggy mit langchain)
15
+ Im Package gilt als Standard-LLM-Default für die allgemeine Nutzung:
10
16
 
11
- **Für alle LLM-gebundenen Utils** (Chain, MemoryChain, Agent, Chatbot, magic-funcs) gilt:
17
+ - **Provider:** `openrouter`
18
+ - **Model:** `openai/gpt-5.4-mini`
12
19
 
13
- - **Default-Modell:** `llama-3.3-70b-versatile` von **ChatGroq**
14
- - **API-Key:** `process.env.CHATGROQ_API_KEY`
20
+ Wenn du nichts explizit setzt, orientiere dich an diesem Default in deinen Aufrufen.
15
21
 
16
- **Wenn du `CHATGROQ_API_KEY` in deiner `.env` setzt und mit dem Modell zufrieden bist, musst du kein LLM übergeben** – alles funktioniert out-of-the-box.
22
+ Für modality-spezifische Flows (`stt`, `tts`, `vision`, `image-gen`) wird zusätzlich mit `type` gearbeitet, damit passende Modelle gewählt werden koennen.
17
23
 
18
- Du kannst jederzeit ein eigenes LLM übergeben (z.B. anderes Modell, anderer Provider). Optimal dafür: die **`getLLM()`** Funktion aus `helpers.ts`. Sie ist eine Abstraktionsschicht für:
24
+ ---
19
25
 
20
- | Typ | Beispiel |
21
- |-----|----------|
22
- | **Groq** | `getLLM({ type: "groq", apikey: process.env.CHATGROQ_API_KEY!, model: "llama-3.3-70b-versatile" })` |
23
- | **OpenRouter** | `getLLM({ type: "openrouter", apikey: process.env.OPENROUTER_API_KEY!, model: "openai/gpt-4o-mini" })` |
24
- | **Ollama (lokal)** | `getLLM({ type: "local", model: "llama3.2:3b" })` |
26
+ ## Installation
27
+
28
+ ```bash
29
+ npm i @delofarag/ai-utils
30
+ ```
25
31
 
26
32
  ---
27
33
 
28
- ## Die 4 Hauptklassen
34
+ ## Environment Variables
35
+
36
+ Empfohlen in `.env`:
29
37
 
30
- ### 1. Chain
38
+ ```env
39
+ OPENROUTER_API_KEY=...
40
+ CHATGROQ_API_KEY=...
41
+ TAVILY_API_KEY=...
42
+ NEXT_PUBLIC_SUPABASE_URL=...
43
+ NEXT_PUBLIC_SUPABASE_ANON_KEY=...
44
+ SUPABASE_SERVICE_ROLE_KEY=...
45
+ ```
46
+
47
+ ### Welche Variable wofuer?
31
48
 
32
- **Was:** Stateless LLM-Chain mit strukturiertem Output (Zod-Schema) und optionalem RAG. Für `output` (Zod v3) kannst du **z.object()** oder **z.record()** verwenden.
49
+ - `OPENROUTER_API_KEY`: OpenRouter-Modelle und Modalities
50
+ - `CHATGROQ_API_KEY`: wenn du `provider: "chatgroq"` nutzt
51
+ - `TAVILY_API_KEY`: `websearch()` / `tavilySearchTool`
52
+ - Supabase-Variablen: fuer `createSupabaseVectoreStore()` und `getSupabaseVectorStore()`
33
53
 
34
- **Wann:** Einmalige Abfragen ohne Konversationsgedächtnis. Ideal für formularähnliche Eingabe → strukturierte Ausgabe.
54
+ ---
35
55
 
36
- **Initialisierung:**
56
+ ## Schnellstart: `getLLM()`
37
57
 
38
58
  ```ts
39
- import { Chain, DEFAULT_OUTPUT_SCHEMA } from "@delofarag/ai-utils"
59
+ import { getLLM } from "@delofarag/ai-utils"
60
+
61
+ const llm = getLLM({ provider: "openrouter", model: "openai/gpt-5.4-mini" })
62
+ ```
63
+
64
+ Beispiele:
65
+
66
+ ```ts
67
+ const llmOpenRouter = getLLM({ provider: "openrouter", model: "openai/gpt-5.4-mini" })
68
+ const llmGroq = getLLM({ provider: "chatgroq", model: "llama-3.3-70b-versatile" })
69
+ const llmLocal = getLLM({ provider: "local", model: "llama3.2:3b" })
70
+ ```
71
+
72
+ Modality-spezifisch:
73
+
74
+ ```ts
75
+ getLLM({ provider: "openrouter", type: "stt" })
76
+ getLLM({ provider: "openrouter", type: "tts" })
77
+ getLLM({ provider: "openrouter", type: "vision" })
78
+ getLLM({ provider: "openrouter", type: "image-gen" })
79
+ ```
80
+
81
+ ---
82
+
83
+ ## Core Classes
84
+
85
+ ## 1) `Chain`
86
+
87
+ Stateless LLM-Chain fuer strukturierte Ergebnisse.
88
+
89
+ ### Besseres Praxisbeispiel (custom output schema)
90
+
91
+ ```ts
92
+ import { Chain, getLLM } from "@delofarag/ai-utils"
40
93
  import { z } from "zod/v3"
41
94
 
42
- const output = z.object({
43
- output: z.string().describe("Deine Antwort"),
44
- score: z.number().optional()
95
+ const productBriefSchema = z.object({
96
+ title: z.string().describe("Kurzer Produktname"),
97
+ targetAudience: z.string().describe("Wer soll das Produkt nutzen?"),
98
+ keyBenefits: z.array(z.string()).describe("Top Vorteile"),
99
+ pricePositioning: z.enum(["budget", "mid", "premium"])
45
100
  })
46
- // alternativ: z.record(z.string()) für beliebige Key-Value-Struktur
47
101
 
48
102
  const chain = new Chain({
49
- prompt: "Du bist ein hilfreicher Assistent.",
50
- // llm optional Default: Groq
51
- output
103
+ llm: getLLM({ provider: "openrouter", model: "openai/gpt-5.4-mini" }),
104
+ prompt: "Du bist ein Product-Marketing-Assistent.",
105
+ output: productBriefSchema
52
106
  })
53
107
 
54
- const result = await chain.invoke({ input: "Was ist die Hauptstadt von Frankreich?" })
55
- // result: { output: "Paris", score?: number }
108
+ const result = await chain.invoke({
109
+ product: "AI-Notizapp fuer Teams",
110
+ market: "DACH SaaS"
111
+ })
56
112
  ```
57
113
 
58
- **RAG:** Mit `chain.setContext(vectorStore)` und `chain.addContext(["Text 1", "Text 2"])` wird automatisch Retrieval vor dem LLM-Call eingebaut.
114
+ ### RAG mit `Chain`
115
+
116
+ ```ts
117
+ import { Chain, createFaissStore } from "@delofarag/ai-utils"
118
+ import { z } from "zod/v3"
119
+
120
+ const vectorStore = await createFaissStore(["Dokument A", "Dokument B"])
59
121
 
60
- **Warum so:** Chain ist die kleinste Einheit – nur Prompt + LLM + Output (Zod-Schema für .invoke()). Kein Memory, keine Tools. Einfach zu testen und zu komponieren.
122
+ const chain = new Chain({
123
+ prompt: "Beantworte Fragen nur mit Kontext.",
124
+ output: z.object({ output: z.string() }),
125
+ vectorStore
126
+ })
127
+
128
+ await chain.addContext(["Dokument C"])
129
+
130
+ const answer = await chain.invoke({ question: "Was steht in Dokument C?" })
131
+ ```
61
132
 
62
133
  ---
63
134
 
64
- ### 2. MemoryChain
135
+ ## 2) `MemoryChain`
65
136
 
66
- **Was:** Chain mit Konversationsgedächtnis. Speichert User/AI-Messages pro `thread_id`.
137
+ `Chain` + Conversation Memory ueber `thread_id`.
67
138
 
68
- **Wann:** Chat-ähnliche Flows, bei denen der Kontext der vorherigen Nachrichten wichtig ist.
139
+ ### Basis
69
140
 
70
- **Initialisierung:**
141
+ ```ts
142
+ import { MemoryChain, getLLM } from "@delofarag/ai-utils"
143
+
144
+ const memoryChain = new MemoryChain({
145
+ llm: getLLM({ provider: "openrouter", model: "openai/gpt-5.4-mini" }),
146
+ prompt: "Du bist ein hilfreicher Assistent."
147
+ })
148
+
149
+ await memoryChain.invoke({ thread_id: "u1", input: "Ich heisse Max." })
150
+ const r2 = await memoryChain.invoke({ thread_id: "u1", input: "Wie heisse ich?" })
151
+ ```
152
+
153
+ ### RAG mit `MemoryChain`
71
154
 
72
155
  ```ts
73
- import { MemoryChain, SmartCheckpointSaver, MemorySaver, getLLM } from "@delofarag/ai-utils"
156
+ import { MemoryChain, createFaissStore } from "@delofarag/ai-utils"
157
+ import { z } from "zod/v3"
74
158
 
75
- const llm = getLLM({ type: "groq", apikey: process.env.CHATGROQ_API_KEY! })
159
+ const vectorStore = await createFaissStore(["Policy A", "Policy B"])
76
160
 
77
161
  const memoryChain = new MemoryChain({
78
- memory: new SmartCheckpointSaver(new MemorySaver(), { llm }),
79
- prompt: "Du bist ein hilfreicher Assistent.",
80
- llm
162
+ prompt: "Nutze Kontext und Gespraechshistorie.",
163
+ vectorStore,
164
+ output: z.object({ output: z.string() })
81
165
  })
82
166
 
83
- const result = await memoryChain.invoke({
84
- thread_id: "user-123",
85
- input: "Ich heiße Max."
86
- })
87
- const result2 = await memoryChain.invoke({
88
- thread_id: "user-123",
89
- input: "Wie heiße ich?"
167
+ const response = await memoryChain.invoke({
168
+ thread_id: "support-77",
169
+ question: "Welche Regel steht in Policy B?"
90
170
  })
91
- // result2.output ≈ "Du heißt Max."
92
171
  ```
93
172
 
94
- **Alternativ:** Du kannst eine bestehende `Chain` übergeben: `new MemoryChain({ chain: myChain, memory })`.
173
+ ---
95
174
 
96
- **Warum so:** MemoryChain kapselt nur die Memory-Logik – History laden, an den Prompt anhängen, Response speichern. Die eigentliche LLM-Logik bleibt in der Chain.
175
+ ## 3) `Agent`
97
176
 
98
- ---
177
+ Tool-using Agent auf Basis von `createReactAgent`.
99
178
 
100
- ### 3. Agent
179
+ ### Basis
101
180
 
102
- **Was:** LLM mit Tools (z.B. Web-Suche, API-Calls, RAG). Nutzt LangGraphs `createReactAgent` unter der Haube.
181
+ ```ts
182
+ import { Agent, ToolRegistry, getLLM } from "@delofarag/ai-utils"
183
+ import { z } from "zod/v3"
103
184
 
104
- **Wann:** Wenn das LLM externe Aktionen ausführen soll (Suche, Rechner, Datenbank, etc.).
185
+ const tools = new ToolRegistry([
186
+ {
187
+ name: "sum",
188
+ description: "Addiert zwei Zahlen",
189
+ schema: z.object({ a: z.number(), b: z.number() }),
190
+ func: ({ a, b }) => a + b
191
+ }
192
+ ]).allTools
105
193
 
106
- **Initialisierung:**
194
+ const agent = new Agent({
195
+ llm: getLLM({ provider: "openrouter", model: "openai/gpt-5.4-mini" }),
196
+ prompt: "Du darfst Tools nutzen wenn noetig.",
197
+ tools
198
+ })
199
+
200
+ const result = await agent.invoke({ input: "Was ist 8 + 13?" })
201
+ ```
202
+
203
+ ### RAG mit `Agent` (als Tool)
107
204
 
108
205
  ```ts
109
- import { Agent, ToolRegistry, createRAGTool, createFaissStore, tavilySearchTool, getLLM } from "@delofarag/ai-utils"
206
+ import { Agent, ToolRegistry, createRAGTool, createFaissStore } from "@delofarag/ai-utils"
110
207
 
111
- const vectorStore = await createFaissStore(["Dokumenteninhalt..."])
208
+ const vectorStore = await createFaissStore(["Release Notes 2026-04", "Known Issues"])
112
209
  const ragTool = createRAGTool({
113
210
  vectorStore,
114
- name: "search_context",
115
- description: "Durchsucht den Kontext nach relevanten Informationen"
211
+ name: "search_docs",
212
+ description: "Sucht relevante Produktdokumente"
116
213
  })
117
214
 
118
215
  const registry = new ToolRegistry([
119
- { name: "calculator", description: "...", schema: z.object({ a: z.number(), b: z.number() }), func: ({ a, b }) => a + b },
120
- tavilySearchTool,
121
- ragTool
216
+ {
217
+ name: "search_docs",
218
+ description: "Sucht relevante Produktdokumente",
219
+ schema: ragTool.schema as any,
220
+ func: ragTool.func as any
221
+ }
122
222
  ])
123
223
 
124
224
  const agent = new Agent({
125
- prompt: "Du bist ein hilfreicher Assistent mit Zugang zu Tools.",
126
- tools: registry.allTools,
127
- llm: getLLM({ type: "groq" }),
128
- memory: new SmartCheckpointSaver(new MemorySaver(), { llm }) // optional
225
+ prompt: "Nutze search_docs fuer faktenbasierte Antworten.",
226
+ tools: [...registry.allTools, ragTool]
129
227
  })
130
-
131
- const result = await agent.invoke({
132
- thread_id: "session-1", // nötig wenn memory gesetzt
133
- input: "Was steht heute in den Nachrichten zu KI?"
134
- })
135
-
136
- agent.addTool(weiteresTool) // Tools nachträglich hinzufügen
137
228
  ```
138
229
 
139
- **RAG:** RAG ist ein normales Tool – nutze `createRAGTool({ vectorStore, name, description })` und füge es zu `tools` hinzu oder via `agent.addTool()`.
230
+ ---
140
231
 
141
- **Warum so:** Der Agent entscheidet selbst, wann er Tools nutzt. RAG wird wie jedes andere Tool behandelt (kein setContext/addContext mehr).
232
+ ## Tool Registry (eigene Section)
142
233
 
143
- ---
234
+ `ToolRegistry` konvertiert einfache Tool-Definitionen zu `DynamicStructuredTool` und bietet:
144
235
 
145
- ### 4. Chatbot
236
+ - `getTool(name)`
237
+ - `getTools(...names)`
238
+ - `allTools`
146
239
 
147
- **Was:** High-Level Wrapper – je nach Konfiguration entweder ein `MemoryChain` oder ein `Agent`. Discriminated Union: `tools` → Agent, `vectorStore` → MemoryChain.
240
+ ```ts
241
+ import { ToolRegistry } from "@delofarag/ai-utils"
242
+ import { z } from "zod/v3"
243
+
244
+ const registry = new ToolRegistry([
245
+ {
246
+ name: "get_weather",
247
+ description: "Liefert Wetter fuer eine Stadt",
248
+ schema: z.object({ city: z.string() }),
249
+ func: async ({ city }) => `${city}: sonnig`
250
+ },
251
+ {
252
+ name: "get_time",
253
+ description: "Liefert aktuelle Zeit",
254
+ schema: z.object({}),
255
+ func: async () => new Date().toISOString()
256
+ }
257
+ ])
148
258
 
149
- **Wann:** Schnell einen chatbasierten Assistenten bauen, mit oder ohne Tools.
259
+ const weatherTool = registry.getTool("get_weather")
260
+ const tools = registry.allTools
261
+ ```
150
262
 
151
- **Initialisierung:**
263
+ ### Tavily Tooling
152
264
 
153
265
  ```ts
154
- import { Chatbot, createRAGTool, createFaissStore, tavilySearchTool, getLLM } from "@delofarag/ai-utils"
266
+ import { tavilySearchTool, TavilySearch } from "@delofarag/ai-utils"
155
267
 
156
- // Ohne Tools, mit RAG → MemoryChain + vectorStore
157
- const vectorStore = await createFaissStore(["Kontextdaten..."])
158
- const simpleChatbot = new Chatbot({
159
- llm: getLLM({ type: "groq" }),
160
- prompt: "Du bist ein freundlicher Assistent.",
161
- vectorStore
268
+ const tavily = new TavilySearch({
269
+ tavilyApiKey: process.env.TAVILY_API_KEY,
270
+ maxResults: 5,
271
+ topic: "general",
272
+ includeAnswer: false
162
273
  })
163
274
 
164
- // Mit Tools Agent (RAG als Tool möglich)
165
- const toolChatbot = new Chatbot({
166
- llm: getLLM({ type: "groq" }),
167
- tools: [
168
- tavilySearchTool,
169
- createRAGTool({ vectorStore, name: "search", description: "Durchsucht den Kontext" })
170
- ],
171
- prompt: "Du bist ein Assistent mit Webzugang."
172
- })
275
+ const response = await tavily.invoke({ query: "latest AI regulation EU" })
276
+ ```
277
+
278
+ ---
279
+
280
+ ## Memory Section (ausfuehrlich)
173
281
 
174
- // Streaming-Chat
175
- for await (const chunk of simpleChatbot.chat({ input: "Hallo!", thread_id: "user-1" })) {
176
- process.stdout.write(chunk)
177
- }
282
+ ### `MemorySaver` (in-memory, schnell fuer local/dev)
178
283
 
179
- // Interaktive Session (CLI)
180
- await simpleChatbot.session({ breakword: "exit", id: "session-1" })
284
+ ```ts
285
+ import { MemorySaver, SmartCheckpointSaver, getLLM } from "@delofarag/ai-utils"
286
+
287
+ const memory = new SmartCheckpointSaver(new MemorySaver(), {
288
+ llm: getLLM({ provider: "openrouter", model: "openai/gpt-5.4-mini" }),
289
+ messagesBeforeSummary: 12,
290
+ maxSummaries: 7
291
+ })
181
292
  ```
182
293
 
183
- **Warum so:** Ein Einstiegspunkt für „einfach nur chatten“. Weniger Boilerplate als Chain/MemoryChain/Agent direkt zu bauen.
294
+ ### `SmartCheckpointSaver`
184
295
 
185
- ---
296
+ Was es macht:
297
+
298
+ - fasst alte Chatverlaeufe zusammen
299
+ - reduziert Token-Kosten
300
+ - erhaelt wichtige Fakten ueber mehrere Sessions
301
+
302
+ Wichtige Optionen:
186
303
 
187
- ## Tool-Registrys
304
+ - `messagesBeforeSummary` (default `12`)
305
+ - `maxSummaries` (default `7`)
306
+ - `llm` (default OpenRouter `gpt-5.4-mini`)
307
+ - `debug`
188
308
 
189
- ### ToolRegistry (BasicToolRegistry) – empfohlen
309
+ ### `SupabaseCheckpointSaver`
190
310
 
191
- Registriert Tools mit `name`, `description`, `schema`, `func`. Perfekt für manuell definierte Tools.
311
+ Persistiert Checkpoints in Supabase.
192
312
 
193
313
  ```ts
194
- import { ToolRegistry } from "@delofarag/ai-utils"
195
- import { z } from "zod/v3"
314
+ import { SupabaseCheckpointSaver, type SupabaseCheckpointRow } from "@delofarag/ai-utils"
315
+ import { SupabaseTable } from "@delofarag/supabase-utils"
196
316
 
197
- const registry = new ToolRegistry([
198
- {
199
- name: "greet",
200
- description: "Begrüßt eine Person",
201
- schema: z.object({ name: z.string() }),
202
- func: ({ name }) => `Hallo, ${name}!`
203
- }
204
- ])
317
+ const checkpointsTable = new SupabaseTable<SupabaseCheckpointRow>({
318
+ // ... deine SupabaseTable Konfiguration
319
+ })
320
+
321
+ const saver = new SupabaseCheckpointSaver(checkpointsTable)
322
+ ```
323
+
324
+ Typischer Einsatz:
325
+
326
+ ```ts
327
+ import { MemoryChain } from "@delofarag/ai-utils"
205
328
 
206
- const tool = registry.getTool("greet")
207
- const allTools = registry.allTools
329
+ const memoryChain = new MemoryChain({
330
+ prompt: "Du bist ein Support Assistant.",
331
+ memory: saver
332
+ })
208
333
  ```
209
334
 
210
- ### ZodiosToolRegistry – noch experimentell
335
+ ---
336
+
337
+ ## RAG Utilities (Detail)
211
338
 
212
- Wandelt Zodios-API-Endpoints automatisch in Tools um. **Funktioniert derzeit nicht zuverlässig** – nur testen, nicht für Produktion.
339
+ ### Vector Stores
213
340
 
214
- ### tavilySearchTool & TAVILY_API_KEY
341
+ - `createRAMVectoreStore(data)`
342
+ - `createSupabaseVectoreStore(data, config?)`
343
+ - `getSupabaseVectorStore(config?)`
344
+ - `createFaissStore(data, config?)`
345
+ - `loadFaissStore({ path })`
346
+ - `turn_to_docs(data)`
215
347
 
216
- Das `tavilySearchTool` ist ein vorgefertigtes Tool für Web-Suche via Tavily. Nutzung:
348
+ ### RAG Chain
217
349
 
218
- - **API-Key:** `process.env.TAVILY_API_KEY` (in `.env` setzen)
219
- - **Import:** `tavilySearchTool` aus `@delofarag/ai-utils`
220
- - **Beispiel:** Siehe Agent-Beispiel oben
350
+ - `createRAGChain({ vectorStore, llm, prompt?, num_of_results_from_vdb? })`
351
+
352
+ ### RAG Tool
353
+
354
+ - `createRAGTool({ vectorStore, name, description })`
355
+
356
+ ```ts
357
+ import { createRAGTool, createFaissStore } from "@delofarag/ai-utils"
221
358
 
222
- Alternativ: `TavilySearch`-Klasse für direkten Aufruf (z.B. in `websearch()`).
359
+ const vectorStore = await createFaissStore(["FAQ 1", "FAQ 2"])
360
+ const ragTool = createRAGTool({
361
+ vectorStore,
362
+ name: "search_faq",
363
+ description: "Sucht in FAQ-Dokumenten"
364
+ })
365
+ ```
223
366
 
224
367
  ---
225
368
 
226
369
  ## Magic-Funcs
227
370
 
228
- Kleine, wiederverwendbare LLM-Funktionen. **Struktur:** Immer `{ llm?, ...params }` – `llm` optional, sonst Default (Groq).
229
-
230
371
  ### Answerers
231
-
232
- - **ask(question)** Einfache Frage → Textantwort
233
- - **websearch(query)** – Sucht im Web (Tavily), braucht `TAVILY_API_KEY`
372
+ - `ask({ question, llm? })`
373
+ - `websearch(query)` (braucht `TAVILY_API_KEY`)
234
374
 
235
375
  ### Evaluators
236
-
237
- - **classify({ data, classes, context? })** – Ordnet Input einer von mehreren Klassen zu
238
- - **decide({ material, kriteria_to_decide })** – Ja/Nein/Unclear plus Begründung
376
+ - `classify({ data, classes, context?, llm? })`
377
+ - `decide({ material, kriteria_to_decide, llm? })`
239
378
 
240
379
  ### Parsers
241
-
242
- - **extract({ data, schema, goal? })** – Extrahiert strukturierte Daten gemäß Zod-Schema
243
- - **structure({ data, into, retries? })** – Formatiert beliebigen Input in ein Zod-Schema
244
- - **rewrite({ data, instruction })** – Transformiert Text nach Anweisung
245
- - **summarize({ data, fokuss?, maxWords? })** – Fasst zusammen
380
+ - `extract({ data, schema, goal?, llm? })`
381
+ - `structure({ data, into, retries?, llm? })`
382
+ - `rewrite({ data, instruction, llm? })`
383
+ - `summarize({ data, fokuss?, maxWords?, llm? })`
246
384
 
247
385
  ### Optimizers
386
+ - `promptify({ request, agentRole?, llm? })`
387
+ - `ragify({ data, llm? })`
248
388
 
249
- - **promptify({ request, agentRole? })** – Erzeugt System-Prompts aus Nutzeranfragen
250
- - **ragify({ data })** – Optimiert Text für RAG (strukturierter, informationsdicht)
251
-
252
- **Beispiel – immer gleiche Struktur:**
389
+ Beispiel:
253
390
 
254
391
  ```ts
255
392
  import { classify, extract, summarize } from "@delofarag/ai-utils"
256
393
  import { z } from "zod/v3"
257
394
 
258
- const klasse = await classify({
259
- data: "Produktbewertung: Tolle Qualität!",
395
+ const sentiment = await classify({
396
+ data: "Das Produkt ist wirklich gut.",
260
397
  classes: ["positiv", "negativ", "neutral"] as const
261
398
  })
262
399
 
263
- const infos = await extract({
264
- data: "Max, 30 Jahre, Berlin",
265
- schema: z.object({ name: z.string(), alter: z.number(), stadt: z.string() })
400
+ const person = await extract({
401
+ data: "Max ist 30 und lebt in Berlin.",
402
+ schema: z.object({
403
+ name: z.string(),
404
+ age: z.number(),
405
+ city: z.string()
406
+ })
266
407
  })
267
408
 
268
- const kurz = await summarize({ data: langerText, maxWords: 50 })
409
+ const short = await summarize({
410
+ data: "Sehr langer Text...",
411
+ maxWords: 50
412
+ })
269
413
  ```
270
414
 
271
415
  ---
272
416
 
273
- ## RAG-Implementierungen
417
+ ## Modalities
274
418
 
275
- **Vector Stores** (in `rag.ts`):
419
+ ### STT
276
420
 
277
- - **turn_to_docs(data)** – Wandelt Strings/Objekte in LangChain-`Document[]` um
278
- - **createSupabaseVectoreStore({ supabase, data, table_name?, RPC_function? })** Supabase Vector Store aus Daten
279
- - **getSupabaseVectorStore({ supabase, table_name?, RPC_function? })** – Bestehenden Store holen
280
- - **createFaissStore({ data, save_path?, embeddings? })** – FAISS-Store (lokal, speicherbar)
281
- - **loadFaissStore({ path, embeddings? })** – FAISS-Store laden
421
+ - `stt(...)`
422
+ - `createSTTPhoneSocketSession(...)` fuer live phone socket chunks (Twilio/Telnyx-style)
282
423
 
283
- **RAG als Tool** (für Agent):
284
-
285
- - **createRAGTool({ vectorStore, name, description })** – Erzeugt ein Tool, mit dem der Agent den Vector Store durchsucht. In `tools` übergeben oder via `agent.addTool()`.
286
-
287
- **Retrieval-Chains** (in `rag.ts`):
288
-
289
- - **createRAGChain({ vectorStore, llm, prompt?, num_of_results_from_vdb? })** – Retrieval-Chain
290
- - **createRAGChainFromRetriever({ retriever, llm, prompt? })** – Alternative mit eigenem Retriever
291
-
292
- **Typischer Ablauf:**
293
-
294
- 1. Vector Store erstellen: `createFaissStore({ data })` oder `createSupabaseVectoreStore({ data })`
295
- 2. **Chain/MemoryChain:** `chain.setContext(vectorStore)` – RAG wird automatisch eingebaut. Optional `chain.addContext(weitereDaten)` für weitere Docs
296
- 3. **Agent/Chatbot:** `createRAGTool({ vectorStore, name, description })` als Tool übergeben
297
-
298
- ---
424
+ ```ts
425
+ import { stt } from "@delofarag/ai-utils"
299
426
 
300
- ## Memory: SupabaseCheckpointSaver & SmartCheckpointSaver
427
+ const result = await stt({
428
+ audio: "./call.wav",
429
+ prompt: "Transcribe in German."
430
+ })
431
+ ```
301
432
 
302
- ### SupabaseCheckpointSaver
433
+ ### TTS
303
434
 
304
- Speichert Checkpoints (inkl. Konversationsverlauf) in einer Supabase-Tabelle. Für persistente Chats über Sessions hinweg.
435
+ - `tts(...)`
436
+ - `streamTTSOverPhoneSocket(...)` fuer chunked outbound audio
305
437
 
306
438
  ```ts
307
- import { SupabaseCheckpointSaver, SupabaseCheckpointRow } from "@delofarag/ai-utils"
308
- import { SupabaseTable } from "@delofarag/supabase-utils"
439
+ import { tts, streamTTSOverPhoneSocket } from "@delofarag/ai-utils"
309
440
 
310
- const table = new SupabaseTable<SupabaseCheckpointRow>({ /* ... */ })
311
- const saver = new SupabaseCheckpointSaver(table)
441
+ const speech = await tts({
442
+ text: "Willkommen beim Support.",
443
+ model: "nova"
444
+ })
312
445
 
313
- const memoryChain = new MemoryChain({
314
- chain: myChain,
315
- memory: saver
446
+ await streamTTSOverPhoneSocket({
447
+ text: "Einen Moment bitte.",
448
+ model: "nova",
449
+ onChunk: async (chunk) => {
450
+ // socket send
451
+ }
316
452
  })
317
453
  ```
318
454
 
319
- **Hinweis:** Noch unter Test – Tabellen-Schema muss zu den Checkpoint-Strukturen passen.
455
+ ### Vision
320
456
 
321
- ### SmartCheckpointSaver
457
+ ```ts
458
+ import { vision } from "@delofarag/ai-utils"
322
459
 
323
- Wrapper um einen anderen `BaseCheckpointSaver` (z.B. `MemorySaver` oder `SupabaseCheckpointSaver`). Führt automatisch **Summarization** durch:
460
+ const result = await vision({
461
+ prompt: "Was ist auf dem Bild zu sehen?",
462
+ images: ["https://example.com/photo.jpg"]
463
+ })
464
+ ```
324
465
 
325
- - Nach `messagesBeforeSummary` User/AI-Nachrichten (Default: 12) wird die Konversation zusammengefasst
326
- - Die Zusammenfassung ersetzt die alten Messages → weniger Tokens, längerer Kontext
327
- - `maxSummaries` (Default: 7): Maximal so viele Summaries werden behalten. Sobald eine neue erstellt würde und das Limit überschritten wäre, wird die älteste Summary gelöscht (Rolling-Window)
466
+ ### Image Generation
328
467
 
329
468
  ```ts
330
- import { SmartCheckpointSaver, MemorySaver, getLLM } from "@delofarag/ai-utils"
469
+ import { generateImages } from "@delofarag/ai-utils"
331
470
 
332
- const llm = getLLM({ type: "groq", apikey: process.env.CHATGROQ_API_KEY! })
333
- const memory = new SmartCheckpointSaver(new MemorySaver(), {
334
- llm,
335
- messagesBeforeSummary: 12,
336
- maxSummaries: 7,
471
+ const generated = await generateImages({
472
+ prompt: "Generate a clean product hero image",
473
+ imageConfig: { aspect_ratio: "16:9", image_size: "2K" }
337
474
  })
475
+ ```
476
+
477
+ ---
338
478
 
339
- const chatbot = new Chatbot({ llm, memory })
479
+ ## Session / Stream Helpers
480
+
481
+ ```ts
482
+ import { session, StreamResponse } from "@delofarag/ai-utils"
340
483
  ```
341
484
 
342
- **Warum so:** Lange Chats blähen den Kontext auf. SmartCheckpointSaver hält die wichtigsten Infos in Zusammenfassungen und reduziert Token-Verbrauch.
485
+ - `session({ streamable, ... })`: CLI-like interactive loop
486
+ - `StreamResponse(asyncIterable)`: streambares NDJSON-HTTP-Response-Objekt
343
487
 
344
488
  ---
345
489
 
346
- ## Kurzüberblick
347
-
348
- | Util | Zweck |
349
- |------|-------|
350
- | **Chain** | Stateless LLM + Schema, optional RAG (setContext/addContext) |
351
- | **MemoryChain** | Chain + Konversations-Memory pro thread_id, optional RAG |
352
- | **Agent** | LLM + Tools, optional Memory. RAG via createRAGTool + addTool |
353
- | **Chatbot** | Discriminated Union: tools → Agent, vectorStore → MemoryChain |
354
- | **ToolRegistry** | Tools registrieren (empfohlen) |
355
- | **tavilySearchTool** | Web-Suche (TAVILY_API_KEY) |
356
- | **Magic-Funcs** | ask, websearch, classify, decide, extract, structure, rewrite, summarize, promptify, ragify |
357
- | **RAG** | createRAGTool, Supabase/FAISS Vector Stores, createRAGChain |
358
- | **SupabaseCheckpointSaver** | Persistente Memory in Supabase |
359
- | **SmartCheckpointSaver** | Memory mit Auto-Summarization |
360
- | **getLLM()** | LLM aus Groq, OpenRouter oder Ollama |
490
+ ## Export Overview (high-level)
491
+
492
+ Top-level Exports decken u. a. ab:
493
+
494
+ - Helpers (`helpers`, `memory`, `rag`, `llms`, `chatbot`)
495
+ - Core (`Agent`, `Chain`, `MemoryChain`)
496
+ - Tools (`ToolRegistry`, `Tavily`, `RAGTool`, Zodios registries)
497
+ - Magic-Funcs (answerers/evaluators/parsers/optimizers)
498
+ - Modalities (`stt`, `tts`, `vision`, `generateImages`)
361
499
 
362
500
  ---
363
501
 
364
- ## .env-Variablen
502
+ ## Empfehlungen
365
503
 
366
- | Variable | Verwendung |
367
- |----------|------------|
368
- | `CHATGROQ_API_KEY` | Default für alle LLM-Utils |
369
- | `TAVILY_API_KEY` | tavilySearchTool, websearch() |
504
+ - Fuer strukturierte Outputs immer `zod/v3` verwenden.
505
+ - Fuer Produktion API-Keys als ENV setzen, nicht hardcoden.
506
+ - Bei langen Chats `SmartCheckpointSaver` verwenden.
507
+ - RAG als Tool im `Agent` ist in der Praxis oft robuster als RAG-only Prompting.