1use crate::completion::GetTokenUsage;
7use serde::Serialize;
8
9pub trait ProviderRequestExt {
10 type InputMessage: Serialize;
11
12 fn get_input_messages(&self) -> Vec<Self::InputMessage>;
13 fn get_system_prompt(&self) -> Option<String>;
14 fn get_model_name(&self) -> String;
15 fn get_prompt(&self) -> Option<String>;
16}
17
18pub trait ProviderResponseExt {
19 type OutputMessage: Serialize;
20 type Usage: Serialize;
21
22 fn get_response_id(&self) -> Option<String>;
23
24 fn get_response_model_name(&self) -> Option<String>;
25
26 fn get_output_messages(&self) -> Vec<Self::OutputMessage>;
27
28 fn get_text_response(&self) -> Option<String>;
29
30 fn get_usage(&self) -> Option<Self::Usage>;
31}
32
33pub trait SpanCombinator {
36 fn record_token_usage<U>(&self, usage: &U)
37 where
38 U: GetTokenUsage;
39
40 fn record_response_metadata<R>(&self, response: &R)
41 where
42 R: ProviderResponseExt;
43
44 fn record_model_input<T>(&self, messages: &T)
45 where
46 T: Serialize;
47
48 fn record_model_output<T>(&self, messages: &T)
49 where
50 T: Serialize;
51}
52
53impl SpanCombinator for tracing::Span {
54 fn record_token_usage<U>(&self, usage: &U)
55 where
56 U: GetTokenUsage,
57 {
58 if let Some(usage) = usage.token_usage() {
59 self.record("gen_ai.usage.input_tokens", usage.input_tokens);
60 self.record("gen_ai.usage.output_tokens", usage.output_tokens);
61 }
62 }
63
64 fn record_response_metadata<R>(&self, response: &R)
65 where
66 R: ProviderResponseExt,
67 {
68 if let Some(id) = response.get_response_id() {
69 self.record("gen_ai.response.id", id);
70 }
71
72 if let Some(model_name) = response.get_response_model_name() {
73 self.record("gen_ai.response.model_name", model_name);
74 }
75 }
76
77 fn record_model_input<T>(&self, input: &T)
78 where
79 T: Serialize,
80 {
81 let input_as_json_string =
82 serde_json::to_string(input).expect("Serializing a Rust type to JSON should not break");
83
84 self.record("gen_ai.input.messages", input_as_json_string);
85 }
86
87 fn record_model_output<T>(&self, input: &T)
88 where
89 T: Serialize,
90 {
91 let input_as_json_string =
92 serde_json::to_string(input).expect("Serializing a Rust type to JSON should not break");
93
94 self.record("gen_ai.input.messages", input_as_json_string);
95 }
96}