next_web_ai/chat/observation/
chat_model_observation_documentation.rs1use next_web_core::error::BoxError;
2
3use crate::{
4 observation::{
5 observation::{Context, Observation, ObservationImpl},
6 observation_documentation::{BoxObservationConvention, ObservationDocumentation},
7 observation_registry::ObservationRegistry,
8 },
9 util::key_name::KeyName,
10};
11
12use super::{
13 conventions::ai_observation_attributes::AiObservationAttributes,
14 default_chat_model_observation_convention::DefaultChatModelObservationConvention,
15 observation_convention::ObservationConvention,
16};
17
18#[derive(Debug, PartialEq, Eq)]
19pub enum ChatModelObservationDocumentation {
20 ChatModelOperation,
21 LowCardinalityKeyNames(LowNames),
22 HighCardinalityKeyNames(HighNames),
23}
24
25impl ObservationDocumentation for ChatModelObservationDocumentation {
26 fn observation(
27 &self,
28 custom_convention: Option<BoxObservationConvention>,
29 default_convention: Option<BoxObservationConvention>,
30 context: impl Context + 'static,
31 registry: Box<dyn ObservationRegistry>,
32 ) -> Result<Box<dyn Observation>, BoxError> {
33 if self.default_convention().is_empty() {
34 return Err("No default convention provided for chat model observation".into());
35 }
36
37 let mut observation = ObservationImpl::create_not_started(
38 custom_convention,
39 default_convention,
40 context,
41 Some(registry),
42 );
43
44 if let Some(name) = self.name() {
45 observation.context().set_name(name);
46 }
47
48 if let Some(contextual_name) = self.contextual_name() {
49 observation.contextual_name(contextual_name);
50 }
51
52 Ok(observation)
53 }
54
55 fn default_convention(&self) -> &'static str {
56 std::any::type_name::<DefaultChatModelObservationConvention>()
57 }
58
59 fn low_cardinality_key_names(&self) -> Vec<KeyName> {
60 LowNames::values()
61 }
62
63 fn high_cardinality_key_names(&self) -> Vec<KeyName> {
64 HighNames::values()
65 }
66}
67
68impl ChatModelObservationDocumentation {
69 pub fn value(&self) -> &str {
70 match self {
71 ChatModelObservationDocumentation::LowCardinalityKeyNames(names) => names.value(),
72 ChatModelObservationDocumentation::HighCardinalityKeyNames(names) => names.value(),
73 _ => "",
74 }
75 }
76}
77
78#[derive(Debug, PartialEq, Eq)]
79pub enum LowNames {
80 AiOperationType,
81 AiProvider,
82 RequestModel,
83 ResponseModel,
84}
85
86#[derive(Debug, PartialEq, Eq)]
87pub enum HighNames {
88 RequestFrequencyPenalty,
89 RequestMaxTokens,
90 RequestPresencePenalty,
91 RequestStopSequences,
92 RequestTemperature,
93 RequestToolNames,
94 RequestTopK,
95 RequestTopP,
96 ResponseFinishReasons,
97 ResponseId,
98 UsageInputTokens,
99 UsageOutputTokens,
100 UsageTotalTokens,
101}
102
103impl HighNames {
104 pub fn value(&self) -> &str {
105 match self {
106 HighNames::RequestFrequencyPenalty => {
107 AiObservationAttributes::RequestFrequencyPenalty.value()
108 }
109 HighNames::RequestMaxTokens => AiObservationAttributes::RequestMaxTokens.value(),
110 HighNames::RequestPresencePenalty => {
111 AiObservationAttributes::RequestPresencePenalty.value()
112 }
113 HighNames::RequestStopSequences => {
114 AiObservationAttributes::RequestStopSequences.value()
115 }
116 HighNames::RequestTemperature => AiObservationAttributes::RequestTemperature.value(),
117 HighNames::RequestToolNames => AiObservationAttributes::RequestToolNames.value(),
118 HighNames::RequestTopK => AiObservationAttributes::RequestTopK.value(),
119 HighNames::RequestTopP => AiObservationAttributes::RequestTopP.value(),
120 HighNames::ResponseFinishReasons => {
121 AiObservationAttributes::ResponseFinishReasons.value()
122 }
123 HighNames::ResponseId => AiObservationAttributes::ResponseId.value(),
124 HighNames::UsageInputTokens => AiObservationAttributes::UsageInputTokens.value(),
125 HighNames::UsageOutputTokens => AiObservationAttributes::UsageOutputTokens.value(),
126 HighNames::UsageTotalTokens => AiObservationAttributes::UsageTotalTokens.value(),
127 }
128 }
129
130 pub fn values() -> Vec<KeyName> {
131 vec![
132 KeyName(HighNames::RequestFrequencyPenalty.value().into()),
133 KeyName(HighNames::RequestMaxTokens.value().into()),
134 KeyName(HighNames::RequestPresencePenalty.value().into()),
135 KeyName(HighNames::RequestStopSequences.value().into()),
136 KeyName(HighNames::RequestTemperature.value().into()),
137 KeyName(HighNames::RequestToolNames.value().into()),
138 KeyName(HighNames::RequestTopK.value().into()),
139 KeyName(HighNames::RequestTopP.value().into()),
140 KeyName(HighNames::ResponseFinishReasons.value().into()),
141 KeyName(HighNames::ResponseId.value().into()),
142 KeyName(HighNames::UsageInputTokens.value().into()),
143 KeyName(HighNames::UsageOutputTokens.value().into()),
144 KeyName(HighNames::UsageTotalTokens.value().into()),
145 ]
146 }
147}
148
149impl LowNames {
150 pub fn value(&self) -> &str {
151 match self {
152 LowNames::AiOperationType => AiObservationAttributes::AiOperationType.value(),
153 LowNames::AiProvider => AiObservationAttributes::AiProvider.value(),
154 LowNames::RequestModel => AiObservationAttributes::RequestModel.value(),
155 LowNames::ResponseModel => AiObservationAttributes::ResponseModel.value(),
156 }
157 }
158
159 pub fn values() -> Vec<KeyName> {
160 vec![
161 KeyName(LowNames::AiOperationType.value().into()),
162 KeyName(LowNames::AiProvider.value().into()),
163 KeyName(LowNames::RequestModel.value().into()),
164 KeyName(LowNames::ResponseModel.value().into()),
165 ]
166 }
167}