Skip to content

Commit 7b09747

Browse files
authored
Merge pull request #144 from rootcodelabs/wip
Get update from rootcodelabs/LLM-Module wip into rootcodelabs/LLM-Module llm-368
2 parents 17bb3d2 + 1a54c5d commit 7b09747

15 files changed

Lines changed: 227 additions & 33 deletions

GUI/src/pages/TestModel/index.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useMutation, useQuery } from '@tanstack/react-query';
22
import { Button, FormSelect, FormTextarea, Collapsible } from 'components';
33
import CircularSpinner from 'components/molecules/CircularSpinner/CircularSpinner';
4-
import { FC, useState } from 'react';
4+
import { ComponentPropsWithoutRef, FC, useState } from 'react';
55
import { useTranslation } from 'react-i18next';
66
import ReactMarkdown from 'react-markdown';
77
import remarkGfm from 'remark-gfm';
@@ -87,6 +87,17 @@ const TestLLM: FC = () => {
8787
}));
8888
};
8989

90+
const markdownComponents = {
91+
ol: ({children}: any) => (
92+
<ol style={{ paddingLeft: '1.5rem', listStyleType: 'decimal' }}>
93+
{children}
94+
</ol>
95+
),
96+
a: (props: ComponentPropsWithoutRef<"a">) => (
97+
<a {...props} target="_blank" rel="noopener noreferrer" />
98+
),
99+
};
100+
90101
return (
91102
<div>
92103
{isLoadingConnections ? (
@@ -141,7 +152,7 @@ const TestLLM: FC = () => {
141152
<div className="result-item">
142153
<strong>Response:</strong>
143154
<div className="response-content">
144-
<ReactMarkdown remarkPlugins={[remarkGfm]}>
155+
<ReactMarkdown remarkPlugins={[remarkGfm]} components={markdownComponents}>
145156
{inferenceResult.content}
146157
</ReactMarkdown>
147158
</div>
@@ -159,7 +170,7 @@ const TestLLM: FC = () => {
159170
<strong>Rank {contextItem.rank}</strong>
160171
</div>
161172
<div className="context-content">
162-
<ReactMarkdown remarkPlugins={[remarkGfm]}>
173+
<ReactMarkdown remarkPlugins={[remarkGfm]} components={markdownComponents}>
163174
{contextItem.chunkRetrieved}
164175
</ReactMarkdown>
165176
</div>

docker-compose-ec2.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ services:
128128
- REACT_APP_RUUTER_API_URL=https://est-rag-rtc.rootcode.software/ruuter-public
129129
- REACT_APP_RUUTER_PRIVATE_API_URL=https://est-rag-rtc.rootcode.software/ruuter-private
130130
- REACT_APP_CUSTOMER_SERVICE_LOGIN=https://est-rag-rtc.rootcode.software/authentication-layer/et/dev-auth
131-
- REACT_APP_CSP=upgrade-insecure-requests; default-src 'self'; font-src 'self' data:; img-src 'self' data:; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; object-src 'none'; connect-src 'self' http://localhost:8086 http://localhost:8088 http://localhost:3004 http://localhost:3005 ws://localhost https://vault-agent-gui:8202 https://est-rag-rtc.rootcode.software;
131+
- REACT_APP_NOTIFICATION_NODE_URL=https://est-rag-rtc.rootcode.software/notifications-node
132+
- REACT_APP_CSP=upgrade-insecure-requests; default-src 'self'; font-src 'self' data:; img-src 'self' data:; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; object-src 'none'; connect-src 'self' http://localhost:8086 http://localhost:8088 http://localhost:3004 http://localhost:3005 http://localhost:4040 https://vault-agent-gui:8202 ws://localhost https://est-rag-rtc.rootcode.software;
132133
- DEBUG_ENABLED=true
133134
- CHOKIDAR_USEPOLLING=true
134135
- PORT=3001

docker-compose.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@ services:
127127
- REACT_APP_RUUTER_API_URL=http://localhost:8086
128128
- REACT_APP_RUUTER_PRIVATE_API_URL=http://localhost:8088
129129
- REACT_APP_CUSTOMER_SERVICE_LOGIN=http://localhost:3004/et/dev-auth
130-
- REACT_APP_CSP=upgrade-insecure-requests; default-src 'self'; font-src 'self' data:; img-src 'self' data:; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; object-src 'none'; connect-src 'self' http://localhost:8086 http://localhost:8088 http://localhost:3004 http://localhost:3005 https://vault-agent-gui:8202 ws://localhost https://est-rag-rtc.rootcode.software;
130+
- REACT_APP_NOTIFICATION_NODE_URL=http://localhost:4040
131+
- REACT_APP_CSP=upgrade-insecure-requests; default-src 'self'; font-src 'self' data:; img-src 'self' data:; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; object-src 'none'; connect-src 'self' http://localhost:8086 http://localhost:8088 http://localhost:3004 http://localhost:3005 http://localhost:4040 https://vault-agent-gui:8202 ws://localhost https://est-rag-rtc.rootcode.software;
131132
- DEBUG_ENABLED=true
132133
- CHOKIDAR_USEPOLLING=true
133134
- PORT=3001

pyproject.toml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,24 @@ ignore = []
9090
fixable = ["ALL"]
9191
unfixable = []
9292

93+
# Per-file ignores for special cases
94+
[tool.ruff.lint.per-file-ignores]
95+
"tests/**/*.py" = [
96+
"ANN", # Ignore all missing type annotations (ANN001, ANN201, etc.)
97+
"T201", # Allow print statements
98+
]
99+
100+
"src/models/request_models.py" = ["N815"] # camelCase fields required for API contract
101+
"src/optimization/optimized_module_loader.py" = ["N815"] # Pydantic model fields
102+
"src/optimization/optimizers/generator_optimizer.py" = ["N815"] # Pydantic model fields
103+
"src/response_generator/response_generate.py" = ["N815", "ANN401"] # Pydantic model fields + DSPy streamify Any type
104+
105+
# Library interface patterns - legitimate Any usage
106+
"src/contextual_retrieval/contextual_retrieval_api_client.py" = ["ANN401"] # httpx **kwargs pass-through
107+
"src/guardrails/dspy_nemo_adapter.py" = ["ANN401"] # LangChain LLM interface + DSPy dynamic types
108+
"src/llm_orchestrator_config/context_manager.py" = ["ANN401"] # MockResponse with dynamic attributes
109+
"src/optimization/metrics/*.py" = ["ANN401"] # DSPy optimizer trace parameter (internal type)
110+
"byk-stack-setup/script.py" = ["T201"] # CLI script uses print
93111

94112
[tool.ruff.format]
95113
# Like Black, use double quotes for strings.
@@ -123,4 +141,4 @@ exclude = [
123141
]
124142

125143
# --- Global strictness ---
126-
typeCheckingMode = "standard" # Standard typechecking mode
144+
typeCheckingMode = "standard" # Standard typechecking mode

src/contextual_retrieval/bm25_search.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
when collection data changes.
66
"""
77

8-
from typing import List, Dict, Any, Optional, Set
8+
from typing import List, Dict, Any, Optional, Set, TYPE_CHECKING
99
from loguru import logger
1010
from rank_bm25 import BM25Okapi
1111
import re
@@ -20,13 +20,16 @@
2020
)
2121
from contextual_retrieval.config import ConfigLoader, ContextualRetrievalConfig
2222

23+
if TYPE_CHECKING:
24+
from contextual_retrieval.contextual_retrieval_api_client import HTTPClientManager
25+
2326

2427
class SmartBM25Search:
2528
"""In-memory BM25 search with smart refresh capabilities."""
2629

2730
def __init__(
2831
self, qdrant_url: str, config: Optional["ContextualRetrievalConfig"] = None
29-
):
32+
) -> None:
3033
self.qdrant_url = qdrant_url
3134
self._config = config if config is not None else ConfigLoader.load_config()
3235
self._http_client_manager = None
@@ -40,7 +43,7 @@ def __init__(
4043
# Strong references to background tasks to prevent premature GC
4144
self._background_tasks: Set[asyncio.Task[None]] = set()
4245

43-
async def _get_http_client_manager(self):
46+
async def _get_http_client_manager(self) -> "HTTPClientManager":
4447
"""Get the HTTP client manager instance."""
4548
if self._http_client_manager is None:
4649
self._http_client_manager = await get_http_client_manager()
@@ -356,7 +359,7 @@ def _tokenize_text(self, text: str) -> List[str]:
356359
tokens = self.tokenizer_pattern.findall(text.lower())
357360
return tokens
358361

359-
async def close(self):
362+
async def close(self) -> None:
360363
"""Close HTTP client."""
361364
if self._http_client_manager:
362365
await self._http_client_manager.close()

src/contextual_retrieval/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class HttpClientConstants:
1515
DEFAULT_FAILURE_THRESHOLD = 5
1616
DEFAULT_RECOVERY_TIMEOUT = 60.0
1717

18-
# Timeouts (seconds)
18+
# Timeouts in seconds
1919
DEFAULT_READ_TIMEOUT = 30.0
2020
DEFAULT_CONNECT_TIMEOUT = 10.0
2121
DEFAULT_WRITE_TIMEOUT = 10.0

src/contextual_retrieval/contextual_retrieval_api_client.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
class ServiceResilienceManager:
2525
"""Service resilience manager with circuit breaker functionality for HTTP requests."""
2626

27-
def __init__(self, config: Optional["ContextualRetrievalConfig"] = None):
27+
def __init__(self, config: Optional["ContextualRetrievalConfig"] = None) -> None:
2828
# Load configuration if not provided
2929
if config is None:
3030
config = ConfigLoader.load_config()
@@ -81,7 +81,7 @@ class HTTPClientManager:
8181
_instance: Optional["HTTPClientManager"] = None
8282
_lock = asyncio.Lock()
8383

84-
def __init__(self, config: Optional["ContextualRetrievalConfig"] = None):
84+
def __init__(self, config: Optional["ContextualRetrievalConfig"] = None) -> None:
8585
"""Initialize HTTP client manager."""
8686
# Load configuration if not provided
8787
self._config = config if config is not None else ConfigLoader.load_config()
@@ -169,7 +169,7 @@ async def get_client(
169169
SecureErrorHandler.sanitize_error_message(
170170
e, "HTTP client initialization"
171171
)
172-
)
172+
) from e
173173

174174
return self._client
175175

src/contextual_retrieval/contextual_retriever.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def __init__(
4343
config_path: Optional[str] = None,
4444
llm_service: Optional["LLMOrchestrationService"] = None,
4545
shared_bm25: Optional[SmartBM25Search] = None,
46-
):
46+
) -> None:
4747
"""
4848
Initialize contextual retriever.
4949
@@ -120,7 +120,7 @@ async def initialize(self) -> bool:
120120
logger.error(f"Failed to initialize Contextual Retriever: {e}")
121121
return False
122122

123-
def _get_session_llm_service(self):
123+
def _get_session_llm_service(self) -> "LLMOrchestrationService":
124124
"""
125125
Get cached LLM service for current retrieval session.
126126
Uses injected service if available, creates new instance as fallback.
@@ -140,7 +140,7 @@ def _get_session_llm_service(self):
140140

141141
return self._session_llm_service
142142

143-
def _clear_session_cache(self):
143+
def _clear_session_cache(self) -> None:
144144
"""Clear cached connections at end of retrieval session."""
145145
if self._session_llm_service is not None:
146146
logger.debug("Clearing session LLM service cache")
@@ -374,7 +374,9 @@ async def _execute_batch_query_searches(
374374
self._search_single_query_with_embedding(
375375
query, i, embedding, collections, limit
376376
)
377-
for i, (query, embedding) in enumerate(zip(queries, batch_embeddings))
377+
for i, (query, embedding) in enumerate(
378+
zip(queries, batch_embeddings, strict=True)
379+
)
378380
]
379381

380382
# Execute all searches in parallel
@@ -621,7 +623,7 @@ async def health_check(self) -> Dict[str, Any]:
621623

622624
return health_status
623625

624-
async def close(self):
626+
async def close(self) -> None:
625627
"""Clean up resources."""
626628
try:
627629
await self.provider_detection.close()

src/contextual_retrieval/provider_detection.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
- No hardcoded weights or preferences
88
"""
99

10-
from typing import List, Optional, Dict, Any
10+
from typing import List, Optional, Dict, Any, TYPE_CHECKING
1111
from loguru import logger
1212
from contextual_retrieval.contextual_retrieval_api_client import get_http_client_manager
1313
from contextual_retrieval.error_handler import SecureErrorHandler
@@ -18,18 +18,21 @@
1818
)
1919
from contextual_retrieval.config import ConfigLoader, ContextualRetrievalConfig
2020

21+
if TYPE_CHECKING:
22+
from contextual_retrieval.contextual_retrieval_api_client import HTTPClientManager
23+
2124

2225
class DynamicProviderDetection:
2326
"""Dynamic collection selection without hardcoded preferences."""
2427

2528
def __init__(
2629
self, qdrant_url: str, config: Optional["ContextualRetrievalConfig"] = None
27-
):
30+
) -> None:
2831
self.qdrant_url = qdrant_url
2932
self._config = config if config is not None else ConfigLoader.load_config()
3033
self._http_client_manager = None
3134

32-
async def _get_http_client_manager(self):
35+
async def _get_http_client_manager(self) -> "HTTPClientManager":
3336
"""Get the HTTP client manager instance."""
3437
if self._http_client_manager is None:
3538
self._http_client_manager = await get_http_client_manager()
@@ -212,7 +215,7 @@ async def get_collection_stats(self) -> Dict[str, Any]:
212215

213216
return stats
214217

215-
async def close(self):
218+
async def close(self) -> None:
216219
"""Close HTTP client."""
217220
if self._http_client_manager:
218221
await self._http_client_manager.close()

src/contextual_retrieval/qdrant_search.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
existing contextual embeddings created by the vector indexer.
66
"""
77

8-
from typing import List, Dict, Any, Optional, Protocol
8+
from typing import List, Dict, Any, Optional, Protocol, TYPE_CHECKING
99
from loguru import logger
1010
import asyncio
1111
from contextual_retrieval.contextual_retrieval_api_client import get_http_client_manager
@@ -17,6 +17,9 @@
1717
)
1818
from contextual_retrieval.config import ConfigLoader, ContextualRetrievalConfig
1919

20+
if TYPE_CHECKING:
21+
from contextual_retrieval.contextual_retrieval_api_client import HTTPClientManager
22+
2023

2124
class LLMServiceProtocol(Protocol):
2225
"""Protocol defining the interface required from LLM service for embedding operations."""
@@ -47,12 +50,12 @@ class QdrantContextualSearch:
4750

4851
def __init__(
4952
self, qdrant_url: str, config: Optional["ContextualRetrievalConfig"] = None
50-
):
53+
) -> None:
5154
self.qdrant_url = qdrant_url
5255
self._config = config if config is not None else ConfigLoader.load_config()
5356
self._http_client_manager = None
5457

55-
async def _get_http_client_manager(self):
58+
async def _get_http_client_manager(self) -> "HTTPClientManager":
5659
"""Get the HTTP client manager instance."""
5760
if self._http_client_manager is None:
5861
self._http_client_manager = await get_http_client_manager()
@@ -345,7 +348,7 @@ def get_embeddings_for_queries_batch(
345348
logger.error(f"Failed to get batch embeddings: {e}")
346349
return None
347350

348-
async def close(self):
351+
async def close(self) -> None:
349352
"""Close HTTP client."""
350353
if self._http_client_manager:
351354
await self._http_client_manager.close()

0 commit comments

Comments
 (0)