forked from unravel-team/DSCloj
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbasic_usage.clj
More file actions
345 lines (279 loc) · 11.4 KB
/
basic_usage.clj
File metadata and controls
345 lines (279 loc) · 11.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
(ns examples.basic-usage
(:require [dscloj.core :as dscloj]
[malli.core :as m]))
;; =============================================================================
;; SETUP: Register Provider Configurations
;; =============================================================================
(comment
;; Option 1: Quick setup from environment variables
;; This will automatically register :openai, :anthropic, :gemini, etc.
;; based on available API keys in environment
(dscloj/quick-setup!)
;; Option 2: Register custom providers
(dscloj/register-provider! :gpt4
{:provider :openai
:model "gpt-4"
:config {:api-key (System/getenv "OPENAI_API_KEY")}})
(dscloj/register-provider! :gpt4-mini
{:provider :openai
:model "gpt-4o-mini"
:config {:api-key (System/getenv "OPENAI_API_KEY")}})
(dscloj/register-provider! :claude
{:provider :anthropic
:model "claude-3-5-sonnet-20241022"
:config {:api-key (System/getenv "ANTHROPIC_API_KEY")}})
;; List all registered providers
(dscloj/list-providers)
)
;; =============================================================================
;; EXAMPLE 1: Simple Q&A Module with Router API
;; =============================================================================
(def qa-module
{:inputs [{:name :question
:spec :string
:description "The question to answer"}]
:outputs [{:name :answer
:spec :string
:description "The answer to the question"}]
:instructions "Provide concise and accurate answers."})
(comment
;; Setup provider first
(dscloj/register-provider! :gpt4
{:provider :openai
:model "gpt-4"
:config {:api-key (System/getenv "OPENAI_API_KEY")}})
;; Using registered provider
(def result (dscloj/predict :gpt4 qa-module
{:question "What is the capital of France?"})) ; provider-config as third argument
(:answer result)
;; => "Paris"
(def result2 (dscloj/predict :gpt4
qa-module
{:question "What is the capital of France?"}))
;; Using different provider (Anthropic)
(dscloj/register-provider! :claude
{:provider :anthropic
:model "claude-haiku-4-5"
:config {:api-key (System/getenv "ANTHROPIC_API_KEY")}})
(def result3 (dscloj/predict :claude qa-module
{:question "What is the capital of France?"}))
;; Invalid input will throw a validation exception
(try
(dscloj/predict :gpt4 qa-module
{:question 123})
(catch Exception e
(println "Validation error:" (.getMessage e))))
)
;; =============================================================================
;; EXAMPLE 2: Custom LLM Options
;; =============================================================================
(def translation-module
{:inputs [{:name :text
:spec :string
:description "Text to translate"}
{:name :target_language
:spec :string
:description "Target language"}]
:outputs [{:name :translation
:spec :string
:description "Translated text"}]
:instructions "Translate text accurately."})
(comment
(dscloj/register-provider! :gpt4
{:provider :openai
:model "gpt-4"
:config {:api-key (System/getenv "OPENAI_API_KEY")}})
;; Pass options as fourth argument
(def translation-result
(dscloj/predict :gpt4 translation-module
{:text "Hello, how are you?"
:target_language "Spanish"}
{:temperature 0.3
:max-tokens 100})) ; options in fourth argument
(:translation translation-result)
;; => "Hola, ¿cómo estás?"
)
;; =============================================================================
;; EXAMPLE 3: Multiple Output Types (bool, float, str)
;; =============================================================================
(def qa-with-confidence-module
{:inputs [{:name :question
:spec :string
:description "Question to answer"}]
:outputs [{:name :answer
:spec :string
:description "The answer"}
{:name :is_confident
:spec :boolean
:description "Whether the answer is confident"}
{:name :confidence_score
:spec :double
:description "Confidence from 0.0 to 1.0"}]
:instructions "Answer with confidence assessment."})
(comment
(dscloj/register-provider! :gpt4
{:provider :openai
:model "gpt-4"
:config {:api-key (System/getenv "OPENAI_API_KEY")}})
(def qa-result
(dscloj/predict :gpt4 qa-with-confidence-module
{:question "What is the speed of light?"}))
;; Types are automatically converted and validated
(:is_confident qa-result) ;; => true (boolean)
(:confidence_score qa-result) ;; => 0.95 (float)
(:answer qa-result) ;; => "The speed of light is..."
(when (:is_confident qa-result)
(if (> (:confidence_score qa-result) 0.8)
(println "High confidence:" (:answer qa-result))
(println "Low confidence:" (:answer qa-result))))
)
;; =============================================================================
;; EXAMPLE 4: Complex Malli Specs with Constraints
;; =============================================================================
(def analysis-module
{:inputs [{:name :text
:spec [:string {:min 1}]
:description "Text to analyze"}
{:name :min_length
:spec [:int {:min 0}]
:description "Minimum length requirement"}]
:outputs [{:name :summary
:spec :string
:description "Summary of the text"}
{:name :is_valid
:spec :boolean
:description "Whether text meets requirements"}
{:name :confidence
:spec [:double {:min 0.0 :max 1.0}]
:description "Confidence score 0.0-1.0"}]
:instructions "Analyze the text and check if it meets the minimum length requirement."})
(comment
(dscloj/register-provider! :gpt4
{:provider :openai
:model "gpt-4"
:config {:api-key (System/getenv "OPENAI_API_KEY")}})
(def analysis-result
(dscloj/predict :gpt4 analysis-module
{:text "This is a sample text for analysis."
:min_length 10}))
;; All outputs are type-validated against Malli specs
(:summary analysis-result) ;; => string
(:is_valid analysis-result) ;; => boolean
(:confidence analysis-result) ;; => double (0.0-1.0)
)
;; =============================================================================
;; EXAMPLE 5: Disabling Validation
;; =============================================================================
;; Sometimes you might want to skip validation (e.g., for debugging)
(def strict-module
{:inputs [{:name :number
:spec [:int {:min 1 :max 100}]}]
:outputs [{:name :result
:spec :string}]
:instructions "Process the number."})
(comment
(dscloj/register-provider! :gpt4
{:provider :openai
:model "gpt-4"
:config {:api-key (System/getenv "OPENAI_API_KEY")}})
;; With validation (default)
(dscloj/predict :gpt4 strict-module
{:number 50}
{:validate? true}) ; This is the default
;; Without validation
(dscloj/predict :gpt4 strict-module
{:number 50}
{:validate? false}) ; Skip Malli validation
)
;; =============================================================================
;; EXAMPLE 6: Inspecting Modules and Generated Prompts
;; =============================================================================
(comment
;; View the prompt template
(def prompt-template (dscloj/module->prompt qa-module))
(println prompt-template)
;; Useful for debugging what's sent to the LLM
)
;; =============================================================================
;; EXAMPLE 7: Working with Validation Errors
;; =============================================================================
(def typed-module
{:inputs [{:name :age
:spec [:int {:min 0 :max 150}]}
{:name :name
:spec [:string {:min 1}]}]
:outputs [{:name :message
:spec :string}]})
(comment
(dscloj/register-provider! :gpt4
{:provider :openai
:model "gpt-4"
:config {:api-key (System/getenv "OPENAI_API_KEY")}})
;; This will throw a validation error with details
(try
(dscloj/predict :gpt4 typed-module
{:age "not-a-number" ; Invalid: should be int
:name "John"})
(catch clojure.lang.ExceptionInfo e
(let [data (ex-data e)]
(println "Error:" (.getMessage e))
(println "Details:" (:errors data))
(println "Field:" (:field data))
(println "Value:" (:value data)))))
;; Validation errors are detailed and helpful
)
;; =============================================================================
;; EXAMPLE 8: Reusable Specs
;; =============================================================================
;; Define reusable Malli specs
(def QuestionSpec [:string {:min 1 :description "The question to answer"}])
(def AnswerSpec [:string {:min 1 :description "The answer"}])
(def ConfidenceSpec [:double {:min 0.0 :max 1.0 :description "Confidence score"}])
(def qa-with-context-module
{:inputs [{:name :question
:spec QuestionSpec}
{:name :context
:spec [:string {:description "Additional context"}]}]
:outputs [{:name :answer
:spec AnswerSpec}
{:name :confidence
:spec ConfidenceSpec}]
:instructions "Answer based on the question and context."})
(comment
(dscloj/register-provider! :gpt4
{:provider :openai
:model "gpt-4"
:config {:api-key (System/getenv "OPENAI_API_KEY")}})
(dscloj/predict :gpt4 qa-with-context-module
{:question "What is the capital?"
:context "We are discussing France."})
)
;; =============================================================================
;; EXAMPLE 9: Switching Between Providers
;; =============================================================================
(comment
;; Register multiple providers
(dscloj/register-provider! :gpt4
{:provider :openai
:model "gpt-4"
:config {:api-key (System/getenv "OPENAI_API_KEY")}})
(dscloj/register-provider! :claude
{:provider :anthropic
:model "claude-3-5-sonnet-20241022"
:config {:api-key (System/getenv "ANTHROPIC_API_KEY")}})
(dscloj/register-provider! :gemini
{:provider :gemini
:model "gemini-pro"
:config {:api-key (System/getenv "GOOGLE_API_KEY")}})
;; Same module, different providers - switch by just changing the config name
(def openai-result (dscloj/predict :gpt4 qa-module
{:question "What is AI?"}))
(def anthropic-result (dscloj/predict :gpt4 qa-module
{:question "What is AI?"}))
(def gemini-result (dscloj/predict :gpt4 qa-module
{:question "What is AI?"}))
;; Compare results
(println "OpenAI:" (:answer openai-result))
(println "Anthropic:" (:answer anthropic-result))
(println "Gemini:" (:answer gemini-result))
)