|
1 | 1 | """Models for REST API requests.""" |
2 | 2 |
|
| 3 | +# pylint: disable=too-many-lines |
| 4 | + |
3 | 5 | from enum import Enum |
4 | 6 | from typing import Any, Optional, Self |
5 | 7 |
|
@@ -935,3 +937,213 @@ def validate_authorization_header_values( |
935 | 937 | "File-path based secrets are only supported in static YAML config." |
936 | 938 | ) |
937 | 939 | return value |
| 940 | + |
| 941 | + |
| 942 | +class VectorStoreCreateRequest(BaseModel): |
| 943 | + """Model representing a request to create a vector store. |
| 944 | +
|
| 945 | + Attributes: |
| 946 | + name: Name of the vector store. |
| 947 | + embedding_model: Optional embedding model to use. |
| 948 | + embedding_dimension: Optional embedding dimension. |
| 949 | + chunking_strategy: Optional chunking strategy configuration. |
| 950 | + provider_id: Optional vector store provider identifier. |
| 951 | + metadata: Optional metadata dictionary for storing session information. |
| 952 | + """ |
| 953 | + |
| 954 | + name: str = Field( |
| 955 | + ..., |
| 956 | + description="Name of the vector store", |
| 957 | + examples=["my_vector_store"], |
| 958 | + min_length=1, |
| 959 | + max_length=256, |
| 960 | + ) |
| 961 | + |
| 962 | + embedding_model: Optional[str] = Field( |
| 963 | + None, |
| 964 | + description="Embedding model to use for the vector store", |
| 965 | + examples=["text-embedding-ada-002"], |
| 966 | + ) |
| 967 | + |
| 968 | + embedding_dimension: Optional[int] = Field( |
| 969 | + None, |
| 970 | + description="Dimension of the embedding vectors", |
| 971 | + examples=[1536], |
| 972 | + gt=0, |
| 973 | + ) |
| 974 | + |
| 975 | + chunking_strategy: Optional[dict[str, Any]] = Field( |
| 976 | + None, |
| 977 | + description="Chunking strategy configuration", |
| 978 | + examples=[{"type": "fixed", "chunk_size": 512, "chunk_overlap": 50}], |
| 979 | + ) |
| 980 | + |
| 981 | + provider_id: Optional[str] = Field( |
| 982 | + None, |
| 983 | + description="Vector store provider identifier", |
| 984 | + examples=["rhdh-docs"], |
| 985 | + ) |
| 986 | + |
| 987 | + metadata: Optional[dict[str, Any]] = Field( |
| 988 | + None, |
| 989 | + description="Metadata dictionary for storing session information", |
| 990 | + examples=[{"user_id": "user123", "session_id": "sess456"}], |
| 991 | + ) |
| 992 | + |
| 993 | + model_config = { |
| 994 | + "extra": "forbid", |
| 995 | + "json_schema_extra": { |
| 996 | + "examples": [ |
| 997 | + { |
| 998 | + "name": "my_vector_store", |
| 999 | + "embedding_model": "text-embedding-ada-002", |
| 1000 | + "embedding_dimension": 1536, |
| 1001 | + "provider_id": "rhdh-docs", |
| 1002 | + "metadata": {"user_id": "user123"}, |
| 1003 | + }, |
| 1004 | + ] |
| 1005 | + }, |
| 1006 | + } |
| 1007 | + |
| 1008 | + |
| 1009 | +class VectorStoreUpdateRequest(BaseModel): |
| 1010 | + """Model representing a request to update a vector store. |
| 1011 | +
|
| 1012 | + Attributes: |
| 1013 | + name: New name for the vector store. |
| 1014 | + expires_at: Optional expiration timestamp. |
| 1015 | + metadata: Optional metadata dictionary for storing session information. |
| 1016 | + """ |
| 1017 | + |
| 1018 | + name: Optional[str] = Field( |
| 1019 | + None, |
| 1020 | + description="New name for the vector store", |
| 1021 | + examples=["updated_vector_store"], |
| 1022 | + min_length=1, |
| 1023 | + max_length=256, |
| 1024 | + ) |
| 1025 | + |
| 1026 | + expires_at: Optional[int] = Field( |
| 1027 | + None, |
| 1028 | + description="Unix timestamp when the vector store should expire", |
| 1029 | + examples=[1735689600], |
| 1030 | + gt=0, |
| 1031 | + ) |
| 1032 | + |
| 1033 | + metadata: Optional[dict[str, Any]] = Field( |
| 1034 | + None, |
| 1035 | + description="Metadata dictionary for storing session information", |
| 1036 | + examples=[{"user_id": "user123", "session_id": "sess456"}], |
| 1037 | + ) |
| 1038 | + |
| 1039 | + model_config = { |
| 1040 | + "extra": "forbid", |
| 1041 | + "json_schema_extra": { |
| 1042 | + "examples": [ |
| 1043 | + { |
| 1044 | + "name": "updated_vector_store", |
| 1045 | + "expires_at": 1735689600, |
| 1046 | + "metadata": {"user_id": "user123"}, |
| 1047 | + }, |
| 1048 | + ] |
| 1049 | + }, |
| 1050 | + } |
| 1051 | + |
| 1052 | + @model_validator(mode="after") |
| 1053 | + def check_at_least_one_field(self) -> Self: |
| 1054 | + """Ensure at least one field is provided for update. |
| 1055 | +
|
| 1056 | + Raises: |
| 1057 | + ValueError: If all fields are None (empty update). |
| 1058 | +
|
| 1059 | + Returns: |
| 1060 | + Self: The validated model instance. |
| 1061 | + """ |
| 1062 | + if self.name is None and self.expires_at is None and self.metadata is None: |
| 1063 | + raise ValueError( |
| 1064 | + "At least one field must be provided: name, expires_at, or metadata" |
| 1065 | + ) |
| 1066 | + return self |
| 1067 | + |
| 1068 | + |
| 1069 | +class VectorStoreFileCreateRequest(BaseModel): |
| 1070 | + """Model representing a request to add a file to a vector store. |
| 1071 | +
|
| 1072 | + Attributes: |
| 1073 | + file_id: ID of the file to add to the vector store. |
| 1074 | + attributes: Optional metadata key-value pairs (max 16 pairs). |
| 1075 | + chunking_strategy: Optional chunking strategy configuration. |
| 1076 | + """ |
| 1077 | + |
| 1078 | + file_id: str = Field( |
| 1079 | + ..., |
| 1080 | + description="ID of the file to add to the vector store", |
| 1081 | + examples=["file-abc123"], |
| 1082 | + min_length=1, |
| 1083 | + ) |
| 1084 | + |
| 1085 | + attributes: Optional[dict[str, str | float | bool]] = Field( |
| 1086 | + None, |
| 1087 | + description=( |
| 1088 | + "Set of up to 16 key-value pairs for storing additional information. " |
| 1089 | + "Keys: strings (max 64 chars). Values: strings (max 512 chars), booleans, or numbers." |
| 1090 | + ), |
| 1091 | + examples=[ |
| 1092 | + {"created_at": "2026-04-04T15:20:00Z", "updated_at": "2026-04-04T15:20:00Z"} |
| 1093 | + ], |
| 1094 | + ) |
| 1095 | + |
| 1096 | + chunking_strategy: Optional[dict[str, Any]] = Field( |
| 1097 | + None, |
| 1098 | + description="Chunking strategy configuration for this file", |
| 1099 | + examples=[{"type": "fixed", "chunk_size": 512, "chunk_overlap": 50}], |
| 1100 | + ) |
| 1101 | + |
| 1102 | + model_config = { |
| 1103 | + "extra": "forbid", |
| 1104 | + "json_schema_extra": { |
| 1105 | + "examples": [ |
| 1106 | + { |
| 1107 | + "file_id": "file-abc123", |
| 1108 | + "attributes": {"created_at": "2026-04-04T15:20:00Z"}, |
| 1109 | + "chunking_strategy": {"type": "fixed", "chunk_size": 512}, |
| 1110 | + }, |
| 1111 | + ] |
| 1112 | + }, |
| 1113 | + } |
| 1114 | + |
| 1115 | + @field_validator("attributes") |
| 1116 | + @classmethod |
| 1117 | + def validate_attributes( |
| 1118 | + cls, value: Optional[dict[str, str | float | bool]] |
| 1119 | + ) -> Optional[dict[str, str | float | bool]]: |
| 1120 | + """Validate attributes field constraints. |
| 1121 | +
|
| 1122 | + Ensures: |
| 1123 | + - Maximum 16 key-value pairs |
| 1124 | + - Keys are max 64 characters |
| 1125 | + - String values are max 512 characters |
| 1126 | +
|
| 1127 | + Parameters: |
| 1128 | + value: The attributes dictionary to validate. |
| 1129 | +
|
| 1130 | + Raises: |
| 1131 | + ValueError: If constraints are violated. |
| 1132 | +
|
| 1133 | + Returns: |
| 1134 | + The validated attributes dictionary. |
| 1135 | + """ |
| 1136 | + if value is None: |
| 1137 | + return value |
| 1138 | + |
| 1139 | + if len(value) > 16: |
| 1140 | + raise ValueError(f"attributes can have at most 16 pairs, got {len(value)}") |
| 1141 | + |
| 1142 | + for key, val in value.items(): |
| 1143 | + if len(key) > 64: |
| 1144 | + raise ValueError(f"attribute key '{key}' exceeds 64 characters") |
| 1145 | + |
| 1146 | + if isinstance(val, str) and len(val) > 512: |
| 1147 | + raise ValueError(f"attribute value for '{key}' exceeds 512 characters") |
| 1148 | + |
| 1149 | + return value |
0 commit comments