77
88from datastew .embedding import Vectorizer
99from datastew .exceptions import ObjectStorageError
10- from datastew .repository . base import BaseRepository
10+ from datastew .process . parsing import DataDictionarySource
1111from datastew .repository .model import Base , Concept , Mapping , MappingResult , Terminology
1212from datastew .repository .pagination import Page
1313
1414logger = logging .getLogger (__name__ )
1515
1616
17- class PostgreSQLRepository ( BaseRepository ) :
17+ class PostgreSQLRepository :
1818 def __init__ (
1919 self ,
2020 connection_string : str ,
@@ -33,7 +33,7 @@ def __init__(
3333 :param pool_timeout: The maximum time (in seconds) to wait for a connection from
3434 the pool before raising an exception.
3535 """
36- super (). __init__ ( vectorizer )
36+ self . vectorizer = vectorizer
3737 self .engine = create_engine (
3838 connection_string , pool_size = pool_size , max_overflow = max_overflow , pool_timeout = pool_timeout
3939 )
@@ -197,6 +197,20 @@ def clear_all(self):
197197 self .session .query (Terminology ).delete ()
198198 self .session .commit ()
199199
200+ def import_data_dictionary (self , data_dictionary : DataDictionarySource , terminology_name : str ):
201+ """Imports a data dictionary, generating concepts and embeddings, and stores them in the database.
202+
203+ :param data_dictionary: Source of variable descriptions and metadata.
204+ :param terminology_name: Name of the terminology being imported.
205+ :raises RuntimeError: If the import or transformation fails.
206+ """
207+ try :
208+ objects = self ._parse_data_dictionary (data_dictionary , terminology_name )
209+ self .store_all (objects )
210+ except Exception as e :
211+ logger .exception ("Failed to import data dictionary." )
212+ raise RuntimeError (f"Failed to import data dictionary source: { e } " )
213+
200214 def import_from_jsonl (
201215 self , jsonl_path : str , object_type : Literal ["terminology" , "concept" , "mapping" ], chunk_size : int = 100
202216 ):
@@ -305,3 +319,27 @@ def _validate_required_fields(
305319 def _initialize_pgvector (self ):
306320 with self .engine .begin () as conn :
307321 conn .execute (text ("CREATE EXTENSION IF NOT EXISTS vector" ))
322+
323+ def _parse_data_dictionary (
324+ self , data_dictionary : DataDictionarySource , terminology_name : str
325+ ) -> List [Union [Concept , Mapping , Terminology ]]:
326+ df = data_dictionary .to_dataframe ()
327+ descriptions = df ["description" ].tolist ()
328+ vectorizer_name = self .vectorizer .model_name
329+ variable_to_embedding = data_dictionary .get_embeddings (self .vectorizer )
330+
331+ terminology = Terminology (name = terminology_name , id = terminology_name )
332+ objects : List [Union [Concept , Mapping , Terminology ]] = [terminology ]
333+
334+ for variable , description in zip (variable_to_embedding .keys (), descriptions ):
335+ concept_id = f"{ terminology_name } :{ variable } "
336+ concept = Concept (terminology = terminology , pref_label = variable , concept_identifier = concept_id )
337+ mapping = Mapping (
338+ concept = concept ,
339+ text = description ,
340+ embedding = variable_to_embedding [variable ],
341+ sentence_embedder = vectorizer_name ,
342+ )
343+ objects .extend ([concept , mapping ])
344+
345+ return objects
0 commit comments