prism-models 0.1.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. prism_models/__init__.py +46 -0
  2. prism_models/agent_profile.py +128 -0
  3. prism_models/base.py +75 -0
  4. prism_models/chat.py +355 -0
  5. prism_models/config.py +37 -0
  6. prism_models/content.py +240 -0
  7. prism_models/feedback.py +145 -0
  8. prism_models/migration/README +1 -0
  9. prism_models/migration/__init__.py +0 -0
  10. prism_models/migration/env.py +131 -0
  11. prism_models/migration/script.py.mako +28 -0
  12. prism_models/migration/versions/2025_09_11_1516_161f8829d93f_initial_schema.py +492 -0
  13. prism_models/migration/versions/2025_09_11_1558_5e011849ea76_changes_for_feedback.py +79 -0
  14. prism_models/migration/versions/2025_09_14_2243_059af231c2b2_profile_entities.py +108 -0
  15. prism_models/migration/versions/2025_09_15_1646_3219fec0bb10_agent_changes.py +32 -0
  16. prism_models/migration/versions/2025_09_16_1627_f2013b08daac_rename_metadata_to_additional_data.py +37 -0
  17. prism_models/migration/versions/2025_09_17_1147_327febbf555f_display_name_added.py +34 -0
  18. prism_models/migration/versions/2025_09_18_1106_b0bcb7ca1dc9_add_support_for_profile_on_create_convo.py +41 -0
  19. prism_models/migration/versions/2025_09_18_1511_bbc1955191e6_preview_mode.py +36 -0
  20. prism_models/migration/versions/2025_09_26_1115_6eb70e848451_added_publish_status_to_document.py +38 -0
  21. prism_models/migration/versions/2025_09_26_1240_f8b0ea2e743c_drop_unique_title_version_on_document.py +40 -0
  22. prism_models/migration/versions/2025_09_26_1505_07dc8c2589e0_added_chunk_id_and_vector_embeddings_to_.py +44 -0
  23. prism_models/migration/versions/2025_09_29_1220_46ba2693b883_add_markdown_markdown_file_path_s3_.py +32 -0
  24. prism_models/migration/versions/2025_10_02_1520_bf1472a9b021_removed_doc_id_from_config_table_and_.py +34 -0
  25. prism_models/migration/versions/2025_10_02_1525_6c0e63e0fef8_removed_doc_id_from_config_table_.py +34 -0
  26. prism_models/migration/versions/2025_10_02_1608_1b3eb48f5017_config_id_on_delete_will_be_set_to_null.py +34 -0
  27. prism_models/migration/versions/2025_10_03_1109_ac85b606d8a4_added_docling_hybrid_to_chunkstrategy.py +32 -0
  28. prism_models/migration/versions/2025_10_03_1204_7d1cb343a63f_added_s3_bucket_and_s3_dir_in_source_.py +42 -0
  29. prism_models/migration/versions/2025_10_03_1452_f9c750ec2a0b_1_to_1_relationship_between_collection_.py +52 -0
  30. prism_models/migration/versions/2025_10_07_1722_5cfa0c462948_added_travel_advisory_enum.py +38 -0
  31. prism_models/migration/versions/2025_10_08_1304_c91eb8e38cc7_added_destination_report_and_event_.py +38 -0
  32. prism_models/migration/versions/2025_10_09_1308_796b720ea35f_added_qa_id_to_vovetor.py +42 -0
  33. prism_models/migration/versions/2025_10_16_1611_663c66268631_added_sharepoint_drive_item_id_as_an_.py +32 -0
  34. prism_models/migration/versions/2025_10_23_1228_919d07a93f83_added_sharepoint_directory_in_source.py +32 -0
  35. prism_models/migration/versions/2025_10_27_1331_ff3be2c4311f_added_agentcollectionaccess_table.py +50 -0
  36. prism_models/migration/versions/2025_10_28_1333_b789e61df26a_ad_enum_and_field_added.py +46 -0
  37. prism_models/migration/versions/2025_11_03_1633_cc27b20a106e_removed_collection_from_source_.py +34 -0
  38. prism_models/migration/versions/2025_11_03_1653_bf5c2ce928e3_removed_collection_from_source_.py +36 -0
  39. prism_models/migration/versions/2025_11_03_1738_b733b48d78b5_remove_source.py +32 -0
  40. prism_models/qdrant.py +102 -0
  41. prism_models-0.1.8.dist-info/METADATA +10 -0
  42. prism_models-0.1.8.dist-info/RECORD +44 -0
  43. prism_models-0.1.8.dist-info/WHEEL +5 -0
  44. prism_models-0.1.8.dist-info/top_level.txt +1 -0
