eeshanyaj commited on
Commit
e699f51
·
1 Parent(s): a236811

minor change

Browse files
app/api/v1/conversation_routes.py CHANGED
@@ -49,7 +49,7 @@ class ChatRequest(BaseModel):
49
  conversation_id: Optional[str] = Field(None, description="Optional conversation ID. If not provided, creates new conversation.")
50
 
51
  class Config:
52
- schema_extra = {
53
  "example": {
54
  "query": "What is my account balance?",
55
  "conversation_id": "507f1f77bcf86cd799439011"
 
49
  conversation_id: Optional[str] = Field(None, description="Optional conversation ID. If not provided, creates new conversation.")
50
 
51
  class Config:
52
+ json_schema_extra = {
53
  "example": {
54
  "query": "What is my account balance?",
55
  "conversation_id": "507f1f77bcf86cd799439011"
app/models/backup_conversation.py CHANGED
@@ -1,313 +1,313 @@
1
- """
2
- Conversation Models for MongoDB
3
 
4
- Handles conversation persistence with:
5
- - Auto-generated titles from first message
6
- - Message metadata (policy actions, retrieval stats)
7
- - Archive/unarchive support
8
- - Search indexing ready
9
- """
10
 
11
- from datetime import datetime
12
- from typing import List, Optional, Dict, Any
13
- from pydantic import BaseModel, Field
14
- from bson import ObjectId
15
 
16
 
17
- # ============================================================================
18
- # CUSTOM TYPES
19
- # ============================================================================
20
 
21
- class PyObjectId(ObjectId):
22
- """Custom ObjectId type compatible with Pydantic v2"""
23
 
24
- @classmethod
25
- def __get_validators__(cls):
26
- yield cls.validate
27
 
28
- @classmethod
29
- def validate(cls, v):
30
- if not ObjectId.is_valid(v):
31
- raise ValueError("Invalid ObjectId")
32
- return ObjectId(v)
33
 
34
- @classmethod
35
- def __get_pydantic_json_schema__(cls, core_schema, handler):
36
- schema = handler(core_schema)
37
- schema.update(type="string")
38
- return schema
39
 
40
 
41
 
42
- # ============================================================================
43
- # MESSAGE MODEL
44
- # ============================================================================
45
 
46
- class Message(BaseModel):
47
- """
48
- Single message in a conversation.
49
 
50
- Contains:
51
- - User/assistant content
52
- - Metadata from RAG pipeline (policy action, retrieval stats)
53
- - Timestamp
54
- """
55
 
56
- role: str = Field(..., description="Role: 'user' or 'assistant'")
57
- content: str = Field(..., description="Message content")
58
- timestamp: datetime = Field(default_factory=datetime.utcnow)
59
 
60
- # Metadata from RAG pipeline (only for assistant messages)
61
- metadata: Optional[Dict[str, Any]] = Field(
62
- default=None,
63
- description="RAG metadata: policy_action, confidence, docs_retrieved, etc."
64
- )
65
 
66
- class Config:
67
- json_encoders = {
68
- datetime: lambda v: v.isoformat()
69
- }
70
- schema_extra = {
71
- "example": {
72
- "role": "user",
73
- "content": "What is my account balance?",
74
- "timestamp": "2024-01-15T10:30:00",
75
- "metadata": None
76
- }
77
- }
78
-
79
-
80
- # ============================================================================
81
- # CONVERSATION MODEL (MongoDB Document)
82
- # ============================================================================
83
-
84
- class Conversation(BaseModel):
85
- """
86
- Full conversation document stored in MongoDB.
87
 
88
- Features:
89
- - Auto-generated title from first user message
90
- - Message history with metadata
91
- - Archive/active status
92
- - User association
93
- - Search-ready structure
94
- """
95
 
96
- id: Optional[PyObjectId] = Field(alias="_id", default=None)
97
- user_id: str = Field(..., description="User ID who owns this conversation")
98
- title: str = Field(..., description="Conversation title (auto-generated or custom)")
99
 
100
- messages: List[Message] = Field(
101
- default_factory=list,
102
- description="List of messages in chronological order"
103
- )
104
 
105
- # Status flags
106
- is_archived: bool = Field(default=False, description="Is conversation archived?")
107
- is_deleted: bool = Field(default=False, description="Soft delete flag")
108
 
109
- # Timestamps
110
- created_at: datetime = Field(default_factory=datetime.utcnow)
111
- updated_at: datetime = Field(default_factory=datetime.utcnow)
112
- last_message_at: Optional[datetime] = Field(default=None)
113
 
114
- # Metadata
115
- message_count: int = Field(default=0, description="Total messages (excluding deleted)")
116
 
117
- class Config:
118
- model_config = {
119
- "populate_by_name": True,
120
- "arbitrary_types_allowed": True,
121
- "json_encoders": {
122
- ObjectId: str,
123
- datetime: lambda v: v.isoformat(),
124
- },
125
- }
126
- schema_extra = {
127
- "example": {
128
- "user_id": "user_123",
129
- "title": "Account Balance Inquiry",
130
- "messages": [
131
- {
132
- "role": "user",
133
- "content": "What is my account balance?",
134
- "timestamp": "2024-01-15T10:30:00"
135
- },
136
- {
137
- "role": "assistant",
138
- "content": "Your current account balance is...",
139
- "timestamp": "2024-01-15T10:30:05",
140
- "metadata": {
141
- "policy_action": "FETCH",
142
- "confidence": 0.95,
143
- "documents_retrieved": 3
144
- }
145
- }
146
- ],
147
- "is_archived": False,
148
- "created_at": "2024-01-15T10:30:00",
149
- "updated_at": "2024-01-15T10:30:05",
150
- "message_count": 2
151
- }
152
- }
153
-
154
-
155
- # ============================================================================
156
- # REQUEST/RESPONSE MODELS (for API)
157
- # ============================================================================
158
-
159
- class CreateConversationRequest(BaseModel):
160
- """Request body for creating a new conversation"""
161
 
162
- title: Optional[str] = Field(
163
- default=None,
164
- description="Optional custom title. If not provided, will be auto-generated from first message",
165
- max_length=100
166
- )
167
- first_message: Optional[str] = Field(
168
- default=None,
169
- description="Optional first user message to start the conversation",
170
- max_length=1000
171
- )
172
 
173
- class Config:
174
- schema_extra = {
175
- "example": {
176
- "title": "Savings Account Help",
177
- "first_message": "How do I open a savings account?"
178
- }
179
- }
180
 
181
 
182
- class AddMessageRequest(BaseModel):
183
- """Request body for adding a message to conversation"""
184
 
185
- message: str = Field(..., description="User message to add")
186
 
187
- class Config:
188
- schema_extra = {
189
- "example": {
190
- "message": "What are the interest rates?"
191
- }
192
- }
193
 
194
 
195
- class UpdateConversationRequest(BaseModel):
196
- """Request body for updating conversation properties"""
197
 
198
- title: Optional[str] = Field(default=None, description="New title")
199
- is_archived: Optional[bool] = Field(default=None, description="Archive status")
200
 
201
- class Config:
202
- schema_extra = {
203
- "example": {
204
- "title": "Fixed Deposit Rates Discussion"
205
- }
206
- }
207
 
208
 
209
- class ConversationResponse(BaseModel):
210
- """Response model for single conversation"""
211
 
212
- id: str = Field(..., description="Conversation ID")
213
- user_id: str
214
- title: str
215
- messages: List[Message]
216
- is_archived: bool
217
- created_at: datetime
218
- updated_at: datetime
219
- last_message_at: Optional[datetime]
220
- message_count: int
221
 
222
- class Config:
223
- json_encoders = {
224
- datetime: lambda v: v.isoformat()
225
- }
226
 
227
 
228
- class ConversationListResponse(BaseModel):
229
- """Response model for list of conversations (without full messages)"""
230
 
231
- id: str
232
- user_id: str
233
- title: str
234
- preview: str = Field(..., description="Last message preview (first 100 chars)")
235
- is_archived: bool
236
- created_at: datetime
237
- updated_at: datetime
238
- last_message_at: Optional[datetime]
239
- message_count: int
240
 
241
- class Config:
242
- json_encoders = {
243
- datetime: lambda v: v.isoformat()
244
- }
245
- schema_extra = {
246
- "example": {
247
- "id": "507f1f77bcf86cd799439011",
248
- "user_id": "user_123",
249
- "title": "Account Balance Inquiry",
250
- "preview": "What is my current account balance?",
251
- "is_archived": False,
252
- "created_at": "2024-01-15T10:30:00",
253
- "updated_at": "2024-01-15T10:35:00",
254
- "last_message_at": "2024-01-15T10:35:00",
255
- "message_count": 6
256
- }
257
- }
258
-
259
-
260
- class ConversationListResult(BaseModel):
261
- """Paginated list of conversations"""
262
 
263
- conversations: List[ConversationListResponse]
264
- total: int = Field(..., description="Total conversations matching filter")
265
- page: int = Field(default=1, description="Current page number")
266
- page_size: int = Field(default=20, description="Items per page")
267
- has_more: bool = Field(..., description="Are there more pages?")
268
 
269
- class Config:
270
- schema_extra = {
271
- "example": {
272
- "conversations": [],
273
- "total": 42,
274
- "page": 1,
275
- "page_size": 20,
276
- "has_more": True
277
- }
278
- }
279
 
280
 
281
 
282
 
283
- # class PyObjectId(ObjectId):
284
- # """Custom ObjectId type for Pydantic validation"""
285
 
286
- # @classmethod
287
- # def __get_validators__(cls):
288
- # yield cls.validate
289
 
290
- # @classmethod
291
- # def validate(cls, v):
292
- # if not ObjectId.is_valid(v):
293
- # raise ValueError("Invalid ObjectId")
294
- # return ObjectId(v)
295
 
296
- # @classmethod
297
- # def __modify_schema__(cls, field_schema):
298
- # field_schema.update(type="string")
299
 
300
 
301
 
302
 
303
- # allow_population_by_field_name = True
304
- # arbitrary_types_allowed = True
305
- # model_config = {
306
- # "populate_by_name": True,
307
- # "arbitrary_types_allowed": True,
308
- # }
309
 
310
- # json_encoders = {
311
- # ObjectId: str,
312
- # datetime: lambda v: v.isoformat()
313
- # }
 
1
+ # """
2
+ # Conversation Models for MongoDB
3
 
4
+ # Handles conversation persistence with:
5
+ # - Auto-generated titles from first message
6
+ # - Message metadata (policy actions, retrieval stats)
7
+ # - Archive/unarchive support
8
+ # - Search indexing ready
9
+ # """
10
 
11
+ # from datetime import datetime
12
+ # from typing import List, Optional, Dict, Any
13
+ # from pydantic import BaseModel, Field
14
+ # from bson import ObjectId
15
 
16
 
17
+ # # ============================================================================
18
+ # # CUSTOM TYPES
19
+ # # ============================================================================
20
 
21
+ # class PyObjectId(ObjectId):
22
+ # """Custom ObjectId type compatible with Pydantic v2"""
23
 
24
+ # @classmethod
25
+ # def __get_validators__(cls):
26
+ # yield cls.validate
27
 
28
+ # @classmethod
29
+ # def validate(cls, v):
30
+ # if not ObjectId.is_valid(v):
31
+ # raise ValueError("Invalid ObjectId")
32
+ # return ObjectId(v)
33
 
34
+ # @classmethod
35
+ # def __get_pydantic_json_schema__(cls, core_schema, handler):
36
+ # schema = handler(core_schema)
37
+ # schema.update(type="string")
38
+ # return schema
39
 
40
 
41
 
42
+ # # ============================================================================
43
+ # # MESSAGE MODEL
44
+ # # ============================================================================
45
 
46
+ # class Message(BaseModel):
47
+ # """
48
+ # Single message in a conversation.
49
 
50
+ # Contains:
51
+ # - User/assistant content
52
+ # - Metadata from RAG pipeline (policy action, retrieval stats)
53
+ # - Timestamp
54
+ # """
55
 
56
+ # role: str = Field(..., description="Role: 'user' or 'assistant'")
57
+ # content: str = Field(..., description="Message content")
58
+ # timestamp: datetime = Field(default_factory=datetime.utcnow)
59
 
60
+ # # Metadata from RAG pipeline (only for assistant messages)
61
+ # metadata: Optional[Dict[str, Any]] = Field(
62
+ # default=None,
63
+ # description="RAG metadata: policy_action, confidence, docs_retrieved, etc."
64
+ # )
65
 
66
+ # class Config:
67
+ # json_encoders = {
68
+ # datetime: lambda v: v.isoformat()
69
+ # }
70
+ # schema_extra = {
71
+ # "example": {
72
+ # "role": "user",
73
+ # "content": "What is my account balance?",
74
+ # "timestamp": "2024-01-15T10:30:00",
75
+ # "metadata": None
76
+ # }
77
+ # }
78
+
79
+
80
+ # # ============================================================================
81
+ # # CONVERSATION MODEL (MongoDB Document)
82
+ # # ============================================================================
83
+
84
+ # class Conversation(BaseModel):
85
+ # """
86
+ # Full conversation document stored in MongoDB.
87
 
88
+ # Features:
89
+ # - Auto-generated title from first user message
90
+ # - Message history with metadata
91
+ # - Archive/active status
92
+ # - User association
93
+ # - Search-ready structure
94
+ # """
95
 
96
+ # id: Optional[PyObjectId] = Field(alias="_id", default=None)
97
+ # user_id: str = Field(..., description="User ID who owns this conversation")
98
+ # title: str = Field(..., description="Conversation title (auto-generated or custom)")
99
 
100
+ # messages: List[Message] = Field(
101
+ # default_factory=list,
102
+ # description="List of messages in chronological order"
103
+ # )
104
 
105
+ # # Status flags
106
+ # is_archived: bool = Field(default=False, description="Is conversation archived?")
107
+ # is_deleted: bool = Field(default=False, description="Soft delete flag")
108
 
109
+ # # Timestamps
110
+ # created_at: datetime = Field(default_factory=datetime.utcnow)
111
+ # updated_at: datetime = Field(default_factory=datetime.utcnow)
112
+ # last_message_at: Optional[datetime] = Field(default=None)
113
 
114
+ # # Metadata
115
+ # message_count: int = Field(default=0, description="Total messages (excluding deleted)")
116
 
117
+ # class Config:
118
+ # model_config = {
119
+ # "populate_by_name": True,
120
+ # "arbitrary_types_allowed": True,
121
+ # "json_encoders": {
122
+ # ObjectId: str,
123
+ # datetime: lambda v: v.isoformat(),
124
+ # },
125
+ # }
126
+ # schema_extra = {
127
+ # "example": {
128
+ # "user_id": "user_123",
129
+ # "title": "Account Balance Inquiry",
130
+ # "messages": [
131
+ # {
132
+ # "role": "user",
133
+ # "content": "What is my account balance?",
134
+ # "timestamp": "2024-01-15T10:30:00"
135
+ # },
136
+ # {
137
+ # "role": "assistant",
138
+ # "content": "Your current account balance is...",
139
+ # "timestamp": "2024-01-15T10:30:05",
140
+ # "metadata": {
141
+ # "policy_action": "FETCH",
142
+ # "confidence": 0.95,
143
+ # "documents_retrieved": 3
144
+ # }
145
+ # }
146
+ # ],
147
+ # "is_archived": False,
148
+ # "created_at": "2024-01-15T10:30:00",
149
+ # "updated_at": "2024-01-15T10:30:05",
150
+ # "message_count": 2
151
+ # }
152
+ # }
153
+
154
+
155
+ # # ============================================================================
156
+ # # REQUEST/RESPONSE MODELS (for API)
157
+ # # ============================================================================
158
+
159
+ # class CreateConversationRequest(BaseModel):
160
+ # """Request body for creating a new conversation"""
161
 
162
+ # title: Optional[str] = Field(
163
+ # default=None,
164
+ # description="Optional custom title. If not provided, will be auto-generated from first message",
165
+ # max_length=100
166
+ # )
167
+ # first_message: Optional[str] = Field(
168
+ # default=None,
169
+ # description="Optional first user message to start the conversation",
170
+ # max_length=1000
171
+ # )
172
 
173
+ # class Config:
174
+ # schema_extra = {
175
+ # "example": {
176
+ # "title": "Savings Account Help",
177
+ # "first_message": "How do I open a savings account?"
178
+ # }
179
+ # }
180
 
181
 
182
+ # class AddMessageRequest(BaseModel):
183
+ # """Request body for adding a message to conversation"""
184
 
185
+ # message: str = Field(..., description="User message to add")
186
 
187
+ # class Config:
188
+ # schema_extra = {
189
+ # "example": {
190
+ # "message": "What are the interest rates?"
191
+ # }
192
+ # }
193
 
194
 
195
+ # class UpdateConversationRequest(BaseModel):
196
+ # """Request body for updating conversation properties"""
197
 
198
+ # title: Optional[str] = Field(default=None, description="New title")
199
+ # is_archived: Optional[bool] = Field(default=None, description="Archive status")
200
 
201
+ # class Config:
202
+ # schema_extra = {
203
+ # "example": {
204
+ # "title": "Fixed Deposit Rates Discussion"
205
+ # }
206
+ # }
207
 
208
 
209
+ # class ConversationResponse(BaseModel):
210
+ # """Response model for single conversation"""
211
 
212
+ # id: str = Field(..., description="Conversation ID")
213
+ # user_id: str
214
+ # title: str
215
+ # messages: List[Message]
216
+ # is_archived: bool
217
+ # created_at: datetime
218
+ # updated_at: datetime
219
+ # last_message_at: Optional[datetime]
220
+ # message_count: int
221
 
222
+ # class Config:
223
+ # json_encoders = {
224
+ # datetime: lambda v: v.isoformat()
225
+ # }
226
 
227
 
228
+ # class ConversationListResponse(BaseModel):
229
+ # """Response model for list of conversations (without full messages)"""
230
 
231
+ # id: str
232
+ # user_id: str
233
+ # title: str
234
+ # preview: str = Field(..., description="Last message preview (first 100 chars)")
235
+ # is_archived: bool
236
+ # created_at: datetime
237
+ # updated_at: datetime
238
+ # last_message_at: Optional[datetime]
239
+ # message_count: int
240
 
241
+ # class Config:
242
+ # json_encoders = {
243
+ # datetime: lambda v: v.isoformat()
244
+ # }
245
+ # schema_extra = {
246
+ # "example": {
247
+ # "id": "507f1f77bcf86cd799439011",
248
+ # "user_id": "user_123",
249
+ # "title": "Account Balance Inquiry",
250
+ # "preview": "What is my current account balance?",
251
+ # "is_archived": False,
252
+ # "created_at": "2024-01-15T10:30:00",
253
+ # "updated_at": "2024-01-15T10:35:00",
254
+ # "last_message_at": "2024-01-15T10:35:00",
255
+ # "message_count": 6
256
+ # }
257
+ # }
258
+
259
+
260
+ # class ConversationListResult(BaseModel):
261
+ # """Paginated list of conversations"""
262
 
263
+ # conversations: List[ConversationListResponse]
264
+ # total: int = Field(..., description="Total conversations matching filter")
265
+ # page: int = Field(default=1, description="Current page number")
266
+ # page_size: int = Field(default=20, description="Items per page")
267
+ # has_more: bool = Field(..., description="Are there more pages?")
268
 
269
+ # class Config:
270
+ # schema_extra = {
271
+ # "example": {
272
+ # "conversations": [],
273
+ # "total": 42,
274
+ # "page": 1,
275
+ # "page_size": 20,
276
+ # "has_more": True
277
+ # }
278
+ # }
279
 
280
 
281
 
282
 
283
+ # # class PyObjectId(ObjectId):
284
+ # # """Custom ObjectId type for Pydantic validation"""
285
 
286
+ # # @classmethod
287
+ # # def __get_validators__(cls):
288
+ # # yield cls.validate
289
 
290
+ # # @classmethod
291
+ # # def validate(cls, v):
292
+ # # if not ObjectId.is_valid(v):
293
+ # # raise ValueError("Invalid ObjectId")
294
+ # # return ObjectId(v)
295
 
296
+ # # @classmethod
297
+ # # def __modify_schema__(cls, field_schema):
298
+ # # field_schema.update(type="string")
299
 
300
 
301
 
302
 
303
+ # # allow_population_by_field_name = True
304
+ # # arbitrary_types_allowed = True
305
+ # # model_config = {
306
+ # # "populate_by_name": True,
307
+ # # "arbitrary_types_allowed": True,
308
+ # # }
309
 
310
+ # # json_encoders = {
311
+ # # ObjectId: str,
312
+ # # datetime: lambda v: v.isoformat()
313
+ # # }