forked from morphik-org/morphik-core
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathservices_init.py
More file actions
263 lines (228 loc) · 11.4 KB
/
Copy pathservices_init.py
File metadata and controls
263 lines (228 loc) · 11.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
"""Centralised initialisation of core services.
This file was introduced during the refactor of `core/api.py` to keep the
monolithic API file small. It performs *exactly* the same initialisation
logic that previously lived in `core/api.py` (lines ~90-210) and exposes the
created singletons so that other modules can simply import them:
from core.services_init import document_service, settings
No behaviour has changed – only the physical location of the code.
"""
from __future__ import annotations
import logging
from typing import Optional
from core.completion.litellm_completion import LiteLLMCompletionModel
from core.config import get_settings
from core.database.postgres_database import PostgresDatabase
from core.embedding.colpali_api_embedding_model import ColpaliApiEmbeddingModel
from core.embedding.litellm_embedding import LiteLLMEmbeddingModel
from core.embedding.minimax_embedding import MiniMaxEmbeddingModel
from core.parser.morphik_parser import MorphikParser
from core.reranker.flag_reranker import FlagReranker
from core.services.document_service import DocumentService
from core.services.ingestion_service import IngestionService
from core.services.v2_document_service import V2DocumentService
from core.storage.local_storage import LocalStorage
from core.storage.s3_storage import S3Storage
from core.vector_store.chunk_v2_store import ChunkV2Store
from core.vector_store.dual_multivector_store import DualMultiVectorStore
from core.vector_store.fast_multivector_store import FastMultiVectorStore
from core.vector_store.multi_vector_store import MultiVectorStore
from core.vector_store.pgvector_store import PGVectorStore
logger = logging.getLogger(__name__)
# ---------------------------------------------------------------------------
# Global settings
# ---------------------------------------------------------------------------
settings = get_settings()
# ---------------------------------------------------------------------------
# Database & vector store
# ---------------------------------------------------------------------------
if not settings.POSTGRES_URI:
raise ValueError("PostgreSQL URI is required for PostgreSQL database")
database = PostgresDatabase(uri=settings.POSTGRES_URI)
logger.debug("Created PostgresDatabase singleton")
vector_store = PGVectorStore(uri=settings.POSTGRES_URI)
logger.debug("Created PGVectorStore singleton")
v2_chunk_store = ChunkV2Store(uri=settings.POSTGRES_URI)
logger.debug("Created ChunkV2Store singleton")
# ---------------------------------------------------------------------------
# Object storage
# ---------------------------------------------------------------------------
match settings.STORAGE_PROVIDER:
case "local":
storage = LocalStorage(storage_path=settings.STORAGE_PATH)
case "aws-s3":
if not settings.AWS_ACCESS_KEY or not settings.AWS_SECRET_ACCESS_KEY:
raise ValueError("AWS credentials are required for S3 storage")
storage = S3Storage(
aws_access_key=settings.AWS_ACCESS_KEY,
aws_secret_key=settings.AWS_SECRET_ACCESS_KEY,
region_name=settings.AWS_REGION,
default_bucket=settings.S3_BUCKET,
upload_concurrency=settings.S3_UPLOAD_CONCURRENCY,
)
case _:
raise ValueError(f"Unsupported storage provider: {settings.STORAGE_PROVIDER}")
logger.debug("Initialised Storage layer: %s", settings.STORAGE_PROVIDER)
# ---------------------------------------------------------------------------
# Parser & models
# ---------------------------------------------------------------------------
parser = MorphikParser(
chunk_size=settings.CHUNK_SIZE,
chunk_overlap=settings.CHUNK_OVERLAP,
assemblyai_api_key=settings.ASSEMBLYAI_API_KEY,
anthropic_api_key=settings.ANTHROPIC_API_KEY,
use_contextual_chunking=settings.USE_CONTEXTUAL_CHUNKING,
)
# Use MiniMax embedding model if the registered model has provider="minimax"
_emb_cfg = settings.REGISTERED_MODELS.get(settings.EMBEDDING_MODEL, {})
if _emb_cfg.get("provider") == "minimax":
embedding_model = MiniMaxEmbeddingModel(model_key=settings.EMBEDDING_MODEL)
logger.info("Initialized MiniMax embedding model with model key: %s", settings.EMBEDDING_MODEL)
else:
embedding_model = LiteLLMEmbeddingModel(model_key=settings.EMBEDDING_MODEL)
logger.info("Initialized LiteLLM embedding model with model key: %s", settings.EMBEDDING_MODEL)
completion_model = LiteLLMCompletionModel(model_key=settings.COMPLETION_MODEL)
logger.info("Initialized LiteLLM completion model with model key: %s", settings.COMPLETION_MODEL)
# ---------------------------------------------------------------------------
# Optional reranker
# ---------------------------------------------------------------------------
reranker: Optional[FlagReranker] = None
if settings.USE_RERANKING:
match settings.RERANKER_PROVIDER:
case "flag":
reranker = FlagReranker(
model_name=settings.RERANKER_MODEL,
device=settings.RERANKER_DEVICE,
use_fp16=settings.RERANKER_USE_FP16,
query_max_length=settings.RERANKER_QUERY_MAX_LENGTH,
passage_max_length=settings.RERANKER_PASSAGE_MAX_LENGTH,
)
case _:
raise ValueError(f"Unsupported reranker provider: {settings.RERANKER_PROVIDER}")
logger.debug("Reranker enabled: %s", bool(reranker))
# ---------------------------------------------------------------------------
# ColPali multi-vector support
# ---------------------------------------------------------------------------
# Check enable_colpali first - if disabled, skip all ColPali initialization
if not settings.ENABLE_COLPALI:
logger.info("ColPali disabled by configuration (enable_colpali=false)")
colpali_embedding_model = None
colpali_vector_store = None
else:
# Only initialize ColPali if enabled AND mode is not "off"
match settings.COLPALI_MODE:
case "off":
logger.info("ColPali mode set to 'off'")
colpali_embedding_model = None
colpali_vector_store = None
case "local":
logger.info("Initializing ColPali in local mode")
from core.embedding.colpali_embedding_model import ColpaliEmbeddingModel
colpali_embedding_model = ColpaliEmbeddingModel()
# Choose multivector store implementation based on provider and dual ingestion setting
if settings.ENABLE_DUAL_MULTIVECTOR_INGESTION:
# Dual ingestion mode: create both stores and wrap them
if not settings.TURBOPUFFER_API_KEY:
raise ValueError("TURBOPUFFER_API_KEY is required when dual ingestion is enabled")
fast_store = FastMultiVectorStore(
uri=settings.POSTGRES_URI, tpuf_api_key=settings.TURBOPUFFER_API_KEY, namespace="public"
)
slow_store = MultiVectorStore(
uri=settings.POSTGRES_URI, enable_external_storage=True, auto_initialize=False
)
colpali_vector_store = DualMultiVectorStore(
fast_store=fast_store, slow_store=slow_store, enable_dual_ingestion=True
)
logger.info("Initialized DualMultiVectorStore for migration (dual ingestion enabled)")
elif settings.MULTIVECTOR_STORE_PROVIDER == "morphik":
if not settings.TURBOPUFFER_API_KEY:
raise ValueError("TURBOPUFFER_API_KEY is required when using morphik multivector store provider")
colpali_vector_store = FastMultiVectorStore(
uri=settings.POSTGRES_URI, tpuf_api_key=settings.TURBOPUFFER_API_KEY, namespace="public"
)
else:
colpali_vector_store = MultiVectorStore(
uri=settings.POSTGRES_URI, enable_external_storage=True, auto_initialize=False
)
case "api":
logger.info("Initializing ColPali in API mode")
colpali_embedding_model = ColpaliApiEmbeddingModel()
# Choose multivector store implementation based on provider and dual ingestion setting
if settings.ENABLE_DUAL_MULTIVECTOR_INGESTION:
# Dual ingestion mode: create both stores and wrap them
if not settings.TURBOPUFFER_API_KEY:
raise ValueError("TURBOPUFFER_API_KEY is required when dual ingestion is enabled")
fast_store = FastMultiVectorStore(
uri=settings.POSTGRES_URI, tpuf_api_key=settings.TURBOPUFFER_API_KEY, namespace="public"
)
slow_store = MultiVectorStore(
uri=settings.POSTGRES_URI, enable_external_storage=True, auto_initialize=False
)
colpali_vector_store = DualMultiVectorStore(
fast_store=fast_store, slow_store=slow_store, enable_dual_ingestion=True
)
logger.info("Initialized DualMultiVectorStore for migration (dual ingestion enabled)")
elif settings.MULTIVECTOR_STORE_PROVIDER == "morphik":
if not settings.TURBOPUFFER_API_KEY:
raise ValueError("TURBOPUFFER_API_KEY is required when using morphik multivector store provider")
colpali_vector_store = FastMultiVectorStore(
uri=settings.POSTGRES_URI, tpuf_api_key=settings.TURBOPUFFER_API_KEY, namespace="public"
)
else:
colpali_vector_store = MultiVectorStore(
uri=settings.POSTGRES_URI, enable_external_storage=True, auto_initialize=False
)
case _:
raise ValueError(f"Unsupported COLPALI_MODE: {settings.COLPALI_MODE}")
# ---------------------------------------------------------------------------
# Document service (ties everything together)
# ---------------------------------------------------------------------------
document_service = DocumentService(
database=database,
vector_store=vector_store,
storage=storage,
parser=parser,
embedding_model=embedding_model,
completion_model=completion_model,
reranker=reranker,
enable_colpali=settings.ENABLE_COLPALI,
colpali_embedding_model=colpali_embedding_model,
colpali_vector_store=colpali_vector_store,
v2_chunk_store=v2_chunk_store,
)
logger.info("Document service initialised")
# ---------------------------------------------------------------------------
# Ingestion service (handles document ingestion operations)
# ---------------------------------------------------------------------------
ingestion_service = IngestionService(
database=database,
vector_store=vector_store,
storage=storage,
parser=parser,
embedding_model=embedding_model,
colpali_embedding_model=colpali_embedding_model,
colpali_vector_store=colpali_vector_store,
)
logger.info("Ingestion service initialised")
# ---------------------------------------------------------------------------
# V2 document service (chunk_v2 store)
# ---------------------------------------------------------------------------
v2_document_service = V2DocumentService(
database=database,
storage=storage,
parser=parser,
embedding_model=embedding_model,
chunk_store=v2_chunk_store,
)
logger.info("V2 document service initialised")
__all__ = [
"settings",
"database",
"vector_store",
"storage",
"embedding_model",
"completion_model",
"document_service",
"ingestion_service",
"v2_chunk_store",
"v2_document_service",
]