baml-cc 0.208.5

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.
@@ -0,0 +1,607 @@
1
+ #![allow(dead_code)]
2
+
3
+ use std::{
4
+ str::FromStr,
5
+ sync::{Arc, Mutex},
6
+ };
7
+
8
+ use baml_runtime::tracingv2::storage::storage::BAML_TRACER;
9
+ use magnus::{
10
+ class, function, method,
11
+ scan_args::{get_kwargs, scan_args},
12
+ try_convert::TryConvertOwned,
13
+ Error, IntoValueFromNative, Module, Object, RArray, RModule, Ruby, Value,
14
+ };
15
+
16
+ use super::{
17
+ request::{HTTPBody, HTTPRequest},
18
+ response::HTTPResponse,
19
+ };
20
+ use crate::Result;
21
+
22
+ crate::lang_wrapper!(
23
+ Collector,
24
+ "Baml::Ffi::Collector",
25
+ baml_runtime::tracingv2::storage::storage::Collector,
26
+ clone_safe
27
+ );
28
+
29
+ unsafe impl TryConvertOwned for &Collector {}
30
+
31
+ crate::lang_wrapper!(
32
+ Usage,
33
+ "Baml::Ffi::Usage",
34
+ baml_runtime::tracingv2::storage::storage::Usage,
35
+ clone_safe
36
+ );
37
+
38
+ crate::lang_wrapper!(
39
+ Timing,
40
+ "Baml::Ffi::Timing",
41
+ baml_runtime::tracingv2::storage::storage::Timing,
42
+ clone_safe
43
+ );
44
+
45
+ crate::lang_wrapper!(
46
+ StreamTiming,
47
+ "Baml::Ffi::StreamTiming",
48
+ baml_runtime::tracingv2::storage::storage::StreamTiming,
49
+ clone_safe
50
+ );
51
+
52
+ crate::lang_wrapper!(
53
+ FunctionLog,
54
+ "Baml::Ffi::FunctionLog",
55
+ baml_runtime::tracingv2::storage::storage::FunctionLog,
56
+ sync_thread_safe
57
+ );
58
+
59
+ crate::lang_wrapper!(
60
+ LLMCall,
61
+ "Baml::Ffi::LLMCall",
62
+ baml_runtime::tracingv2::storage::storage::LLMCall,
63
+ clone_safe
64
+ );
65
+
66
+ unsafe impl IntoValueFromNative for LLMCall {}
67
+
68
+ unsafe impl IntoValueFromNative for LLMStreamCall {}
69
+ crate::lang_wrapper!(
70
+ LLMStreamCall,
71
+ "Baml::Ffi::LLMStreamCall",
72
+ baml_runtime::tracingv2::storage::storage::LLMStreamCall,
73
+ clone_safe
74
+ );
75
+
76
+ unsafe impl TryConvertOwned for &FunctionLog {}
77
+
78
+ impl Collector {
79
+ pub fn new(args: &[Value]) -> Result<Self> {
80
+ let args = scan_args::<(), (), (), (), _, ()>(args)?;
81
+ let kwargs = get_kwargs::<_, (), (Option<String>,), ()>(args.keywords, &[], &["name"])?;
82
+
83
+ let name = kwargs.optional.0;
84
+ let collector = baml_runtime::tracingv2::storage::storage::Collector::new(name);
85
+ Ok(Self {
86
+ inner: Arc::new(collector),
87
+ })
88
+ }
89
+
90
+ pub fn clear(&self) {
91
+ let _ = self.inner.clear();
92
+ }
93
+
94
+ pub fn logs(&self) -> RArray {
95
+ let function_logs = self.inner.function_logs();
96
+ function_logs
97
+ .iter()
98
+ .map(|inner_function_log| FunctionLog {
99
+ inner: Arc::new(Mutex::new(inner_function_log.clone())),
100
+ })
101
+ .collect()
102
+ }
103
+
104
+ pub fn last(&self) -> Option<FunctionLog> {
105
+ self.inner
106
+ .last_function_log()
107
+ .map(|inner_function_log| FunctionLog {
108
+ inner: Arc::new(Mutex::new(inner_function_log.clone())),
109
+ })
110
+ }
111
+
112
+ pub fn id(&self, function_log_id: String) -> Option<FunctionLog> {
113
+ self.inner
114
+ .function_log_by_id(&baml_ids::FunctionCallId::from_str(&function_log_id).ok()?)
115
+ .map(|inner_function_log| FunctionLog {
116
+ inner: Arc::new(Mutex::new(inner_function_log.clone())),
117
+ })
118
+ }
119
+
120
+ pub fn usage(&self) -> Usage {
121
+ Usage {
122
+ inner: self.inner.usage().into(),
123
+ }
124
+ }
125
+
126
+ pub fn to_s(&self) -> String {
127
+ let logs = self.inner.function_logs();
128
+ let log_ids: Vec<String> = logs.iter().map(|log| log.id().to_string()).collect();
129
+ format!(
130
+ "LogCollector(name={}, function_log_ids=[{}])",
131
+ self.inner.name(),
132
+ log_ids.join(", ")
133
+ )
134
+ }
135
+
136
+ pub fn __function_call_count() -> u32 {
137
+ let span_count = BAML_TRACER.lock().unwrap().function_call_count();
138
+ span_count as u32
139
+ }
140
+
141
+ pub fn __print_storage() {
142
+ let tracer = BAML_TRACER.lock().unwrap();
143
+ println!("Storage: {tracer:#?}");
144
+ }
145
+
146
+ pub fn define_in_ruby(module: &RModule) -> Result<()> {
147
+ let cls = module.define_class("Collector", class::object())?;
148
+
149
+ cls.define_singleton_method("new", function!(Collector::new, -1))?;
150
+ cls.define_method("logs", method!(Collector::logs, 0))?;
151
+ cls.define_method("last", method!(Collector::last, 0))?;
152
+ cls.define_method("id", method!(Collector::id, 1))?;
153
+ cls.define_method("usage", method!(Collector::usage, 0))?;
154
+ cls.define_method("clear", method!(Collector::clear, 0))?;
155
+ cls.define_method("to_s", method!(Collector::to_s, 0))?;
156
+ cls.define_singleton_method(
157
+ "__function_call_count",
158
+ function!(Collector::__function_call_count, 0),
159
+ )?;
160
+ cls.define_singleton_method("__print_storage", function!(Collector::__print_storage, 0))?;
161
+
162
+ Ok(())
163
+ }
164
+ }
165
+
166
+ impl FunctionLog {
167
+ pub fn to_s(&self) -> String {
168
+ // Acquire the lock once and extract all needed data
169
+ let mut guard = self.inner.lock().unwrap();
170
+ let id = guard.id().to_string();
171
+ let function_name = guard.function_name();
172
+ let log_type = guard.log_type().to_string();
173
+ let timing_data = guard.timing().clone();
174
+ let usage_data = guard.usage().clone();
175
+ let calls_data = guard.calls();
176
+ let raw_llm_response = guard.raw_llm_response().unwrap_or("null".to_string());
177
+ // Release the lock by dropping the guard
178
+ drop(guard);
179
+
180
+ // Now process calls without holding the lock
181
+ let calls_str = calls_data
182
+ .into_iter()
183
+ .map(|call| match call {
184
+ baml_runtime::tracingv2::storage::storage::LLMCallKind::Basic(inner) => {
185
+ let llm_call = LLMCall {
186
+ inner: Arc::new(inner.clone()),
187
+ };
188
+ llm_call.to_s()
189
+ }
190
+ baml_runtime::tracingv2::storage::storage::LLMCallKind::Stream(inner) => {
191
+ let stream_call = LLMStreamCall {
192
+ inner: Arc::new(inner.clone()),
193
+ };
194
+ stream_call.to_s()
195
+ }
196
+ })
197
+ .collect::<Vec<_>>()
198
+ .join(", ");
199
+
200
+ // Create timing and usage objects from cloned data
201
+ let timing = Timing {
202
+ inner: timing_data.into(),
203
+ };
204
+ let usage = Usage {
205
+ inner: usage_data.into(),
206
+ };
207
+
208
+ // Format the string with all the extracted data
209
+ format!(
210
+ "FunctionLog(id={}, function_name={}, type={}, timing={}, usage={}, calls=[{}], raw_llm_response={})",
211
+ id,
212
+ function_name,
213
+ log_type,
214
+ timing.to_s(),
215
+ usage.to_s(),
216
+ calls_str,
217
+ raw_llm_response
218
+ )
219
+ }
220
+
221
+ pub fn id(&self) -> String {
222
+ self.inner.lock().unwrap().id().to_string()
223
+ }
224
+
225
+ pub fn function_name(&self) -> String {
226
+ self.inner.lock().unwrap().function_name()
227
+ }
228
+
229
+ pub fn log_type(&self) -> String {
230
+ self.inner.lock().unwrap().log_type().to_string()
231
+ }
232
+
233
+ pub fn timing(&self) -> Timing {
234
+ Timing {
235
+ inner: self.inner.lock().unwrap().timing().into(),
236
+ }
237
+ }
238
+
239
+ pub fn usage(&self) -> Usage {
240
+ Usage {
241
+ inner: self.inner.lock().unwrap().usage().into(),
242
+ }
243
+ }
244
+
245
+ pub fn calls(&self) -> RArray {
246
+ let calls = self.inner.lock().unwrap().calls();
247
+ let array = RArray::new();
248
+
249
+ for call in calls {
250
+ match call {
251
+ baml_runtime::tracingv2::storage::storage::LLMCallKind::Basic(inner) => {
252
+ let llm_call = LLMCall {
253
+ inner: Arc::new(inner.clone()),
254
+ };
255
+ array.push(llm_call).unwrap();
256
+ }
257
+ baml_runtime::tracingv2::storage::storage::LLMCallKind::Stream(inner) => {
258
+ let stream_call = LLMStreamCall {
259
+ inner: Arc::new(inner.clone()),
260
+ };
261
+ array.push(stream_call).unwrap();
262
+ }
263
+ }
264
+ }
265
+
266
+ array
267
+ }
268
+
269
+ pub fn raw_llm_response(&self) -> Option<String> {
270
+ self.inner.lock().unwrap().raw_llm_response()
271
+ }
272
+
273
+ pub fn selected_call(ruby: &Ruby, rb_self: &Self) -> Option<Value> {
274
+ let calls = rb_self.inner.lock().unwrap().calls();
275
+ calls.into_iter().find_map(|call| match call {
276
+ baml_runtime::tracingv2::storage::storage::LLMCallKind::Basic(inner) => {
277
+ if inner.selected {
278
+ Some(
279
+ LLMCall {
280
+ inner: Arc::new(inner.clone()),
281
+ }
282
+ .to_value(ruby)
283
+ .unwrap(),
284
+ )
285
+ } else {
286
+ None
287
+ }
288
+ }
289
+ baml_runtime::tracingv2::storage::storage::LLMCallKind::Stream(inner) => {
290
+ if inner.llm_call.selected {
291
+ let stream_call = LLMStreamCall {
292
+ inner: Arc::new(inner.clone()),
293
+ };
294
+ Some(stream_call.to_value(ruby).unwrap())
295
+ } else {
296
+ None
297
+ }
298
+ }
299
+ })
300
+ }
301
+
302
+ pub fn define_in_ruby(module: &RModule) -> Result<()> {
303
+ let cls = module.define_class("FunctionLog", class::object())?;
304
+
305
+ cls.define_method("to_s", method!(FunctionLog::to_s, 0))?;
306
+ cls.define_method("id", method!(FunctionLog::id, 0))?;
307
+ cls.define_method("function_name", method!(FunctionLog::function_name, 0))?;
308
+ cls.define_method("log_type", method!(FunctionLog::log_type, 0))?;
309
+ cls.define_method("timing", method!(FunctionLog::timing, 0))?;
310
+ cls.define_method("usage", method!(FunctionLog::usage, 0))?;
311
+ cls.define_method("calls", method!(FunctionLog::calls, 0))?;
312
+ cls.define_method(
313
+ "raw_llm_response",
314
+ method!(FunctionLog::raw_llm_response, 0),
315
+ )?;
316
+ cls.define_method("selected_call", method!(FunctionLog::selected_call, 0))?;
317
+
318
+ Ok(())
319
+ }
320
+ }
321
+
322
+ impl Timing {
323
+ pub fn to_s(&self) -> String {
324
+ format!(
325
+ "Timing(start_time_utc_ms={}, duration_ms={})",
326
+ self.inner.start_time_utc_ms,
327
+ self.inner
328
+ .duration_ms
329
+ .map_or("null".to_string(), |v| v.to_string())
330
+ )
331
+ }
332
+
333
+ pub fn start_time_utc_ms(&self) -> i64 {
334
+ self.inner.start_time_utc_ms
335
+ }
336
+
337
+ pub fn duration_ms(&self) -> Option<i64> {
338
+ self.inner.duration_ms
339
+ }
340
+
341
+ pub fn define_in_ruby(module: &RModule) -> Result<()> {
342
+ let cls = module.define_class("Timing", class::object())?;
343
+
344
+ cls.define_method("to_s", method!(Timing::to_s, 0))?;
345
+ cls.define_method("start_time_utc_ms", method!(Timing::start_time_utc_ms, 0))?;
346
+ cls.define_method("duration_ms", method!(Timing::duration_ms, 0))?;
347
+
348
+ Ok(())
349
+ }
350
+
351
+ pub fn into_value(self, ruby: &Ruby) -> crate::Result<Value> {
352
+ serde_magnus::serialize(&self.inner)
353
+ .map_err(|e| Error::new(ruby.exception_runtime_error(), format!("{e:?}")))
354
+ }
355
+ }
356
+
357
+ impl StreamTiming {
358
+ pub fn to_s(&self) -> String {
359
+ format!(
360
+ "StreamTiming(start_time_utc_ms={}, duration_ms={})",
361
+ self.inner.start_time_utc_ms,
362
+ self.inner
363
+ .duration_ms
364
+ .map_or("null".to_string(), |v| v.to_string())
365
+ )
366
+ }
367
+
368
+ pub fn start_time_utc_ms(&self) -> i64 {
369
+ self.inner.start_time_utc_ms
370
+ }
371
+
372
+ pub fn duration_ms(&self) -> Option<i64> {
373
+ self.inner.duration_ms
374
+ }
375
+
376
+ pub fn define_in_ruby(module: &RModule) -> Result<()> {
377
+ let cls = module.define_class("StreamTiming", class::object())?;
378
+
379
+ cls.define_method("to_s", method!(StreamTiming::to_s, 0))?;
380
+ cls.define_method(
381
+ "start_time_utc_ms",
382
+ method!(StreamTiming::start_time_utc_ms, 0),
383
+ )?;
384
+ cls.define_method("duration_ms", method!(StreamTiming::duration_ms, 0))?;
385
+
386
+ Ok(())
387
+ }
388
+ }
389
+
390
+ impl Usage {
391
+ pub fn to_s(&self) -> String {
392
+ format!(
393
+ "Usage(input_tokens={}, output_tokens={}, cached_input_tokens={})",
394
+ self.inner
395
+ .input_tokens
396
+ .map_or_else(|| "null".to_string(), |v| v.to_string()),
397
+ self.inner
398
+ .output_tokens
399
+ .map_or_else(|| "null".to_string(), |v| v.to_string()),
400
+ self.inner
401
+ .cached_input_tokens
402
+ .map_or_else(|| "null".to_string(), |v| v.to_string())
403
+ )
404
+ }
405
+
406
+ pub fn input_tokens(&self) -> Option<i64> {
407
+ self.inner.input_tokens
408
+ }
409
+
410
+ pub fn output_tokens(&self) -> Option<i64> {
411
+ self.inner.output_tokens
412
+ }
413
+
414
+ pub fn cached_input_tokens(&self) -> Option<i64> {
415
+ self.inner.cached_input_tokens
416
+ }
417
+
418
+ pub fn define_in_ruby(module: &RModule) -> Result<()> {
419
+ let cls = module.define_class("Usage", class::object())?;
420
+
421
+ cls.define_method("to_s", method!(Usage::to_s, 0))?;
422
+ cls.define_method("input_tokens", method!(Usage::input_tokens, 0))?;
423
+ cls.define_method("output_tokens", method!(Usage::output_tokens, 0))?;
424
+ cls.define_method(
425
+ "cached_input_tokens",
426
+ method!(Usage::cached_input_tokens, 0),
427
+ )?;
428
+
429
+ Ok(())
430
+ }
431
+ }
432
+
433
+ struct SerializationError {
434
+ position: Vec<String>,
435
+ message: String,
436
+ }
437
+
438
+ unsafe impl TryConvertOwned for &LLMCall {}
439
+
440
+ impl LLMCall {
441
+ pub fn selected(&self) -> bool {
442
+ self.inner.selected
443
+ }
444
+
445
+ pub fn http_request(&self) -> Option<HTTPRequest> {
446
+ self.inner
447
+ .request
448
+ .clone()
449
+ .map(|req| HTTPRequest { inner: req })
450
+ }
451
+
452
+ pub fn http_response(&self) -> Option<HTTPResponse> {
453
+ self.inner
454
+ .response
455
+ .clone()
456
+ .map(|resp| HTTPResponse { inner: resp })
457
+ }
458
+
459
+ pub fn usage(&self) -> Option<Usage> {
460
+ self.inner.usage.clone().map(|u| Usage { inner: u.into() })
461
+ }
462
+
463
+ pub fn timing(&self) -> Timing {
464
+ Timing {
465
+ inner: self.inner.timing.clone().into(),
466
+ }
467
+ }
468
+
469
+ pub fn provider(&self) -> String {
470
+ self.inner.provider.clone()
471
+ }
472
+
473
+ pub fn client_name(&self) -> String {
474
+ self.inner.client_name.clone()
475
+ }
476
+
477
+ pub fn to_s(&self) -> String {
478
+ format!(
479
+ "LLMCall(provider={}, client_name={}, selected={}, usage={}, timing={:?}, http_request={}, http_response={})",
480
+ self.inner.provider,
481
+ self.inner.client_name,
482
+ self.inner.selected,
483
+ self.inner.usage.as_ref().map_or("null".to_string(), |u| format!("{u:?}")),
484
+ self.inner.timing,
485
+ self.inner.request.as_ref().map_or("null".to_string(), |req| format!("{req:?}")),
486
+ self.inner.response.as_ref().map_or("null".to_string(), |resp| format!("{resp:?}"))
487
+ )
488
+ }
489
+
490
+ pub fn to_value(&self, ruby: &Ruby) -> crate::Result<Value> {
491
+ serde_magnus::serialize(&self.inner)
492
+ .map_err(|e| Error::new(ruby.exception_runtime_error(), format!("{e:?}")))
493
+ }
494
+
495
+ pub fn define_in_ruby(module: &RModule) -> Result<()> {
496
+ let cls = module.define_class("LLMCall", class::object())?;
497
+
498
+ cls.define_method("selected", method!(LLMCall::selected, 0))?;
499
+ cls.define_method("http_request", method!(LLMCall::http_request, 0))?;
500
+ cls.define_method("http_response", method!(LLMCall::http_response, 0))?;
501
+ cls.define_method("usage", method!(LLMCall::usage, 0))?;
502
+ cls.define_method("timing", method!(LLMCall::timing, 0))?;
503
+ cls.define_method("provider", method!(LLMCall::provider, 0))?;
504
+ cls.define_method("client_name", method!(LLMCall::client_name, 0))?;
505
+ cls.define_method("to_s", method!(LLMCall::to_s, 0))?;
506
+
507
+ Ok(())
508
+ }
509
+ }
510
+
511
+ // TODO: remove?
512
+ unsafe impl TryConvertOwned for &LLMStreamCall {}
513
+
514
+ impl LLMStreamCall {
515
+ pub fn to_s(&self) -> String {
516
+ format!(
517
+ "LLMStreamCall(provider={}, client_name={}, selected={}, usage={}, timing={:?}, http_request={}, http_response={})",
518
+ self.inner.llm_call.provider,
519
+ self.inner.llm_call.client_name,
520
+ self.inner.llm_call.selected,
521
+ self.inner.llm_call.usage.as_ref().map_or("null".to_string(), |u| format!("{u:?}")),
522
+ self.inner.timing,
523
+ self.inner.llm_call.request.as_ref().map_or("null".to_string(), |req| format!("{req:?}")),
524
+ self.inner.llm_call.response.as_ref().map_or("null".to_string(), |resp| format!("{resp:?}"))
525
+ )
526
+ }
527
+
528
+ pub fn http_request(&self) -> Option<HTTPRequest> {
529
+ self.inner
530
+ .llm_call
531
+ .request
532
+ .clone()
533
+ .map(|req| HTTPRequest { inner: req })
534
+ }
535
+
536
+ pub fn http_response(&self) -> Option<HTTPResponse> {
537
+ self.inner
538
+ .llm_call
539
+ .response
540
+ .clone()
541
+ .map(|resp| HTTPResponse {
542
+ inner: resp.clone(),
543
+ })
544
+ }
545
+
546
+ pub fn provider(&self) -> String {
547
+ self.inner.llm_call.provider.clone()
548
+ }
549
+
550
+ pub fn client_name(&self) -> String {
551
+ self.inner.llm_call.client_name.clone()
552
+ }
553
+
554
+ pub fn selected(&self) -> bool {
555
+ self.inner.llm_call.selected
556
+ }
557
+
558
+ pub fn usage(&self) -> Option<Usage> {
559
+ self.inner
560
+ .llm_call
561
+ .usage
562
+ .clone()
563
+ .map(|u| Usage { inner: u.into() })
564
+ }
565
+
566
+ pub fn timing(&self) -> StreamTiming {
567
+ StreamTiming {
568
+ inner: self.inner.timing.clone().into(),
569
+ }
570
+ }
571
+
572
+ pub fn to_value(&self, ruby: &Ruby) -> crate::Result<Value> {
573
+ // Serialize to Ruby value - handle errors gracefully
574
+ serde_magnus::serialize(&self.inner)
575
+ .map_err(|e| Error::new(ruby.exception_runtime_error(), format!("{e:?}")))
576
+ }
577
+
578
+ pub fn define_in_ruby(module: &RModule) -> Result<()> {
579
+ let cls = module.define_class("LLMStreamCall", class::object())?;
580
+
581
+ cls.define_method("to_s", method!(LLMStreamCall::to_s, 0))?;
582
+ cls.define_method("http_request", method!(LLMStreamCall::http_request, 0))?;
583
+ cls.define_method("http_response", method!(LLMStreamCall::http_response, 0))?;
584
+ cls.define_method("provider", method!(LLMStreamCall::provider, 0))?;
585
+ cls.define_method("client_name", method!(LLMStreamCall::client_name, 0))?;
586
+ cls.define_method("selected", method!(LLMStreamCall::selected, 0))?;
587
+ cls.define_method("usage", method!(LLMStreamCall::usage, 0))?;
588
+ cls.define_method("timing", method!(LLMStreamCall::timing, 0))?;
589
+
590
+ Ok(())
591
+ }
592
+ }
593
+
594
+ pub fn define_all_in_ruby(module: &RModule) -> Result<()> {
595
+ Collector::define_in_ruby(module)?;
596
+ FunctionLog::define_in_ruby(module)?;
597
+ Timing::define_in_ruby(module)?;
598
+ StreamTiming::define_in_ruby(module)?;
599
+ Usage::define_in_ruby(module)?;
600
+ LLMCall::define_in_ruby(module)?;
601
+ LLMStreamCall::define_in_ruby(module)?;
602
+ HTTPRequest::define_in_ruby(module)?;
603
+ HTTPResponse::define_in_ruby(module)?;
604
+ HTTPBody::define_in_ruby(module)?;
605
+
606
+ Ok(())
607
+ }