ums.utils.types
This represents the basic types used to interact with the management. The types are implemented using pydantic. It provides validation, allow JSON serialization and works well with FastAPI which is used internally for the http request between the agents and the management.
Example
ex = AgentMessage(
id="ex1",
riddle={
"context":"Example 1",
"question":"Get the name of the person."
},
data=[
RiddleData(
type=RiddleDataType.TEXT,
file_plain="./cv.txt"
)
]
)
ex.status.extract.required = False
{
"id": "ex1",
"sub_ids": [],
"riddle": {
"context": "Example 1",
"question": "Get the name of the person.",
"solutions_before": []
},
"solution": null,
"data": [
{
"type": "text",
"file_plain": "/ums-agenten/share/cv.txt",
"file_extracted": null
}
],
"status": {
"extract": {
"required": false,
"finished": false
},
"solve": {
"required": true,
"finished": false
},
"validate": {
"required": true,
"finished": false
},
"trial": 0,
"solved": false
}
}
ex.solution = RiddleSolution(
solution="Otto",
explanation="Written in line 6 after 'Name:'"
)
{
...
"solution": {
"solution": "Otto",
"explanation": "Written in line 6 after 'Name:'",
"used_data": [],
"accepted": false,
"review": null
},
...
}
1# Agenten Plattform 2# 3# (c) 2024 Magnus Bender 4# Institute of Humanities-Centered Artificial Intelligence (CHAI) 5# Universitaet Hamburg 6# https://www.chai.uni-hamburg.de/~bender 7# 8# source code released under the terms of GNU Public License Version 3 9# https://www.gnu.org/licenses/gpl-3.0.txt 10 11""" 12 This represents the basic types used to interact with the management. 13 The types are implemented using [pydantic](https://docs.pydantic.dev/). 14 It provides validation, allow JSON serialization and works well with [FastAPI](https://fastapi.tiangolo.com/) which is used internally for the http request between the agents and the management. 15 16 ### Example 17 18 ```python 19 ex = AgentMessage( 20 id="ex1", 21 riddle={ 22 "context":"Example 1", 23 "question":"Get the name of the person." 24 }, 25 data=[ 26 RiddleData( 27 type=RiddleDataType.TEXT, 28 file_plain="./cv.txt" 29 ) 30 ] 31 ) 32 ex.status.extract.required = False 33 ``` 34 ```json 35 { 36 "id": "ex1", 37 "sub_ids": [], 38 "riddle": { 39 "context": "Example 1", 40 "question": "Get the name of the person.", 41 "solutions_before": [] 42 }, 43 "solution": null, 44 "data": [ 45 { 46 "type": "text", 47 "file_plain": "/ums-agenten/share/cv.txt", 48 "file_extracted": null 49 } 50 ], 51 "status": { 52 "extract": { 53 "required": false, 54 "finished": false 55 }, 56 "solve": { 57 "required": true, 58 "finished": false 59 }, 60 "validate": { 61 "required": true, 62 "finished": false 63 }, 64 "trial": 0, 65 "solved": false 66 } 67 } 68 ``` 69 ```python 70 ex.solution = RiddleSolution( 71 solution="Otto", 72 explanation="Written in line 6 after 'Name:'" 73 ) 74 ``` 75 ```json 76 { 77 ... 78 "solution": { 79 "solution": "Otto", 80 "explanation": "Written in line 6 after 'Name:'", 81 "used_data": [], 82 "accepted": false, 83 "review": null 84 }, 85 ... 86 } 87 ``` 88 89""" 90 91import os 92 93from enum import Enum 94 95from typing import List, Any 96from typing_extensions import Annotated 97 98from pydantic import ( 99 BaseModel, 100 ValidationError, ValidationInfo, 101 ValidatorFunctionWrapHandler 102) 103from pydantic.functional_validators import WrapValidator, AfterValidator 104 105from ums.utils.const import SHARE_PATH 106 107class RiddleInformation(BaseModel): 108 """ 109 This is the basic class used as superclass for all message and infos 110 about a riddle. 111 """ 112 113class RiddleDataType(Enum): 114 """ 115 Enum for the three types of data used in a riddle. 116 """ 117 118 TEXT = "text" 119 IMAGE = "image" 120 AUDIO = "audio" 121 122def _check_data_file(file_name:str) -> str: 123 if not file_name.startswith('/'): 124 file_name = os.path.join(SHARE_PATH, file_name) 125 126 assert file_name.startswith(SHARE_PATH), "The data file needs to be in {}!".format(SHARE_PATH) 127 128 file_name = os.path.realpath(file_name, strict=False) 129 130 assert os.path.isfile(file_name), "The data file {} does not exist!".format(file_name) 131 132 return file_name 133 134def _ignore_file_missing( 135 v: Any, handler: ValidatorFunctionWrapHandler, info: ValidationInfo 136 ) -> str: 137 try: 138 return handler(v) 139 except ValidationError: 140 if not info.context is None and \ 141 "require_file_exists" in info.context and \ 142 info.context["require_file_exists"] == False and \ 143 isinstance(v, str): 144 return "missing:{}".format(v) 145 else: 146 raise 147 148class RiddleData(RiddleInformation): 149 150 """ 151 A data item to be used to solve the riddle 152 """ 153 154 type: RiddleDataType 155 """ 156 The type of the data item. 157 """ 158 159 file_plain: Annotated[str, AfterValidator(_check_data_file), WrapValidator(_ignore_file_missing)] 160 """ 161 The plain file (as path to file system) without any processing. 162 163 The path will be validated and must start with `SHARE_PATH` (or be relative to `SHARE_PATH`). 164 The file must exist. 165 """ 166 167 file_extracted: Annotated[str, AfterValidator(_check_data_file), WrapValidator(_ignore_file_missing)] | None = None 168 """ 169 The processed files (as path to file system), i.e., a schematic file containing all extracted informations. 170 171 The path will be validated and must start with `SHARE_PATH` (or be relative to `SHARE_PATH`). 172 The file must exist. 173 """ 174 175 176 177class RiddleSolution(RiddleInformation): 178 """ 179 A solution of a riddle. 180 """ 181 182 solution: str 183 """ 184 The textual value of the solution. 185 """ 186 187 explanation: str 188 """ 189 An explanation of the solution. 190 """ 191 192 used_data: List[RiddleData] = [] 193 """ 194 The data items used to create the solution (optional). 195 """ 196 197 accepted : bool = False 198 """ 199 If the solution is accepted by validator/ gatekeeper. 200 """ 201 202 review: str | None = None 203 """ 204 A review of the solution (if None: not tried to validate) 205 """ 206 207class Riddle(RiddleInformation): 208 """ 209 The riddle (the task description and possibly a solution) 210 """ 211 212 context: str 213 """ 214 The context of the riddle (as textual string). 215 """ 216 217 question: str 218 """ 219 The actual main question of the riddle (as textual string). 220 """ 221 222 solutions_before: List[RiddleSolution] = [] 223 """ 224 If already tried to solve this riddle before, the (not accepted) solutions are stored here 225 """ 226 227class RiddleSubStatus(RiddleInformation): 228 """ 229 The sub status for each possible step a riddle may go though. 230 """ 231 232 required: bool = True 233 """ 234 Is this step required (i.e., requested) 235 """ 236 237 finished: bool = False 238 """ 239 Was this step already executed. 240 """ 241 242class RiddleStatus(RiddleInformation): 243 """ 244 The status of a riddle, will be mostly changed by Management when the riddle is sent to different agents while solving it. 245 """ 246 247 extract: RiddleSubStatus = RiddleSubStatus() 248 """ 249 The first extract step (image, text, audio -> more sematic data) 250 251 The `RiddleData` items in `AgentMessage.data` shall have `file_extracted` afterwards. 252 """ 253 254 solve: RiddleSubStatus = RiddleSubStatus() 255 """ 256 The *main* solving step. 257 258 `AgentMessage.solution` shall be an `RiddleSolution` afterwards. 259 """ 260 261 validate: RiddleSubStatus = RiddleSubStatus() 262 """ 263 The validation step, i.e., does the gatekeeper accept the solution in `AgentMessage.solution`. 264 """ 265 266 trial: int = 0 267 """ 268 A counter for the number of trials. 269 Each time the gatekeeper does not accept a solution of this riddle, the value is incremented. 270 """ 271 272 solved: bool = False 273 """ 274 True, after the gatekeeper accepts the solution at `AgentMessage.solution` 275 """ 276 277class AgentMessage(RiddleInformation): 278 """ 279 The basic message, which is sent be the agent and the management. 280 The objects will be JSON en- and decoded. 281 """ 282 283 id: str 284 """ 285 The riddle id, e.g., ``ex1`` 286 This is a unique string and identifies the riddle. 287 """ 288 289 sub_ids: List[str] = [] 290 """ 291 There might be cases, when an agent decided to split in riddle in multiple *smaller* steps. 292 Each *sub* riddle will then get its own id (i.e., ``ex1-sub1``) while the sub id is added here as reference. 293 """ 294 295 riddle: Riddle 296 """ 297 The riddle to solve. 298 """ 299 300 solution: RiddleSolution | None = None 301 """ 302 The solution of the riddle (or empty if no solution available) 303 """ 304 305 data: List[RiddleData] = [] 306 """ 307 The data to get the solution from. 308 """ 309 310 status: RiddleStatus = RiddleStatus() 311 """ 312 The status of the riddle. 313 """ 314 315class AgentResponse(RiddleInformation): 316 """ 317 Returned by the management when receiving an `AgentMessage`. 318 """ 319 320 count : int 321 """ 322 The count of the message (overall numeric id). 323 """ 324 325 msg: str|None = None 326 """ 327 An additional message. 328 """ 329 330 error: bool = False 331 """ 332 If an error occurred. 333 """ 334 335 error_msg: str|None = None 336 """ 337 Error message (if `error` ) 338 """ 339 340class MessageDbRow(BaseModel): 341 """ 342 Object representing a database row. 343 """ 344 345 count : int 346 """ 347 The count (primary key) of the item. 348 """ 349 350 sender : str 351 """ 352 The sender of the message. 353 """ 354 355 recipient : str 356 """ 357 The recipient of the message 358 """ 359 360 time : int 361 """ 362 The time (unix timestamp) the message was received/ sent. 363 """ 364 365 message : AgentMessage 366 """ 367 The message received/ sent. 368 """ 369 370 processed : bool 371 """ 372 Did the management process the message, i.e., did the tasks necessary for this message (mostly only relevant for received messages). 373 """ 374 375 solution : bool|None = None 376 """ 377 Does this message contain a valid solution? 378 True if contains valid solution, False if solution not valid, Null/None if not applicable 379 """
108class RiddleInformation(BaseModel): 109 """ 110 This is the basic class used as superclass for all message and infos 111 about a riddle. 112 """
This is the basic class used as superclass for all message and infos about a riddle.
Inherited Members
- pydantic.main.BaseModel
- BaseModel
- model_extra
- model_fields_set
- model_construct
- model_copy
- model_dump
- model_dump_json
- model_json_schema
- model_parametrized_name
- model_post_init
- model_rebuild
- model_validate
- model_validate_json
- model_validate_strings
- dict
- json
- parse_obj
- parse_raw
- parse_file
- from_orm
- construct
- copy
- schema
- schema_json
- validate
- update_forward_refs
114class RiddleDataType(Enum): 115 """ 116 Enum for the three types of data used in a riddle. 117 """ 118 119 TEXT = "text" 120 IMAGE = "image" 121 AUDIO = "audio"
Enum for the three types of data used in a riddle.
Inherited Members
- enum.Enum
- name
- value
149class RiddleData(RiddleInformation): 150 151 """ 152 A data item to be used to solve the riddle 153 """ 154 155 type: RiddleDataType 156 """ 157 The type of the data item. 158 """ 159 160 file_plain: Annotated[str, AfterValidator(_check_data_file), WrapValidator(_ignore_file_missing)] 161 """ 162 The plain file (as path to file system) without any processing. 163 164 The path will be validated and must start with `SHARE_PATH` (or be relative to `SHARE_PATH`). 165 The file must exist. 166 """ 167 168 file_extracted: Annotated[str, AfterValidator(_check_data_file), WrapValidator(_ignore_file_missing)] | None = None 169 """ 170 The processed files (as path to file system), i.e., a schematic file containing all extracted informations. 171 172 The path will be validated and must start with `SHARE_PATH` (or be relative to `SHARE_PATH`). 173 The file must exist. 174 """
A data item to be used to solve the riddle
The plain file (as path to file system) without any processing.
The path will be validated and must start with SHARE_PATH
(or be relative to SHARE_PATH
).
The file must exist.
The processed files (as path to file system), i.e., a schematic file containing all extracted informations.
The path will be validated and must start with SHARE_PATH
(or be relative to SHARE_PATH
).
The file must exist.
Inherited Members
- pydantic.main.BaseModel
- BaseModel
- model_extra
- model_fields_set
- model_construct
- model_copy
- model_dump
- model_dump_json
- model_json_schema
- model_parametrized_name
- model_post_init
- model_rebuild
- model_validate
- model_validate_json
- model_validate_strings
- dict
- json
- parse_obj
- parse_raw
- parse_file
- from_orm
- construct
- copy
- schema
- schema_json
- validate
- update_forward_refs
178class RiddleSolution(RiddleInformation): 179 """ 180 A solution of a riddle. 181 """ 182 183 solution: str 184 """ 185 The textual value of the solution. 186 """ 187 188 explanation: str 189 """ 190 An explanation of the solution. 191 """ 192 193 used_data: List[RiddleData] = [] 194 """ 195 The data items used to create the solution (optional). 196 """ 197 198 accepted : bool = False 199 """ 200 If the solution is accepted by validator/ gatekeeper. 201 """ 202 203 review: str | None = None 204 """ 205 A review of the solution (if None: not tried to validate) 206 """
A solution of a riddle.
Inherited Members
- pydantic.main.BaseModel
- BaseModel
- model_extra
- model_fields_set
- model_construct
- model_copy
- model_dump
- model_dump_json
- model_json_schema
- model_parametrized_name
- model_post_init
- model_rebuild
- model_validate
- model_validate_json
- model_validate_strings
- dict
- json
- parse_obj
- parse_raw
- parse_file
- from_orm
- construct
- copy
- schema
- schema_json
- validate
- update_forward_refs
208class Riddle(RiddleInformation): 209 """ 210 The riddle (the task description and possibly a solution) 211 """ 212 213 context: str 214 """ 215 The context of the riddle (as textual string). 216 """ 217 218 question: str 219 """ 220 The actual main question of the riddle (as textual string). 221 """ 222 223 solutions_before: List[RiddleSolution] = [] 224 """ 225 If already tried to solve this riddle before, the (not accepted) solutions are stored here 226 """
The riddle (the task description and possibly a solution)
If already tried to solve this riddle before, the (not accepted) solutions are stored here
Inherited Members
- pydantic.main.BaseModel
- BaseModel
- model_extra
- model_fields_set
- model_construct
- model_copy
- model_dump
- model_dump_json
- model_json_schema
- model_parametrized_name
- model_post_init
- model_rebuild
- model_validate
- model_validate_json
- model_validate_strings
- dict
- json
- parse_obj
- parse_raw
- parse_file
- from_orm
- construct
- copy
- schema
- schema_json
- validate
- update_forward_refs
228class RiddleSubStatus(RiddleInformation): 229 """ 230 The sub status for each possible step a riddle may go though. 231 """ 232 233 required: bool = True 234 """ 235 Is this step required (i.e., requested) 236 """ 237 238 finished: bool = False 239 """ 240 Was this step already executed. 241 """
The sub status for each possible step a riddle may go though.
Inherited Members
- pydantic.main.BaseModel
- BaseModel
- model_extra
- model_fields_set
- model_construct
- model_copy
- model_dump
- model_dump_json
- model_json_schema
- model_parametrized_name
- model_post_init
- model_rebuild
- model_validate
- model_validate_json
- model_validate_strings
- dict
- json
- parse_obj
- parse_raw
- parse_file
- from_orm
- construct
- copy
- schema
- schema_json
- validate
- update_forward_refs
243class RiddleStatus(RiddleInformation): 244 """ 245 The status of a riddle, will be mostly changed by Management when the riddle is sent to different agents while solving it. 246 """ 247 248 extract: RiddleSubStatus = RiddleSubStatus() 249 """ 250 The first extract step (image, text, audio -> more sematic data) 251 252 The `RiddleData` items in `AgentMessage.data` shall have `file_extracted` afterwards. 253 """ 254 255 solve: RiddleSubStatus = RiddleSubStatus() 256 """ 257 The *main* solving step. 258 259 `AgentMessage.solution` shall be an `RiddleSolution` afterwards. 260 """ 261 262 validate: RiddleSubStatus = RiddleSubStatus() 263 """ 264 The validation step, i.e., does the gatekeeper accept the solution in `AgentMessage.solution`. 265 """ 266 267 trial: int = 0 268 """ 269 A counter for the number of trials. 270 Each time the gatekeeper does not accept a solution of this riddle, the value is incremented. 271 """ 272 273 solved: bool = False 274 """ 275 True, after the gatekeeper accepts the solution at `AgentMessage.solution` 276 """
The status of a riddle, will be mostly changed by Management when the riddle is sent to different agents while solving it.
The first extract step (image, text, audio -> more sematic data)
The RiddleData
items in AgentMessage.data
shall have file_extracted
afterwards.
The main solving step.
AgentMessage.solution
shall be an RiddleSolution
afterwards.
1383 @classmethod 1384 @typing_extensions.deprecated('The `validate` method is deprecated; use `model_validate` instead.', category=None) 1385 def validate(cls, value: Any) -> Self: # noqa: D102 1386 warnings.warn( 1387 'The `validate` method is deprecated; use `model_validate` instead.', category=PydanticDeprecatedSince20 1388 ) 1389 return cls.model_validate(value)
The validation step, i.e., does the gatekeeper accept the solution in AgentMessage.solution
.
A counter for the number of trials. Each time the gatekeeper does not accept a solution of this riddle, the value is incremented.
Inherited Members
- pydantic.main.BaseModel
- BaseModel
- model_extra
- model_fields_set
- model_construct
- model_copy
- model_dump
- model_dump_json
- model_json_schema
- model_parametrized_name
- model_post_init
- model_rebuild
- model_validate
- model_validate_json
- model_validate_strings
- dict
- json
- parse_obj
- parse_raw
- parse_file
- from_orm
- construct
- copy
- schema
- schema_json
- update_forward_refs
278class AgentMessage(RiddleInformation): 279 """ 280 The basic message, which is sent be the agent and the management. 281 The objects will be JSON en- and decoded. 282 """ 283 284 id: str 285 """ 286 The riddle id, e.g., ``ex1`` 287 This is a unique string and identifies the riddle. 288 """ 289 290 sub_ids: List[str] = [] 291 """ 292 There might be cases, when an agent decided to split in riddle in multiple *smaller* steps. 293 Each *sub* riddle will then get its own id (i.e., ``ex1-sub1``) while the sub id is added here as reference. 294 """ 295 296 riddle: Riddle 297 """ 298 The riddle to solve. 299 """ 300 301 solution: RiddleSolution | None = None 302 """ 303 The solution of the riddle (or empty if no solution available) 304 """ 305 306 data: List[RiddleData] = [] 307 """ 308 The data to get the solution from. 309 """ 310 311 status: RiddleStatus = RiddleStatus() 312 """ 313 The status of the riddle. 314 """
The basic message, which is sent be the agent and the management. The objects will be JSON en- and decoded.
There might be cases, when an agent decided to split in riddle in multiple smaller steps.
Each sub riddle will then get its own id (i.e., ex1-sub1
) while the sub id is added here as reference.
Inherited Members
- pydantic.main.BaseModel
- BaseModel
- model_extra
- model_fields_set
- model_construct
- model_copy
- model_dump
- model_dump_json
- model_json_schema
- model_parametrized_name
- model_post_init
- model_rebuild
- model_validate
- model_validate_json
- model_validate_strings
- dict
- json
- parse_obj
- parse_raw
- parse_file
- from_orm
- construct
- copy
- schema
- schema_json
- validate
- update_forward_refs
316class AgentResponse(RiddleInformation): 317 """ 318 Returned by the management when receiving an `AgentMessage`. 319 """ 320 321 count : int 322 """ 323 The count of the message (overall numeric id). 324 """ 325 326 msg: str|None = None 327 """ 328 An additional message. 329 """ 330 331 error: bool = False 332 """ 333 If an error occurred. 334 """ 335 336 error_msg: str|None = None 337 """ 338 Error message (if `error` ) 339 """
Returned by the management when receiving an AgentMessage
.
Inherited Members
- pydantic.main.BaseModel
- BaseModel
- model_extra
- model_fields_set
- model_construct
- model_copy
- model_dump
- model_dump_json
- model_json_schema
- model_parametrized_name
- model_post_init
- model_rebuild
- model_validate
- model_validate_json
- model_validate_strings
- dict
- json
- parse_obj
- parse_raw
- parse_file
- from_orm
- construct
- copy
- schema
- schema_json
- validate
- update_forward_refs
341class MessageDbRow(BaseModel): 342 """ 343 Object representing a database row. 344 """ 345 346 count : int 347 """ 348 The count (primary key) of the item. 349 """ 350 351 sender : str 352 """ 353 The sender of the message. 354 """ 355 356 recipient : str 357 """ 358 The recipient of the message 359 """ 360 361 time : int 362 """ 363 The time (unix timestamp) the message was received/ sent. 364 """ 365 366 message : AgentMessage 367 """ 368 The message received/ sent. 369 """ 370 371 processed : bool 372 """ 373 Did the management process the message, i.e., did the tasks necessary for this message (mostly only relevant for received messages). 374 """ 375 376 solution : bool|None = None 377 """ 378 Does this message contain a valid solution? 379 True if contains valid solution, False if solution not valid, Null/None if not applicable 380 """
Object representing a database row.
Did the management process the message, i.e., did the tasks necessary for this message (mostly only relevant for received messages).
Does this message contain a valid solution? True if contains valid solution, False if solution not valid, Null/None if not applicable
Inherited Members
- pydantic.main.BaseModel
- BaseModel
- model_extra
- model_fields_set
- model_construct
- model_copy
- model_dump
- model_dump_json
- model_json_schema
- model_parametrized_name
- model_post_init
- model_rebuild
- model_validate
- model_validate_json
- model_validate_strings
- dict
- json
- parse_obj
- parse_raw
- parse_file
- from_orm
- construct
- copy
- schema
- schema_json
- validate
- update_forward_refs