@@ -0,0 +1,492 @@
1
+ """initial schema
2
+
3
+ Revision ID: 161f8829d93f
4
+ Revises:
5
+ Create Date: 2025-09-11 15:16:39.153056
6
+
7
+ """
8
+ from typing import Sequence, Union
9
+
10
+ from alembic import op
11
+ import sqlalchemy as sa
12
+ from sqlalchemy.dialects import postgresql
13
+
14
+ # revision identifiers, used by Alembic.
15
+ revision: str = '161f8829d93f'
16
+ down_revision: Union[str, Sequence[str], None] = None
17
+ branch_labels: Union[str, Sequence[str], None] = None
18
+ depends_on: Union[str, Sequence[str], None] = None
19
+
20
+
21
+ def upgrade() -> None:
22
+ """Upgrade schema."""
23
+ # ### commands auto generated by Alembic - please adjust! ###
24
+ op.create_table('contact',
25
+ sa.Column('email', sa.String(length=300), nullable=True),
26
+ sa.Column('first_name', sa.String(length=100), nullable=False),
27
+ sa.Column('middle_name', sa.String(length=100), nullable=True),
28
+ sa.Column('last_name', sa.String(length=100), nullable=False),
29
+ sa.Column('primary_phone', sa.String(length=45), nullable=True),
30
+ sa.Column('gender', sa.Enum('MALE', 'FEMALE', name='gender'), nullable=True),
31
+ sa.Column('status', sa.Enum('ACTIVE', 'INACTIVE', 'APPROVAL_PENDING', 'MERGED', name='contactstatus'), nullable=True),
32
+ sa.Column('source', sa.Enum('GRID', 'CRM', 'EXTERNAL', name='contactsource'), nullable=False),
33
+ sa.Column('grid_contact_id', sa.Integer(), nullable=True),
34
+ sa.Column('crm_contact_guid', sa.String(length=36), nullable=True),
35
+ sa.Column('account_id', sa.String(length=36), nullable=True),
36
+ sa.Column('id', sa.Integer(), nullable=False),
37
+ sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
38
+ sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
39
+ sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
40
+ sa.PrimaryKeyConstraint('id', name=op.f('contact_pkey'))
41
+ )
42
+ op.create_index(op.f('contact_id_idx'), 'contact', ['id'], unique=False)
43
+ op.create_table('source',
44
+ sa.Column('name', sa.String(length=200), nullable=False),
45
+ sa.Column('connection_config', sa.JSON(), nullable=True),
46
+ sa.Column('metadata', sa.JSON(), nullable=True),
47
+ sa.Column('is_active', sa.Boolean(), nullable=False),
48
+ sa.Column('id', sa.Integer(), nullable=False),
49
+ sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
50
+ sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
51
+ sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
52
+ sa.PrimaryKeyConstraint('id', name=op.f('source_pkey'))
53
+ )
54
+ op.create_index(op.f('source_id_idx'), 'source', ['id'], unique=False)
55
+ op.create_index(op.f('source_name_idx'), 'source', ['name'], unique=False)
56
+ op.create_table('vector',
57
+ sa.Column('source_type', sa.String(length=20), nullable=False),
58
+ sa.Column('source_id', sa.Integer(), nullable=False),
59
+ sa.Column('model', sa.String(length=100), nullable=False),
60
+ sa.Column('qdrant_point_id', sa.String(length=100), nullable=True),
61
+ sa.Column('metadata', sa.JSON(), nullable=True),
62
+ sa.Column('id', sa.Integer(), nullable=False),
63
+ sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
64
+ sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
65
+ sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
66
+ sa.PrimaryKeyConstraint('id', name=op.f('vector_pkey')),
67
+ sa.UniqueConstraint('qdrant_point_id', name=op.f('vector_qdrant_point_id_key'))
68
+ )
69
+ op.create_index('idx_vector_source', 'vector', ['source_type', 'source_id'], unique=False)
70
+ op.create_index(op.f('vector_id_idx'), 'vector', ['id'], unique=False)
71
+ op.create_table('collection',
72
+ sa.Column('name', sa.String(length=200), nullable=False),
73
+ sa.Column('description', sa.Text(), nullable=True),
74
+ sa.Column('metadata', sa.JSON(), nullable=True),
75
+ sa.Column('is_active', sa.Boolean(), nullable=False),
76
+ sa.Column('owner_id', sa.Integer(), nullable=True),
77
+ sa.Column('id', sa.Integer(), nullable=False),
78
+ sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
79
+ sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
80
+ sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
81
+ sa.ForeignKeyConstraint(['owner_id'], ['contact.id'], name=op.f('collection_owner_id_fkey')),
82
+ sa.PrimaryKeyConstraint('id', name=op.f('collection_pkey')),
83
+ sa.UniqueConstraint('name', name='uq_collection_name')
84
+ )
85
+ op.create_index(op.f('collection_id_idx'), 'collection', ['id'], unique=False)
86
+ op.create_index(op.f('collection_name_idx'), 'collection', ['name'], unique=False)
87
+ op.create_index(op.f('collection_owner_id_idx'), 'collection', ['owner_id'], unique=False)
88
+ op.create_table('conversation',
89
+ sa.Column('uuid', sa.UUID(), nullable=False),
90
+ sa.Column('title', sa.String(length=255), nullable=True),
91
+ sa.Column('contact_id', sa.Integer(), nullable=False),
92
+ sa.Column('is_active', sa.Boolean(), nullable=False),
93
+ sa.Column('conversation_type', sa.Enum('TRAVEL_GUIDE', 'MSA_CHAT', name='conversationtype'), nullable=False),
94
+ sa.Column('audio_file_url', sa.String(length=1024), nullable=True),
95
+ sa.Column('transcription_json_url', sa.String(length=1024), nullable=True),
96
+ sa.Column('repaired_json_url', sa.String(length=1024), nullable=True),
97
+ sa.Column('id', sa.Integer(), nullable=False),
98
+ sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
99
+ sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
100
+ sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
101
+ sa.ForeignKeyConstraint(['contact_id'], ['contact.id'], name=op.f('conversation_contact_id_fkey')),
102
+ sa.PrimaryKeyConstraint('id', name=op.f('conversation_pkey'))
103
+ )
104
+ op.create_index(op.f('conversation_id_idx'), 'conversation', ['id'], unique=False)
105
+ op.create_index(op.f('conversation_uuid_idx'), 'conversation', ['uuid'], unique=True)
106
+ op.create_table('document',
107
+ sa.Column('title', sa.String(length=500), nullable=False),
108
+ sa.Column('source_id', sa.Integer(), nullable=False),
109
+ sa.Column('parent_document_id', sa.Integer(), nullable=True),
110
+ sa.Column('uploaded_by_id', sa.Integer(), nullable=True),
111
+ sa.Column('file_path_s3', sa.String(length=2048), nullable=True),
112
+ sa.Column('file_hash', sa.String(length=255), nullable=True),
113
+ sa.Column('file_size', sa.Integer(), nullable=True),
114
+ sa.Column('version', sa.Integer(), nullable=False),
115
+ sa.Column('is_latest', sa.Boolean(), nullable=False),
116
+ sa.Column('metadata', sa.JSON(), nullable=True),
117
+ sa.Column('status', sa.String(length=50), nullable=False),
118
+ sa.Column('id', sa.Integer(), nullable=False),
119
+ sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
120
+ sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
121
+ sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
122
+ sa.ForeignKeyConstraint(['parent_document_id'], ['document.id'], name=op.f('document_parent_document_id_fkey')),
123
+ sa.ForeignKeyConstraint(['source_id'], ['source.id'], name=op.f('document_source_id_fkey')),
124
+ sa.ForeignKeyConstraint(['uploaded_by_id'], ['contact.id'], name=op.f('document_uploaded_by_id_fkey')),
125
+ sa.PrimaryKeyConstraint('id', name=op.f('document_pkey')),
126
+ sa.UniqueConstraint('title', name='uq_document_title')
127
+ )
128
+ op.create_index(op.f('document_id_idx'), 'document', ['id'], unique=False)
129
+ op.create_index(op.f('document_parent_document_id_idx'), 'document', ['parent_document_id'], unique=False)
130
+ op.create_index(op.f('document_source_id_idx'), 'document', ['source_id'], unique=False)
131
+ op.create_index(op.f('document_status_idx'), 'document', ['status'], unique=False)
132
+ op.create_index(op.f('document_title_idx'), 'document', ['title'], unique=False)
133
+ op.create_index(op.f('document_uploaded_by_id_idx'), 'document', ['uploaded_by_id'], unique=False)
134
+ op.create_table('chunk_config',
135
+ sa.Column('document_id', sa.Integer(), nullable=True),
136
+ sa.Column('name', sa.String(length=255), nullable=False),
137
+ sa.Column('strategy', sa.String(length=50), nullable=False),
138
+ sa.Column('chunk_size', sa.Integer(), nullable=False),
139
+ sa.Column('chunk_overlap', sa.Integer(), nullable=False),
140
+ sa.Column('internal_qa_enabled', sa.Boolean(), nullable=False),
141
+ sa.Column('external_qa_enabled', sa.Boolean(), nullable=False),
142
+ sa.Column('internal_qa_prompt', sa.Text(), nullable=True),
143
+ sa.Column('external_qa_prompt', sa.Text(), nullable=True),
144
+ sa.Column('metadata', sa.JSON(), nullable=True),
145
+ sa.Column('is_template', sa.Boolean(), nullable=False),
146
+ sa.Column('id', sa.Integer(), nullable=False),
147
+ sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
148
+ sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
149
+ sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
150
+ sa.ForeignKeyConstraint(['document_id'], ['document.id'], name=op.f('chunk_config_document_id_fkey')),
151
+ sa.PrimaryKeyConstraint('id', name=op.f('chunk_config_pkey'))
152
+ )
153
+ op.create_index(op.f('chunk_config_id_idx'), 'chunk_config', ['id'], unique=False)
154
+ op.create_table('collection_document',
155
+ sa.Column('collection_id', sa.Integer(), nullable=False),
156
+ sa.Column('document_id', sa.Integer(), nullable=False),
157
+ sa.Column('id', sa.Integer(), nullable=False),
158
+ sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
159
+ sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
160
+ sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
161
+ sa.ForeignKeyConstraint(['collection_id'], ['collection.id'], name=op.f('collection_document_collection_id_fkey')),
162
+ sa.ForeignKeyConstraint(['document_id'], ['document.id'], name=op.f('collection_document_document_id_fkey')),
163
+ sa.PrimaryKeyConstraint('id', name=op.f('collection_document_pkey')),
164
+ sa.UniqueConstraint('collection_id', 'document_id', name='uq_collection_document')
165
+ )
166
+ op.create_index(op.f('collection_document_id_idx'), 'collection_document', ['id'], unique=False)
167
+ op.create_table('conversation_compare',
168
+ sa.Column('conversation_id', sa.Integer(), nullable=False),
169
+ sa.Column('question_index', sa.Integer(), nullable=False),
170
+ sa.Column('question_text', sa.Text(), nullable=False),
171
+ sa.Column('msa_answer_text', sa.Text(), nullable=True),
172
+ sa.Column('ai_answer_text', sa.Text(), nullable=True),
173
+ sa.Column('msa_speaker_label', sa.String(length=32), nullable=True),
174
+ sa.Column('id', sa.Integer(), nullable=False),
175
+ sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
176
+ sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
177
+ sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
178
+ sa.ForeignKeyConstraint(['conversation_id'], ['conversation.id'], name=op.f('conversation_compare_conversation_id_fkey'), ondelete='CASCADE'),
179
+ sa.PrimaryKeyConstraint('id', name=op.f('conversation_compare_pkey')),
180
+ sa.UniqueConstraint('conversation_id', 'question_index', name='uq_sim_compare_conversation_qidx')
181
+ )
182
+ op.create_index(op.f('conversation_compare_id_idx'), 'conversation_compare', ['id'], unique=False)
183
+ op.create_index('ix_sim_compare_conversation_created', 'conversation_compare', ['conversation_id', 'created_at'], unique=False)
184
+ op.create_index('ix_sim_compare_conversation_sequence', 'conversation_compare', ['conversation_id', 'question_index'], unique=False)
185
+ op.create_table('conversation_message',
186
+ sa.Column('content', sa.Text(), nullable=False),
187
+ sa.Column('conversation_id', sa.Integer(), nullable=False),
188
+ sa.Column('role', sa.Enum('USER', 'ASSISTANT', 'SYSTEM', name='messagerole'), nullable=False),
189
+ sa.Column('status', sa.Enum('PENDING', 'PROCESSING', 'COMPLETED', 'FAILED', name='messagestatus'), nullable=False),
190
+ sa.Column('message_type', sa.Enum('TEXT', name='messagetype'), nullable=False),
191
+ sa.Column('sequence_number', sa.Integer(), nullable=False),
192
+ sa.Column('llm_response_data', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
193
+ sa.Column('is_upvoted', sa.Boolean(), nullable=True),
194
+ sa.Column('is_resolved', sa.Boolean(), nullable=True),
195
+ sa.Column('id', sa.Integer(), nullable=False),
196
+ sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
197
+ sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
198
+ sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
199
+ sa.ForeignKeyConstraint(['conversation_id'], ['conversation.id'], name=op.f('conversation_message_conversation_id_fkey')),
200
+ sa.PrimaryKeyConstraint('id', name=op.f('conversation_message_pkey')),
201
+ sa.UniqueConstraint('conversation_id', 'sequence_number', name='uq_conversation_message_sequence')
202
+ )
203
+ op.create_index(op.f('conversation_message_id_idx'), 'conversation_message', ['id'], unique=False)
204
+ op.create_index('ix_conversation_message_conversation_created', 'conversation_message', ['conversation_id', 'created_at'], unique=False)
205
+ op.create_index('ix_conversation_message_conversation_sequence', 'conversation_message', ['conversation_id', 'sequence_number'], unique=False)
206
+ op.create_index('ix_conversation_message_llm_response_gin', 'conversation_message', ['llm_response_data'], unique=False, postgresql_using='gin')
207
+ op.create_table('qa_pair',
208
+ sa.Column('document_id', sa.Integer(), nullable=False),
209
+ sa.Column('question', sa.Text(), nullable=False),
210
+ sa.Column('answer', sa.Text(), nullable=False),
211
+ sa.Column('provenance', sa.String(length=50), nullable=False),
212
+ sa.Column('confidence_score', sa.Float(), nullable=True),
213
+ sa.Column('id', sa.Integer(), nullable=False),
214
+ sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
215
+ sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
216
+ sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
217
+ sa.ForeignKeyConstraint(['document_id'], ['document.id'], name=op.f('qa_pair_document_id_fkey')),
218
+ sa.PrimaryKeyConstraint('id', name=op.f('qa_pair_pkey'))
219
+ )
220
+ op.create_index(op.f('qa_pair_document_id_idx'), 'qa_pair', ['document_id'], unique=False)
221
+ op.create_index(op.f('qa_pair_id_idx'), 'qa_pair', ['id'], unique=False)
222
+ op.create_table('chunk',
223
+ sa.Column('document_id', sa.Integer(), nullable=False),
224
+ sa.Column('chunk_config_id', sa.Integer(), nullable=True),
225
+ sa.Column('text', sa.Text(), nullable=False),
226
+ sa.Column('text_hash', sa.String(length=64), nullable=True),
227
+ sa.Column('id', sa.Integer(), nullable=False),
228
+ sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
229
+ sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
230
+ sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
231
+ sa.ForeignKeyConstraint(['chunk_config_id'], ['chunk_config.id'], name=op.f('chunk_chunk_config_id_fkey')),
232
+ sa.ForeignKeyConstraint(['document_id'], ['document.id'], name=op.f('chunk_document_id_fkey')),
233
+ sa.PrimaryKeyConstraint('id', name=op.f('chunk_pkey'))
234
+ )
235
+ op.create_index(op.f('chunk_document_id_idx'), 'chunk', ['document_id'], unique=False)
236
+ op.create_index(op.f('chunk_id_idx'), 'chunk', ['id'], unique=False)
237
+ op.create_index(op.f('chunk_text_hash_idx'), 'chunk', ['text_hash'], unique=False)
238
+ op.create_table('conversation_message_metadata',
239
+ sa.Column('message_id', sa.Integer(), nullable=False),
240
+ sa.Column('model_name', sa.String(length=100), nullable=True),
241
+ sa.Column('token_count_input', sa.Integer(), nullable=True),
242
+ sa.Column('token_count_output', sa.Integer(), nullable=True),
243
+ sa.Column('processing_time_ms', sa.Integer(), nullable=True),
244
+ sa.Column('retrieval_context', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
245
+ sa.Column('id', sa.Integer(), nullable=False),
246
+ sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
247
+ sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
248
+ sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
249
+ sa.ForeignKeyConstraint(['message_id'], ['conversation_message.id'], name=op.f('conversation_message_metadata_message_id_fkey')),
250
+ sa.PrimaryKeyConstraint('id', name=op.f('conversation_message_metadata_pkey')),
251
+ sa.UniqueConstraint('message_id', name=op.f('conversation_message_metadata_message_id_key'))
252
+ )
253
+ op.create_index(op.f('conversation_message_metadata_id_idx'), 'conversation_message_metadata', ['id'], unique=False)
254
+ op.create_index('ix_conversation_message_metadata_retrieval_gin', 'conversation_message_metadata', ['retrieval_context'], unique=False, postgresql_using='gin')
255
+ op.create_table('integration_config',
256
+ sa.Column('source_id', sa.Integer(), nullable=False),
257
+ sa.Column('chunk_config_id', sa.Integer(), nullable=True),
258
+ sa.Column('external_id', sa.String(length=255), nullable=True),
259
+ sa.Column('target_collection_ids', postgresql.ARRAY(sa.Integer()), nullable=True),
260
+ sa.Column('sync_frequency', sa.String(length=20), nullable=False),
261
+ sa.Column('sync_enabled', sa.Boolean(), nullable=False),
262
+ sa.Column('id', sa.Integer(), nullable=False),
263
+ sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
264
+ sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
265
+ sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
266
+ sa.ForeignKeyConstraint(['chunk_config_id'], ['chunk_config.id'], name=op.f('integration_config_chunk_config_id_fkey')),
267
+ sa.ForeignKeyConstraint(['source_id'], ['source.id'], name=op.f('integration_config_source_id_fkey')),
268
+ sa.PrimaryKeyConstraint('id', name=op.f('integration_config_pkey'))
269
+ )
270
+ op.create_index(op.f('integration_config_id_idx'), 'integration_config', ['id'], unique=False)
271
+ op.create_index(op.f('integration_config_source_id_idx'), 'integration_config', ['source_id'], unique=False)
272
+ op.create_table('message_component',
273
+ sa.Column('component_type', sa.String(), nullable=False),
274
+ sa.Column('payload', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
275
+ sa.Column('position', sa.Integer(), nullable=False),
276
+ sa.Column('message_id', sa.Integer(), nullable=False),
277
+ sa.Column('id', sa.Integer(), nullable=False),
278
+ sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
279
+ sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
280
+ sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
281
+ sa.ForeignKeyConstraint(['message_id'], ['conversation_message.id'], name=op.f('message_component_message_id_fkey'), ondelete='CASCADE'),
282
+ sa.PrimaryKeyConstraint('id', name=op.f('message_component_pkey')),
283
+ sa.UniqueConstraint('message_id', 'position', name='uq_message_component_position')
284
+ )
285
+ op.create_index('ix_message_component_message_id', 'message_component', ['message_id'], unique=False)
286
+ op.create_index('ix_message_component_position', 'message_component', ['message_id', 'position'], unique=False)
287
+ op.create_index(op.f('message_component_id_idx'), 'message_component', ['id'], unique=False)
288
+ op.create_table('message_feedback',
289
+ sa.Column('message_id', sa.Integer(), nullable=False),
290
+ sa.Column('conversation_id', sa.Integer(), nullable=False),
291
+ sa.Column('contact_id', sa.Integer(), nullable=False),
292
+ sa.Column('feedback_type', sa.Enum('THUMBS_DOWN', 'THUMBS_UP', name='feedbacktype'), nullable=False),
293
+ sa.Column('user_query', sa.Text(), nullable=False),
294
+ sa.Column('message_content', sa.Text(), nullable=False),
295
+ sa.Column('user_feedback', sa.Text(), nullable=True),
296
+ sa.Column('llm_synthesized_correction', sa.Text(), nullable=True),
297
+ sa.Column('review_status', sa.Enum('PENDING', 'REVIEWED', 'CORRECTED', name='reviewstatus'), nullable=False),
298
+ sa.Column('reviewed_by', sa.String(length=255), nullable=True),
299
+ sa.Column('reviewed_at', sa.DateTime(), nullable=True),
300
+ sa.Column('metadata_json', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
301
+ sa.Column('id', sa.Integer(), nullable=False),
302
+ sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
303
+ sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
304
+ sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
305
+ sa.ForeignKeyConstraint(['contact_id'], ['contact.id'], name=op.f('message_feedback_contact_id_fkey')),
306
+ sa.ForeignKeyConstraint(['conversation_id'], ['conversation.id'], name=op.f('message_feedback_conversation_id_fkey')),
307
+ sa.ForeignKeyConstraint(['message_id'], ['conversation_message.id'], name=op.f('message_feedback_message_id_fkey')),
308
+ sa.PrimaryKeyConstraint('id', name=op.f('message_feedback_pkey'))
309
+ )
310
+ op.create_index('ix_message_feedback_contact_id', 'message_feedback', ['contact_id'], unique=False)
311
+ op.create_index('ix_message_feedback_conversation_id', 'message_feedback', ['conversation_id'], unique=False)
312
+ op.create_index('ix_message_feedback_created_at', 'message_feedback', ['created_at'], unique=False)
313
+ op.create_index('ix_message_feedback_feedback_type', 'message_feedback', ['feedback_type'], unique=False)
314
+ op.create_index('ix_message_feedback_message_id', 'message_feedback', ['message_id'], unique=False)
315
+ op.create_index('ix_message_feedback_metadata_gin', 'message_feedback', ['metadata_json'], unique=False, postgresql_using='gin')
316
+ op.create_index('ix_message_feedback_review_status', 'message_feedback', ['review_status'], unique=False)
317
+ op.create_index('ix_message_feedback_reviewed_at', 'message_feedback', ['reviewed_at'], unique=False)
318
+ op.create_index(op.f('message_feedback_contact_id_idx'), 'message_feedback', ['contact_id'], unique=False)
319
+ op.create_index(op.f('message_feedback_conversation_id_idx'), 'message_feedback', ['conversation_id'], unique=False)
320
+ op.create_index(op.f('message_feedback_id_idx'), 'message_feedback', ['id'], unique=False)
321
+ op.create_index(op.f('message_feedback_message_id_idx'), 'message_feedback', ['message_id'], unique=False)
322
+ op.create_table('feedback',
323
+ sa.Column('manager_id', sa.Integer(), nullable=False),
324
+ sa.Column('chunk_id', sa.Integer(), nullable=True),
325
+ sa.Column('qa_pair_id', sa.Integer(), nullable=True),
326
+ sa.Column('message_id', sa.Integer(), nullable=True),
327
+ sa.Column('assigned_reviewer_id', sa.Integer(), nullable=True),
328
+ sa.Column('authority_domain', sa.String(length=255), nullable=True),
329
+ sa.Column('confidence_level', sa.String(length=50), nullable=True),
330
+ sa.Column('feedback_type', sa.String(length=50), nullable=False),
331
+ sa.Column('query', sa.Text(), nullable=True),
332
+ sa.Column('provided_response', sa.Text(), nullable=True),
333
+ sa.Column('correction', sa.Text(), nullable=True),
334
+ sa.Column('requires_review', sa.Boolean(), nullable=False),
335
+ sa.Column('status', sa.String(length=50), nullable=False),
336
+ sa.Column('admin_notes', sa.Text(), nullable=True),
337
+ sa.Column('reviewed_at', sa.TIMESTAMP(timezone=True), nullable=True),
338
+ sa.Column('routed', sa.Boolean(), nullable=False),
339
+ sa.Column('id', sa.Integer(), nullable=False),
340
+ sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
341
+ sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
342
+ sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
343
+ sa.ForeignKeyConstraint(['assigned_reviewer_id'], ['contact.id'], name=op.f('feedback_assigned_reviewer_id_fkey')),
344
+ sa.ForeignKeyConstraint(['chunk_id'], ['chunk.id'], name=op.f('feedback_chunk_id_fkey')),
345
+ sa.ForeignKeyConstraint(['manager_id'], ['contact.id'], name=op.f('feedback_manager_id_fkey')),
346
+ sa.ForeignKeyConstraint(['message_id'], ['conversation_message.id'], name=op.f('feedback_message_id_fkey')),
347
+ sa.ForeignKeyConstraint(['qa_pair_id'], ['qa_pair.id'], name=op.f('feedback_qa_pair_id_fkey')),
348
+ sa.PrimaryKeyConstraint('id', name=op.f('feedback_pkey'))
349
+ )
350
+ op.create_index(op.f('feedback_assigned_reviewer_id_idx'), 'feedback', ['assigned_reviewer_id'], unique=False)
351
+ op.create_index(op.f('feedback_chunk_id_idx'), 'feedback', ['chunk_id'], unique=False)
352
+ op.create_index(op.f('feedback_id_idx'), 'feedback', ['id'], unique=False)
353
+ op.create_index(op.f('feedback_manager_id_idx'), 'feedback', ['manager_id'], unique=False)
354
+ op.create_index(op.f('feedback_message_id_idx'), 'feedback', ['message_id'], unique=False)
355
+ op.create_index(op.f('feedback_qa_pair_id_idx'), 'feedback', ['qa_pair_id'], unique=False)
356
+ op.create_index(op.f('feedback_status_idx'), 'feedback', ['status'], unique=False)
357
+ op.create_table('qa_pair_chunk_association',
358
+ sa.Column('qa_pair_id', sa.Integer(), nullable=False),
359
+ sa.Column('chunk_id', sa.Integer(), nullable=False),
360
+ sa.ForeignKeyConstraint(['chunk_id'], ['chunk.id'], name=op.f('qa_pair_chunk_association_chunk_id_fkey')),
361
+ sa.ForeignKeyConstraint(['qa_pair_id'], ['qa_pair.id'], name=op.f('qa_pair_chunk_association_qa_pair_id_fkey')),
362
+ sa.PrimaryKeyConstraint('qa_pair_id', 'chunk_id', name=op.f('qa_pair_chunk_association_pkey'))
363
+ )
364
+ op.create_table('augmentation',
365
+ sa.Column('feedback_id', sa.Integer(), nullable=False),
366
+ sa.Column('original_chunk_id', sa.Integer(), nullable=True),
367
+ sa.Column('original_qa_pair_id', sa.Integer(), nullable=True),
368
+ sa.Column('generated_chunk_id', sa.Integer(), nullable=True),
369
+ sa.Column('generated_qa_pair_id', sa.Integer(), nullable=True),
370
+ sa.Column('action_type', sa.String(length=50), nullable=False),
371
+ sa.Column('change_summary', sa.JSON(), nullable=True),
372
+ sa.Column('status', sa.String(length=50), nullable=False),
373
+ sa.Column('id', sa.Integer(), nullable=False),
374
+ sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
375
+ sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
376
+ sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
377
+ sa.ForeignKeyConstraint(['feedback_id'], ['feedback.id'], name=op.f('augmentation_feedback_id_fkey')),
378
+ sa.ForeignKeyConstraint(['generated_chunk_id'], ['chunk.id'], name=op.f('augmentation_generated_chunk_id_fkey')),
379
+ sa.ForeignKeyConstraint(['generated_qa_pair_id'], ['qa_pair.id'], name=op.f('augmentation_generated_qa_pair_id_fkey')),
380
+ sa.ForeignKeyConstraint(['original_chunk_id'], ['chunk.id'], name=op.f('augmentation_original_chunk_id_fkey')),
381
+ sa.ForeignKeyConstraint(['original_qa_pair_id'], ['qa_pair.id'], name=op.f('augmentation_original_qa_pair_id_fkey')),
382
+ sa.PrimaryKeyConstraint('id', name=op.f('augmentation_pkey'))
383
+ )
384
+ op.create_index(op.f('augmentation_feedback_id_idx'), 'augmentation', ['feedback_id'], unique=False)
385
+ op.create_index(op.f('augmentation_id_idx'), 'augmentation', ['id'], unique=False)
386
+ op.create_index(op.f('augmentation_status_idx'), 'augmentation', ['status'], unique=False)
387
+ op.create_table('feedback_analysis',
388
+ sa.Column('feedback_id', sa.Integer(), nullable=False),
389
+ sa.Column('analysis_type', sa.String(length=50), nullable=False),
390
+ sa.Column('llm_response', sa.JSON(), nullable=True),
391
+ sa.Column('confidence_score', sa.Float(), nullable=True),
392
+ sa.Column('model_used', sa.String(length=255), nullable=True),
393
+ sa.Column('analyzed_at', sa.TIMESTAMP(timezone=True), server_default=sa.text('now()'), nullable=False),
394
+ sa.Column('approved', sa.Boolean(), nullable=False),
395
+ sa.Column('reason_to_reject', sa.Text(), nullable=True),
396
+ sa.Column('id', sa.Integer(), nullable=False),
397
+ sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
398
+ sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
399
+ sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
400
+ sa.ForeignKeyConstraint(['feedback_id'], ['feedback.id'], name=op.f('feedback_analysis_feedback_id_fkey')),
401
+ sa.PrimaryKeyConstraint('id', name=op.f('feedback_analysis_pkey'))
402
+ )
403
+ op.create_index(op.f('feedback_analysis_feedback_id_idx'), 'feedback_analysis', ['feedback_id'], unique=False)
404
+ op.create_index(op.f('feedback_analysis_id_idx'), 'feedback_analysis', ['id'], unique=False)
405
+ # ### end Alembic commands ###
406
+
407
+
408
+ def downgrade() -> None:
409
+ """Downgrade schema."""
410
+ # ### commands auto generated by Alembic - please adjust! ###
411
+ op.drop_index(op.f('feedback_analysis_id_idx'), table_name='feedback_analysis')
412
+ op.drop_index(op.f('feedback_analysis_feedback_id_idx'), table_name='feedback_analysis')
413
+ op.drop_table('feedback_analysis')
414
+ op.drop_index(op.f('augmentation_status_idx'), table_name='augmentation')
415
+ op.drop_index(op.f('augmentation_id_idx'), table_name='augmentation')
416
+ op.drop_index(op.f('augmentation_feedback_id_idx'), table_name='augmentation')
417
+ op.drop_table('augmentation')
418
+ op.drop_table('qa_pair_chunk_association')
419
+ op.drop_index(op.f('feedback_status_idx'), table_name='feedback')
420
+ op.drop_index(op.f('feedback_qa_pair_id_idx'), table_name='feedback')
421
+ op.drop_index(op.f('feedback_message_id_idx'), table_name='feedback')
422
+ op.drop_index(op.f('feedback_manager_id_idx'), table_name='feedback')
423
+ op.drop_index(op.f('feedback_id_idx'), table_name='feedback')
424
+ op.drop_index(op.f('feedback_chunk_id_idx'), table_name='feedback')
425
+ op.drop_index(op.f('feedback_assigned_reviewer_id_idx'), table_name='feedback')
426
+ op.drop_table('feedback')
427
+ op.drop_index(op.f('message_feedback_message_id_idx'), table_name='message_feedback')
428
+ op.drop_index(op.f('message_feedback_id_idx'), table_name='message_feedback')
429
+ op.drop_index(op.f('message_feedback_conversation_id_idx'), table_name='message_feedback')
430
+ op.drop_index(op.f('message_feedback_contact_id_idx'), table_name='message_feedback')
431
+ op.drop_index('ix_message_feedback_reviewed_at', table_name='message_feedback')
432
+ op.drop_index('ix_message_feedback_review_status', table_name='message_feedback')
433
+ op.drop_index('ix_message_feedback_metadata_gin', table_name='message_feedback', postgresql_using='gin')
434
+ op.drop_index('ix_message_feedback_message_id', table_name='message_feedback')
435
+ op.drop_index('ix_message_feedback_feedback_type', table_name='message_feedback')
436
+ op.drop_index('ix_message_feedback_created_at', table_name='message_feedback')
437
+ op.drop_index('ix_message_feedback_conversation_id', table_name='message_feedback')
438
+ op.drop_index('ix_message_feedback_contact_id', table_name='message_feedback')
439
+ op.drop_table('message_feedback')
440
+ op.drop_index(op.f('message_component_id_idx'), table_name='message_component')
441
+ op.drop_index('ix_message_component_position', table_name='message_component')
442
+ op.drop_index('ix_message_component_message_id', table_name='message_component')
443
+ op.drop_table('message_component')
444
+ op.drop_index(op.f('integration_config_source_id_idx'), table_name='integration_config')
445
+ op.drop_index(op.f('integration_config_id_idx'), table_name='integration_config')
446
+ op.drop_table('integration_config')
447
+ op.drop_index('ix_conversation_message_metadata_retrieval_gin', table_name='conversation_message_metadata', postgresql_using='gin')
448
+ op.drop_index(op.f('conversation_message_metadata_id_idx'), table_name='conversation_message_metadata')
449
+ op.drop_table('conversation_message_metadata')
450
+ op.drop_index(op.f('chunk_text_hash_idx'), table_name='chunk')
451
+ op.drop_index(op.f('chunk_id_idx'), table_name='chunk')
452
+ op.drop_index(op.f('chunk_document_id_idx'), table_name='chunk')
453
+ op.drop_table('chunk')
454
+ op.drop_index(op.f('qa_pair_id_idx'), table_name='qa_pair')
455
+ op.drop_index(op.f('qa_pair_document_id_idx'), table_name='qa_pair')
456
+ op.drop_table('qa_pair')
457
+ op.drop_index('ix_conversation_message_llm_response_gin', table_name='conversation_message', postgresql_using='gin')
458
+ op.drop_index('ix_conversation_message_conversation_sequence', table_name='conversation_message')
459
+ op.drop_index('ix_conversation_message_conversation_created', table_name='conversation_message')
460
+ op.drop_index(op.f('conversation_message_id_idx'), table_name='conversation_message')
461
+ op.drop_table('conversation_message')
462
+ op.drop_index('ix_sim_compare_conversation_sequence', table_name='conversation_compare')
463
+ op.drop_index('ix_sim_compare_conversation_created', table_name='conversation_compare')
464
+ op.drop_index(op.f('conversation_compare_id_idx'), table_name='conversation_compare')
465
+ op.drop_table('conversation_compare')
466
+ op.drop_index(op.f('collection_document_id_idx'), table_name='collection_document')
467
+ op.drop_table('collection_document')
468
+ op.drop_index(op.f('chunk_config_id_idx'), table_name='chunk_config')
469
+ op.drop_table('chunk_config')
470
+ op.drop_index(op.f('document_uploaded_by_id_idx'), table_name='document')
471
+ op.drop_index(op.f('document_title_idx'), table_name='document')
472
+ op.drop_index(op.f('document_status_idx'), table_name='document')
473
+ op.drop_index(op.f('document_source_id_idx'), table_name='document')
474
+ op.drop_index(op.f('document_parent_document_id_idx'), table_name='document')
475
+ op.drop_index(op.f('document_id_idx'), table_name='document')
476
+ op.drop_table('document')
477
+ op.drop_index(op.f('conversation_uuid_idx'), table_name='conversation')
478
+ op.drop_index(op.f('conversation_id_idx'), table_name='conversation')
479
+ op.drop_table('conversation')
480
+ op.drop_index(op.f('collection_owner_id_idx'), table_name='collection')
481
+ op.drop_index(op.f('collection_name_idx'), table_name='collection')
482
+ op.drop_index(op.f('collection_id_idx'), table_name='collection')
483
+ op.drop_table('collection')
484
+ op.drop_index(op.f('vector_id_idx'), table_name='vector')
485
+ op.drop_index('idx_vector_source', table_name='vector')
486
+ op.drop_table('vector')
487
+ op.drop_index(op.f('source_name_idx'), table_name='source')
488
+ op.drop_index(op.f('source_id_idx'), table_name='source')
489
+ op.drop_table('source')
490
+ op.drop_index(op.f('contact_id_idx'), table_name='contact')
491
+ op.drop_table('contact')
492
+ # ### end Alembic commands ###
@@ -0,0 +1,79 @@
1
+ """changes for feedback
2
+
3
+ Revision ID: 5e011849ea76
4
+ Revises: 161f8829d93f
5
+ Create Date: 2025-09-11 15:58:57.378056
6
+
7
+ """
8
+
9
+ from typing import Sequence
10
+
11
+ import sqlalchemy as sa
12
+ from alembic import op
13
+ from sqlalchemy.dialects import postgresql
14
+
15
+ # revision identifiers, used by Alembic.
16
+ revision: str = "5e011849ea76"
17
+ down_revision: str | Sequence[str] | None = "161f8829d93f"
18
+ branch_labels: str | Sequence[str] | None = None
19
+ depends_on: str | Sequence[str] | None = None
20
+
21
+
22
+ def upgrade() -> None:
23
+ """Upgrade schema."""
24
+ # ### commands auto generated by Alembic - please adjust! ###
25
+ op.drop_index(op.f("ix_message_feedback_contact_id"), table_name="message_feedback")
26
+ op.drop_index(op.f("ix_message_feedback_conversation_id"), table_name="message_feedback")
27
+ op.drop_index(op.f("ix_message_feedback_created_at"), table_name="message_feedback")
28
+ op.drop_index(op.f("ix_message_feedback_feedback_type"), table_name="message_feedback")
29
+ op.drop_index(op.f("ix_message_feedback_message_id"), table_name="message_feedback")
30
+ op.drop_index(op.f("ix_message_feedback_metadata_gin"), table_name="message_feedback", postgresql_using="gin")
31
+ op.drop_index(op.f("ix_message_feedback_review_status"), table_name="message_feedback")
32
+ op.drop_index(op.f("ix_message_feedback_reviewed_at"), table_name="message_feedback")
33
+ op.drop_index(op.f("message_feedback_contact_id_idx"), table_name="message_feedback")
34
+ op.drop_index(op.f("message_feedback_conversation_id_idx"), table_name="message_feedback")
35
+ op.drop_index(op.f("message_feedback_id_idx"), table_name="message_feedback")
36
+ op.drop_index(op.f("message_feedback_message_id_idx"), table_name="message_feedback")
37
+ op.drop_table("message_feedback")
38
+ # ### end Alembic commands ###
39
+
40
+
41
+ def downgrade() -> None:
42
+ """Downgrade schema."""
43
+ # ### commands auto generated by Alembic - please adjust! ###
44
+ op.create_table(
45
+ "message_feedback",
46
+ sa.Column("message_id", sa.INTEGER(), autoincrement=False, nullable=False),
47
+ sa.Column("conversation_id", sa.INTEGER(), autoincrement=False, nullable=False),
48
+ sa.Column("contact_id", sa.INTEGER(), autoincrement=False, nullable=False),
49
+ sa.Column("feedback_type", postgresql.ENUM("THUMBS_DOWN", "THUMBS_UP", name="feedbacktype"), autoincrement=False, nullable=False),
50
+ sa.Column("user_query", sa.TEXT(), autoincrement=False, nullable=False),
51
+ sa.Column("message_content", sa.TEXT(), autoincrement=False, nullable=False),
52
+ sa.Column("user_feedback", sa.TEXT(), autoincrement=False, nullable=True),
53
+ sa.Column("llm_synthesized_correction", sa.TEXT(), autoincrement=False, nullable=True),
54
+ sa.Column("review_status", postgresql.ENUM("PENDING", "REVIEWED", "CORRECTED", name="reviewstatus"), autoincrement=False, nullable=False),
55
+ sa.Column("reviewed_by", sa.VARCHAR(length=255), autoincrement=False, nullable=True),
56
+ sa.Column("reviewed_at", postgresql.TIMESTAMP(), autoincrement=False, nullable=True),
57
+ sa.Column("metadata_json", postgresql.JSONB(astext_type=sa.Text()), autoincrement=False, nullable=True),
58
+ sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False),
59
+ sa.Column("created_at", postgresql.TIMESTAMP(timezone=True), server_default=sa.text("now()"), autoincrement=False, nullable=False),
60
+ sa.Column("updated_at", postgresql.TIMESTAMP(timezone=True), server_default=sa.text("now()"), autoincrement=False, nullable=False),
61
+ sa.Column("deleted_at", postgresql.TIMESTAMP(timezone=True), autoincrement=False, nullable=True),
62
+ sa.ForeignKeyConstraint(["contact_id"], ["contact.id"], name=op.f("message_feedback_contact_id_fkey")),
63
+ sa.ForeignKeyConstraint(["conversation_id"], ["conversation.id"], name=op.f("message_feedback_conversation_id_fkey")),
64
+ sa.ForeignKeyConstraint(["message_id"], ["conversation_message.id"], name=op.f("message_feedback_message_id_fkey")),
65
+ sa.PrimaryKeyConstraint("id", name=op.f("message_feedback_pkey")),
66
+ )
67
+ op.create_index(op.f("message_feedback_message_id_idx"), "message_feedback", ["message_id"], unique=False)
68
+ op.create_index(op.f("message_feedback_id_idx"), "message_feedback", ["id"], unique=False)
69
+ op.create_index(op.f("message_feedback_conversation_id_idx"), "message_feedback", ["conversation_id"], unique=False)
70
+ op.create_index(op.f("message_feedback_contact_id_idx"), "message_feedback", ["contact_id"], unique=False)
71
+ op.create_index(op.f("ix_message_feedback_reviewed_at"), "message_feedback", ["reviewed_at"], unique=False)
72
+ op.create_index(op.f("ix_message_feedback_review_status"), "message_feedback", ["review_status"], unique=False)
73
+ op.create_index(op.f("ix_message_feedback_metadata_gin"), "message_feedback", ["metadata_json"], unique=False, postgresql_using="gin")
74
+ op.create_index(op.f("ix_message_feedback_message_id"), "message_feedback", ["message_id"], unique=False)
75
+ op.create_index(op.f("ix_message_feedback_feedback_type"), "message_feedback", ["feedback_type"], unique=False)
76
+ op.create_index(op.f("ix_message_feedback_created_at"), "message_feedback", ["created_at"], unique=False)
77
+ op.create_index(op.f("ix_message_feedback_conversation_id"), "message_feedback", ["conversation_id"], unique=False)
78
+ op.create_index(op.f("ix_message_feedback_contact_id"), "message_feedback", ["contact_id"], unique=False)
79
+ # ### end Alembic commands ###