# Copyright 2025 - Oumi## Licensed under the Apache License, Version 2.0 (the "License");# you may not use this file except in compliance with the License.# You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License.fromtypingimportAny,Optionalfromtyping_extensionsimportoverridefromoumi.core.types.conversationimportConversation,Message,Role,TemplatedMessagefromoumi.judges.base_judgeimportBaseJudge,BaseJudgeOutputfromoumi.utils.str_utilsimportstr_to_bool
[docs]classOumiJudgeInput(TemplatedMessage):role:Role=Role.USERtemplate:str="""<request>{{ request }}</request>{% if context %}<context>{{ context }}</context>{% endif %}{% if response %}<response>{{ response }}</response>{% endif %}"""request:strresponse:Optional[str]=Nonecontext:Optional[str]=None
[docs]classOumiJudgeOutput(BaseJudgeOutput):role:Role=Role.ASSISTANTtemplate:str=("<explanation>{{explanation}}</explanation><judgement>{{judgement}}</judgement>")judgement:Optional[str]=Noneexplanation:Optional[str]=None@property@overridedeflabel(self):"""Convert the judgement to a boolean or Likert scale label."""ifself.judgement:ifself.judgement.isdigit():returnint(self.judgement)try:returnstr_to_bool(self.judgement)exceptValueError:returnNonereturnNone
[docs]classOumiXmlJudge(BaseJudge):def_transform_conversation_input(self,conversation:Conversation)->OumiJudgeInput:user_prompt:Optional[Message]=conversation.last_message(Role.USER)assistant_prompt:Optional[Message]=conversation.last_message(Role.ASSISTANT)ifuser_promptisnotNone:ifnotuser_prompt.contains_text_content_items_only():raiseValueError("User message contains non-text content!")request:str=user_prompt.compute_flattened_text_content()else:raiseValueError("No user prompt found in conversation")response:Optional[str]=Noneifassistant_promptisnotNone:ifnotassistant_prompt.contains_text_content_items_only():raiseValueError("Assistant message contains non-text content!")response=assistant_prompt.compute_flattened_text_content()else:response=NonereturnOumiJudgeInput(request=request,response=response)def_transform_dict_input(self,raw_input:dict[str,Any])->OumiJudgeInput:returnOumiJudgeInput(**raw_input)def_transform_model_output(self,model_output)->Optional[OumiJudgeOutput]:returnOumiJudgeOutput.from_xml_output(model_output)