TriCacheLLM-MMA 0.1.0__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.
@@ -0,0 +1,132 @@
1
+ # File: portable_cache_Ai/portable_cache_rerankAi.py
2
+ import cohere
3
+ from typing import Optional, Any
4
+ from pathlib import Path
5
+ from sqlalchemy import create_engine
6
+ from sqlalchemy.orm import sessionmaker
7
+ from langchain_core.documents import Document as LangChainDocument
8
+ from portable_cache_utils.protable_cache_DynamicEnv_maker import get_settings
9
+ from portable_cache_dbSchema import Paths
10
+
11
+ class CohereManager:
12
+ """Encapsulates the Cohere client to prevent import-time crashes."""
13
+ def __init__(self):
14
+ self._client: Optional[cohere.ClientV2] = None
15
+ self._current_api_key: Optional[str] = None
16
+
17
+ def _get_cohere_api_key_from_registry(self) -> Optional[str]:
18
+ """Sneaks a peek into the SQLite registry DB to grab the true source-of-truth cohere_api_key."""
19
+ try:
20
+ settings = get_settings()
21
+ db_path = Path(settings.portable_cache_registry_db)
22
+ if not db_path.exists():
23
+ return None
24
+
25
+ sync_engine = create_engine(f"sqlite:///{db_path}")
26
+ SessionLocal = sessionmaker(bind=sync_engine)
27
+ with SessionLocal() as session:
28
+ path_record = session.query(Paths).filter_by(id=1).first()
29
+
30
+ sync_engine.dispose()
31
+ if path_record and path_record.cohere_api_key:
32
+ return path_record.cohere_api_key
33
+ except Exception:
34
+ pass
35
+ return None
36
+
37
+ def get_client(self, api_key: Optional[str] = None) -> cohere.ClientV2:
38
+ """Lazily initializes the Cohere V2 client using explicit arg, registry DB, or settings/env."""
39
+ settings = get_settings()
40
+
41
+ target_api_key = api_key or self._get_cohere_api_key_from_registry() or settings.portable_cache_cohere_api_key
42
+
43
+ if not target_api_key:
44
+ raise ValueError("Cohere API key not found! Run create_cache_system first or set your API key.")
45
+
46
+ if self._client is None or self._current_api_key != target_api_key:
47
+ self._current_api_key = target_api_key
48
+ self._client = cohere.ClientV2(api_key=target_api_key)
49
+
50
+ return self._client
51
+
52
+ cohere_manager = CohereManager()
53
+
54
+ async def portable_cache_cohere_rerank(
55
+ question: str,
56
+ user_id: Any,
57
+ received_docs: list[LangChainDocument],
58
+ top_k: int,
59
+ ) -> dict:
60
+ """
61
+ Enterprise portable wrapper for document reranking using Cohere's native cross-encoder API.
62
+ Returns a clean dict: {"success": bool, "data": list[LangChainDocument] | None, "error": str | None}
63
+ """
64
+ print(f"CACHE_RERANK_STARTED where user_id: {user_id}")
65
+
66
+ if not question or not question.strip():
67
+ print(f"CACHE_RERANK_FAILED: Empty input question for user_id: {user_id}")
68
+ return {
69
+ "success": False,
70
+ "data": None,
71
+ "error": "Input text is empty"
72
+ }
73
+
74
+ if not received_docs:
75
+ print(f"CACHE_RERANK_FAILED: No documents received for user_id: {user_id}")
76
+ return {
77
+ "success": False,
78
+ "data": None,
79
+ "error": "Re-ranker got no data, meaning retriever returned empty candidates."
80
+ }
81
+
82
+ documents_text = [doc.page_content for doc in received_docs]
83
+
84
+ try:
85
+ print(f"CACHE_RERANK_PROVIDER_REQUEST where user_id: {user_id}")
86
+ client = cohere_manager.get_client()
87
+ rerank_model = get_settings().portable_cache_cohere_rerank_model
88
+
89
+ response = client.rerank(
90
+ model=rerank_model,
91
+ query=question,
92
+ documents=documents_text,
93
+ top_n=min(top_k, len(documents_text)),
94
+ )
95
+ print(f"CACHE_RERANK_PROVIDER_SUCCESS where user_id: {user_id}")
96
+ except Exception as e:
97
+ print(f"CACHE_RERANK_ERROR where error: {str(e)} and user_id: {user_id}")
98
+ return {
99
+ "success": False,
100
+ "data": None,
101
+ "error": str(e)
102
+ }
103
+
104
+ print(f"CACHE_RERANK_MAPPING_STARTED where user_id: {user_id}")
105
+ reranked_docs: list[LangChainDocument] = []
106
+ try:
107
+ for result in response.results:
108
+ original_doc = received_docs[result.index]
109
+ updated_metadata = dict(original_doc.metadata or {})
110
+ updated_metadata["rerank_score"] = float(result.relevance_score)
111
+
112
+ reranked_docs.append(
113
+ LangChainDocument(
114
+ page_content=original_doc.page_content,
115
+ metadata=updated_metadata,
116
+ )
117
+ )
118
+ print(f"CACHE_RERANK_MAPPING_SUCCESS where user_id: {user_id}")
119
+ except Exception as e:
120
+ print(f"CACHE_RERANK_MAPPING_ERROR where error: {str(e)} and user_id: {user_id}")
121
+ return {
122
+ "success": False,
123
+ "data": None,
124
+ "error": "Failed to map reranked results to documents."
125
+ }
126
+
127
+ print(f"CACHE_RERANK_COMPLETED where user_id: {user_id}")
128
+ return {
129
+ "success": True,
130
+ "data": reranked_docs,
131
+ "error": None
132
+ }
@@ -0,0 +1,51 @@
1
+ # File: portable_cache_bgWorkers/portable_cache_celery_conf.py
2
+ from pathlib import Path
3
+ from celery import Celery
4
+ from sqlalchemy import create_engine
5
+ from sqlalchemy.orm import sessionmaker
6
+ from portable_cache_utils.protable_cache_DynamicEnv_maker import get_settings
7
+ from portable_cache_dbSchema import Paths
8
+
9
+ def get_celery_redis_url() -> str:
10
+ """Sneaks a peek into the SQLite registry DB to grab the true source-of-truth redis_url for Celery."""
11
+ try:
12
+ settings = get_settings()
13
+ if settings.protable_cache_registry_db:
14
+ db_path = Path(settings.protable_cache_registry_db)
15
+ if db_path.exists():
16
+ sync_engine = create_engine(f"sqlite:///{db_path}")
17
+ SessionLocal = sessionmaker(bind=sync_engine)
18
+ with SessionLocal() as session:
19
+ path_record = session.query(Paths).filter_by(id=1).first()
20
+ sync_engine.dispose()
21
+ if path_record and path_record.redis_url:
22
+ return path_record.redis_url
23
+ except Exception:
24
+ pass
25
+
26
+ return get_settings().portable_cache_redis_url
27
+
28
+ redis_base_url = get_celery_redis_url()
29
+
30
+ celery_app = Celery(
31
+ "fastapi_ai_backend",
32
+ broker=redis_base_url,
33
+ backend=redis_base_url.rsplit("/", 1)[0] + "/1",
34
+ )
35
+
36
+ celery_app.conf.imports = (
37
+ "portable_cache_bgWorkers.portable_cache_workers",
38
+ )
39
+
40
+ celery_app.conf.task_default_queue = "default"
41
+ celery_app.conf.task_routes = {
42
+ "ai.*": {
43
+ "queue": "ai"
44
+ },
45
+ "retri.*": {
46
+ "queue": "retri"
47
+ },
48
+ "maintenance.*": {
49
+ "queue": "maintenance"
50
+ },
51
+ }
@@ -0,0 +1,163 @@
1
+ # File: portable_cache_bgWorkers/portable_cache_workers.py
2
+ import asyncio
3
+ from pathlib import Path
4
+ from typing import Any
5
+ from portable_cache_bgWorkers.portable_cache_celery_conf import celery_app
6
+ from portable_cache_schemas.portable_cache_dbConf import db_manager
7
+ import json
8
+ from portable_cache_dbSchema import CacheVDBResource
9
+ from portable_cache_utils.protable_cache_DynamicEnv_maker import get_settings
10
+ from portable_cache_schemas.portable_cache_schemas import CacheVDBStatus
11
+ from langchain_core.documents import Document as LangChainDocument
12
+ from sqlalchemy import select
13
+ from portable_cache_utils.portable_cache_embedding_model import embedding_model
14
+ from langchain_chroma import Chroma
15
+ from datetime import datetime, timezone
16
+ from portable_cache_dbSchema import Paths
17
+ from sqlalchemy import text
18
+ import time
19
+
20
+ @celery_app.task(bind=True, max_retries=3, name="ai.cache_vdb")
21
+ def create_cache_vdb_worker(self, user_id: int):
22
+ try:
23
+ return asyncio.run(
24
+ create_cache_vdb_async(
25
+ task_instance=self,
26
+ user_id=user_id,
27
+ )
28
+ )
29
+ except Exception as exc:
30
+ raise self.retry(exc=exc, countdown=10)
31
+
32
+ async def create_cache_vdb_async(task_instance: Any, user_id: int):
33
+ async with db_manager.celery_session() as db:
34
+ try:
35
+ result = await db.execute(select(Paths).filter_by(id=1))
36
+ path_record = result.scalars().first()
37
+
38
+ if path_record and path_record.chroma_db_dir:
39
+ base_chroma_dir = path_record.chroma_db_dir
40
+ else:
41
+ base_chroma_dir = get_settings().portable_cache_chroma_db_dir
42
+
43
+ user_cache_dir = Path(base_chroma_dir) / f"user_{user_id}"
44
+ await asyncio.to_thread(
45
+ user_cache_dir.mkdir,
46
+ parents=True,
47
+ exist_ok=True,
48
+ )
49
+
50
+ await asyncio.to_thread(
51
+ lambda: Chroma(
52
+ collection_name=f"question_cache_{user_id}",
53
+ embedding_function=embedding_model,
54
+ persist_directory=str(user_cache_dir),
55
+ )
56
+ )
57
+
58
+ stmt = select(CacheVDBResource).where(
59
+ CacheVDBResource.user_id == user_id
60
+ )
61
+ result = await db.execute(stmt)
62
+ cache_res = result.scalar_one_or_none()
63
+
64
+ if cache_res is None:
65
+ raise RuntimeError(
66
+ f"Cache VDB resource record not found in DB for user {user_id}"
67
+ )
68
+
69
+ cache_res.status = CacheVDBStatus.READY
70
+ cache_res.vdb_path = str(user_cache_dir)
71
+ cache_res.failure_reason = None
72
+ await db.commit()
73
+
74
+ return {
75
+ "status": "READY",
76
+ "user_id": user_id,
77
+ }
78
+
79
+ except Exception as exc:
80
+ stmt = select(CacheVDBResource).where(
81
+ CacheVDBResource.user_id == user_id
82
+ )
83
+ result = await db.execute(stmt)
84
+ cache_res = result.scalar_one_or_none()
85
+
86
+ if cache_res:
87
+ cache_res.status = CacheVDBStatus.FAILED
88
+ cache_res.failure_reason = str(exc)
89
+ await db.commit()
90
+
91
+ raise
92
+
93
+
94
+ @celery_app.task(bind=True, max_retries=3, name="ai.push_cache_vdb")
95
+ def push_responce_in_cache_worker(self, user_id: int, question: str, model_output_dict: dict):
96
+ try:
97
+ return asyncio.run(
98
+ push_response_in_cache_async(
99
+ task_instance=self,
100
+ user_id=user_id,
101
+ question=question,
102
+ model_output_dict=model_output_dict
103
+ )
104
+ )
105
+ except Exception as exc:
106
+ raise self.retry(exc=exc, countdown=10)
107
+
108
+ async def push_response_in_cache_async(task_instance: Any, user_id, question: str, model_output_dict: dict) -> str | None:
109
+ print(f"CACHE_VDB_PUSH_ASYNC_ENTERED where user_id: {user_id}")
110
+ async with db_manager.celery_session() as db:
111
+ try:
112
+ response_json_str = json.dumps(model_output_dict)
113
+
114
+ cache_metadata = {
115
+ "user_id": user_id,
116
+ "question": question,
117
+ "llm_response": response_json_str,
118
+ "created_at": datetime.now(timezone.utc).isoformat(),
119
+ "timestamp": time.time()
120
+ }
121
+
122
+ cache_document = LangChainDocument(
123
+ page_content=question,
124
+ metadata=cache_metadata
125
+ )
126
+
127
+ stmt = select(CacheVDBResource).where(
128
+ CacheVDBResource.user_id == user_id
129
+ )
130
+
131
+ result = await db.execute(stmt)
132
+ cache_res = result.scalar_one_or_none()
133
+
134
+ if cache_res is None:
135
+ raise RuntimeError(
136
+ f"Cache VDB resource record not found for user {user_id}"
137
+ )
138
+
139
+ if not cache_res.vdb_path:
140
+ raise RuntimeError(
141
+ f"Cache VDB path not found for user {user_id}"
142
+ )
143
+
144
+ user_cache_vdb_path = Path(cache_res.vdb_path)
145
+
146
+ user_cache_vdb = await asyncio.to_thread(
147
+ lambda: Chroma(
148
+ collection_name=f"question_cache_{user_id}",
149
+ embedding_function=embedding_model,
150
+ persist_directory=str(user_cache_vdb_path),
151
+ )
152
+ )
153
+
154
+ await asyncio.to_thread(
155
+ user_cache_vdb.add_documents,
156
+ documents=[cache_document]
157
+ )
158
+
159
+ return cache_metadata["created_at"]
160
+
161
+ except Exception as exc:
162
+ print(f"AI_SERVICE_FAILED, ---WARNING--- | user_id: {user_id} and error: {str(exc)}")
163
+ raise
@@ -0,0 +1,3 @@
1
+ # File: portable_cache_schemas/portable_cache_dbBase.py
2
+ from sqlalchemy.orm import declarative_base
3
+ Base = declarative_base()
@@ -0,0 +1,147 @@
1
+ # File: portable_cache_schemas/portable_cache_dbConf.py
2
+ import sqlite3
3
+ from pathlib import Path
4
+ from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
5
+ from sqlalchemy import event
6
+ from portable_cache_schemas.portable_cache_dbBase import Base
7
+ from portable_cache_utils.protable_cache_DynamicEnv_maker import get_settings
8
+
9
+
10
+ class DatabaseManager:
11
+ """
12
+ Professional Singleton Manager to handle dynamic engine creation
13
+ without module-level 'None' globals or manual boot order guessing.
14
+ """
15
+ def __init__(self):
16
+ self.celery_engine = None
17
+ self.norma_engine = None
18
+ self.CelerySessionLocal = None
19
+ self.AsyncSessionLocal = None
20
+ self._initialized = False
21
+
22
+ def initialize(self, db_path: str | Path):
23
+ """Explicitly initializes the engines and session makers."""
24
+ if self._initialized:
25
+ return
26
+
27
+ resolved_path = Path(db_path)
28
+ resolved_path.parent.mkdir(parents=True, exist_ok=True)
29
+ DATABASE_URL = f"sqlite+aiosqlite:///{resolved_path}"
30
+
31
+ self.celery_engine = create_async_engine(
32
+ DATABASE_URL,
33
+ connect_args={"timeout": 30},
34
+ )
35
+ self.norma_engine = create_async_engine(
36
+ DATABASE_URL,
37
+ pool_size=20,
38
+ max_overflow=10,
39
+ pool_timeout=30,
40
+ pool_recycle=3600
41
+ )
42
+
43
+ self.CelerySessionLocal = async_sessionmaker(
44
+ bind=self.celery_engine,
45
+ class_=AsyncSession,
46
+ autoflush=False,
47
+ expire_on_commit=False,
48
+ )
49
+
50
+ self.AsyncSessionLocal = async_sessionmaker(
51
+ bind=self.norma_engine,
52
+ class_=AsyncSession,
53
+ autoflush=False,
54
+ expire_on_commit=False,
55
+ )
56
+
57
+ @event.listens_for(self.celery_engine.sync_engine, "connect")
58
+ #"connect" is a SQLAlchemy lifecycle event. It tells SQLAlchemy: "Fire this function the exact millisecond a brand new raw
59
+ #connection to the SQLite database is successfully opened."
60
+ #now sqlite3 is syncro to rlly catch the new connection we need to tap into sync_engine!
61
+ def set_sqlite_pragma(dbapi_connection, connection_record):
62
+ #raw database connection -> dbapi_connection
63
+ #connection_record -> its detail
64
+ cursor = dbapi_connection.cursor()
65
+ cursor.execute("PRAGMA foreign_keys=ON")
66
+ cursor.close()
67
+ #no return was intentional
68
+
69
+ self._initialized = True #made ture for said obj
70
+
71
+ def _auto_bootstrap_if_needed(self):
72
+ """Self-heals and auto-initializes if a worker or process calls it blindly."""
73
+ if self._initialized:
74
+ return #now we return not above here
75
+
76
+ try:
77
+ settings = get_settings()
78
+ registry_db = getattr(settings, "portable_cache_registry_db", None)
79
+ if registry_db and Path(registry_db).exists():
80
+ conn = sqlite3.connect(registry_db)
81
+ cursor = conn.cursor()
82
+ cursor.execute("SELECT db_path FROM paths WHERE id = 1")
83
+ row = cursor.fetchone()
84
+ conn.close()
85
+
86
+ if row and row[0]:
87
+ self.initialize(row[0])
88
+ return
89
+ except Exception:
90
+ pass
91
+
92
+ raise RuntimeError(
93
+ "Database not initialized! Call init_cache_database(db_path) explicitly "
94
+ "or ensure the registry database is seeded."
95
+ )
96
+
97
+ #oh ok ig ill tell u, @property is like typedeff of c++ on drungs asside form being a rename its capable of running stuff as u can see
98
+ #when i need CelerySessionLocal instead of me doing: async with db_manager.CelerySessionLocal as db: i can simaplly async with db_manager.async_session() as db:
99
+ @property
100
+ def celery_session(self):
101
+ self._auto_bootstrap_if_needed()
102
+ return self.CelerySessionLocal
103
+
104
+ @property
105
+ def async_session(self):
106
+ self._auto_bootstrap_if_needed()
107
+ return self.AsyncSessionLocal
108
+
109
+
110
+ # Instantiate a single global manager for the application lifecycle
111
+ db_manager = DatabaseManager()
112
+
113
+
114
+ def init_cache_database(db_path: str | Path):
115
+ """Initializes engines and session makers using the path provided by the user's system startup."""
116
+ db_manager.initialize(db_path)
117
+
118
+
119
+ async def init_db_tables():
120
+ if db_manager.celery_engine is None: #u may ask this wouldnt happen tho?
121
+ db_manager._auto_bootstrap_if_needed() #and if it did inside it we are accessing settings() which isnt created on 1st run
122
+ #ur correct! this is here for nth run, where env is alredy created so settings() would exist dw! for cold start!
123
+
124
+ async with db_manager.celery_engine.begin() as conn:
125
+ await conn.run_sync(Base.metadata.create_all)
126
+
127
+
128
+ async def get_db():
129
+ """Dependency for yielding database sessions safely with automatic lazy loading."""
130
+ SessionMaker = db_manager.async_session
131
+ async with SessionMaker() as session:
132
+ yield session
133
+
134
+
135
+ # PEP 562 Module-Level Dynamic Attributes for legacy code/imports compatibility
136
+ def __getattr__(name):
137
+ if name == "CelerySessionLocal":
138
+ return db_manager.celery_session
139
+ if name == "AsyncSessionLocal":
140
+ return db_manager.async_session
141
+ if name == "celery_engine":
142
+ db_manager._auto_bootstrap_if_needed()
143
+ return db_manager.celery_engine
144
+ if name == "norma_engine":
145
+ db_manager._auto_bootstrap_if_needed()
146
+ return db_manager.norma_engine
147
+ raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
@@ -0,0 +1,8 @@
1
+ # File: portable_cache_schemas/portable_cache_schemas.py
2
+
3
+ import enum
4
+ class CacheVDBStatus(enum.Enum):
5
+ PENDING = "PENDING"
6
+ PROCESSING = "PROCESSING"
7
+ READY = "READY"
8
+ FAILED = "FAILED"
@@ -0,0 +1,7 @@
1
+ # # File: portable_cache_utils/portable_cache_embedding_model.py
2
+ from langchain_huggingface import HuggingFaceEmbeddings
3
+ from portable_cache_utils.protable_cache_DynamicEnv_maker import get_settings
4
+
5
+ embedding_model = HuggingFaceEmbeddings(
6
+ model_name=get_settings().portable_cache_cache_proj_embedding_model
7
+ )
@@ -0,0 +1,152 @@
1
+ # File: portable_cache_utils/protable_cache_DynamicEnv_maker.py
2
+ import os
3
+ from pathlib import Path
4
+ from typing import Any, Optional
5
+ from pydantic_settings import BaseSettings, SettingsConfigDict
6
+ from portable_cache_dbSchema import Paths
7
+ from sqlalchemy import create_engine, select
8
+ from pydantic import model_validator
9
+
10
+
11
+
12
+ _INTERNAL_ENV_FILE = (
13
+ Path.cwd()
14
+ / ".portable_cache_internal"
15
+ / ".env_protable_cache"
16
+ )
17
+
18
+ class Settings(BaseSettings):
19
+ portable_cache_embedding_model: str = "all-MiniLM-L6-v2"
20
+ portable_cache_chroma_db_dir: str = "./chroma_cache_storage"
21
+ portable_cache_cohere_rerank_model: str = "rerank-english-v3.0"
22
+ portable_cache_cohere_api_key: Optional[str] = None
23
+ portable_cache_redis_url: str = "redis://localhost:6379/0"
24
+ portable_cache_registry_db: Optional[str] = None
25
+ portable_cache_cache_proj_embedding_model: str = "sentence-transformers/all-MiniLM-L6-v2"
26
+
27
+ @model_validator(mode="after")
28
+ def assemble_registry_path(self) -> "Settings":
29
+ if not self.portable_cache_registry_db:
30
+ self.portable_cache_registry_db = str(
31
+ Path(self.portable_cache_chroma_db_dir) / "registry.db"
32
+ )
33
+ return self
34
+
35
+ model_config = SettingsConfigDict(
36
+ env_file=_INTERNAL_ENV_FILE if _INTERNAL_ENV_FILE.exists() else (
37
+ Path(__file__).resolve().parent.parent
38
+ / ".portable_cache_internal"
39
+ / ".env_protable_cache"
40
+ ),
41
+ env_file_encoding="utf-8",
42
+ extra="ignore"
43
+ )
44
+
45
+ def get_settings() -> Settings:
46
+ """Always returns a fresh Settings instance loaded from current environment / file."""
47
+ return Settings()
48
+
49
+
50
+ def system_key(redis_url: str, cohere_api_key: str, chroma_db_dir: str = "./chroma_cache_storage", local_cache_dir: Path = None, portable_cache_registry_db: Path = None) -> dict[str, Any]:
51
+ if not redis_url or not cohere_api_key:
52
+ raise ValueError("'redis_url' and 'cohere_api_key' are strictly required to initialize the cache system.")
53
+
54
+ try:
55
+ resolved_chroma = str(Path(chroma_db_dir).resolve())
56
+
57
+ if local_cache_dir:
58
+ cache_dir = Path(local_cache_dir)
59
+ else:
60
+ cache_dir = (Path.cwd() / ".portable_cache_internal")
61
+
62
+ cache_dir.mkdir(parents=True, exist_ok=True)
63
+
64
+ if portable_cache_registry_db:
65
+ db_file = portable_cache_registry_db.resolve()
66
+ else:
67
+ db_file = cache_dir / "registry.db"
68
+ db_file.parent.mkdir(parents=True, exist_ok=True)
69
+
70
+ resolved_db_path = str(db_file)
71
+ env_file = cache_dir / ".env_protable_cache"
72
+
73
+ env_lines = []
74
+ if env_file.exists():
75
+ env_lines = env_file.read_text().splitlines()
76
+
77
+ configs = {
78
+ "PORTABLE_CACHE_REDIS_URL": redis_url,
79
+ "PORTABLE_CACHE_COHERE_API_KEY": cohere_api_key,
80
+ "PORTABLE_CACHE_CHROMA_DB_DIR": resolved_chroma,
81
+ "PORTABLE_CACHE_REGISTRY_DB": resolved_db_path
82
+ }
83
+
84
+ for key, val in configs.items():
85
+ os.environ[key] = val
86
+ updated = False
87
+ for i, line in enumerate(env_lines):
88
+ if line.startswith(f"{key}="):
89
+ env_lines[i] = f"{key}={val}"
90
+ updated = True
91
+ break
92
+ if not updated:
93
+ env_lines.append(f"{key}={val}")
94
+
95
+ env_file.write_text("\n".join(env_lines) + "\n")
96
+
97
+ sync_engine = create_engine(f"sqlite:///{db_file}")
98
+ from sqlalchemy.orm import sessionmaker
99
+ SessionLocal = sessionmaker(bind=sync_engine)
100
+
101
+ with SessionLocal() as session:
102
+ path_record = session.query(Paths).filter_by(id=1).first()
103
+ if path_record:
104
+ path_record.portable_env_path = str(env_file.resolve())
105
+ path_record.chroma_db_dir = resolved_chroma
106
+ path_record.redis_url = redis_url
107
+ path_record.db_path = resolved_db_path
108
+ path_record.cohere_api_key = cohere_api_key
109
+ else:
110
+ path_record = Paths(
111
+ id=1,
112
+ portable_env_path=str(env_file.resolve()),
113
+ chroma_db_dir=resolved_chroma,
114
+ redis_url=redis_url,
115
+ db_path=resolved_db_path,
116
+ cohere_api_key=cohere_api_key
117
+ )
118
+ session.add(path_record)
119
+ session.commit()
120
+
121
+ print("Portable Cache initialized, saved to .env, and recorded in registry Paths table successfully!")
122
+ return {"success": True, "configured": list(configs.keys())}
123
+
124
+ except Exception as e:
125
+ print(f"Error initializing Portable Cache configuration: {str(e)}")
126
+ return {"success": False, "error": str(e), "configured": []}
127
+
128
+
129
+ async def get_stored_paths() -> dict:
130
+ """Instantly pulls absolute paths and credentials from SQLite,
131
+ immune to working directory changes.
132
+ """
133
+ from portable_cache_schemas.portable_cache_dbConf import db_manager
134
+
135
+ async with db_manager.async_session() as session:
136
+ result = await session.execute(
137
+ select(Paths).filter_by(id=1)
138
+ )
139
+ record = result.scalars().first()
140
+
141
+ if not record:
142
+ raise RuntimeError(
143
+ "Portable Cache not initialized! Run system_key() first."
144
+ )
145
+
146
+ return {
147
+ "env_path": record.portable_env_path,
148
+ "chroma_dir": record.chroma_db_dir,
149
+ "redis_url": record.redis_url,
150
+ "db_path": record.db_path,
151
+ "cohere_api_key": record.cohere_api_key,
152
+ }