pirag 0.1.7__py3-none-any.whl → 0.2.2__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.
- app/main.py +47 -65
- app/rag/agent/services.py +11 -0
- app/rag/api.py +40 -0
- app/rag/cli.py +54 -0
- app/rag/config.py +115 -122
- app/rag/embedding/client.py +70 -0
- app/rag/embedding/services.py +26 -0
- app/rag/llm/client.py +128 -0
- app/rag/llm/services.py +26 -0
- app/rag/llm/utilities.py +40 -0
- app/rag/models.py +19 -0
- app/rag/routers.py +41 -0
- app/rag/utilities.py +15 -0
- app/rag/v1/routers.py +7 -0
- app/rag/vector_store/client.py +84 -0
- app/rag/vector_store/services.py +56 -0
- app/requirements.txt +6 -5
- app/setup.py +2 -3
- {pirag-0.1.7.dist-info → pirag-0.2.2.dist-info}/METADATA +6 -3
- pirag-0.2.2.dist-info/RECORD +27 -0
- {pirag-0.1.7.dist-info → pirag-0.2.2.dist-info}/WHEEL +1 -1
- app/rag/agent.py +0 -64
- app/rag/ask/__init__.py +0 -2
- app/rag/ask/config.py +0 -9
- app/rag/ask/router.py +0 -4
- app/rag/doctor/__init__.py +0 -2
- app/rag/doctor/config.py +0 -24
- app/rag/doctor/router.py +0 -4
- app/rag/test/__init__.py +0 -2
- app/rag/test/config.py +0 -9
- app/rag/test/router.py +0 -4
- app/rag/train/__init__.py +0 -2
- app/rag/train/config.py +0 -20
- app/rag/train/router.py +0 -4
- app/rag/train/service.py +0 -0
- pirag-0.1.7.dist-info/RECORD +0 -27
- /app/rag/{ask/service.py → test/client.py} +0 -0
- /app/rag/{doctor/service.py → train/client.py} +0 -0
- /app/rag/{test/service.py → v1/services.py} +0 -0
- {pirag-0.1.7.dist-info → pirag-0.2.2.dist-info}/entry_points.txt +0 -0
- {pirag-0.1.7.dist-info → pirag-0.2.2.dist-info}/licenses/LICENSE +0 -0
- {pirag-0.1.7.dist-info → pirag-0.2.2.dist-info}/top_level.txt +0 -0
app/rag/llm/client.py
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
import requests
|
2
|
+
import time
|
3
|
+
from langchain_openai.llms import OpenAI
|
4
|
+
from typing import Dict, Tuple, Any, List, Optional
|
5
|
+
|
6
|
+
import app.rag.config as cfn
|
7
|
+
from app.rag.utilities import connection_check
|
8
|
+
from .utilities import MetricCallbackHandler
|
9
|
+
|
10
|
+
class LLMClient:
|
11
|
+
def __init__(self, base_url: str, api_key: str, model: str):
|
12
|
+
self.base_url = base_url
|
13
|
+
self.api_key = api_key
|
14
|
+
self.model = model
|
15
|
+
self._is_connected = True
|
16
|
+
self._client = None
|
17
|
+
|
18
|
+
if self.check_connection():
|
19
|
+
try:
|
20
|
+
self._client = OpenAI(
|
21
|
+
base_url = base_url,
|
22
|
+
api_key = api_key,
|
23
|
+
model = model
|
24
|
+
)
|
25
|
+
except Exception as e:
|
26
|
+
self._is_connected = False
|
27
|
+
|
28
|
+
def check_connection(self) -> bool:
|
29
|
+
"""Check if the LLM server is accessible"""
|
30
|
+
try:
|
31
|
+
requests.head(url=self.base_url, timeout=5)
|
32
|
+
except requests.exceptions.ConnectionError:
|
33
|
+
self._is_connected = False
|
34
|
+
return False
|
35
|
+
self._is_connected = True
|
36
|
+
return True
|
37
|
+
|
38
|
+
@connection_check
|
39
|
+
def generate(self, prompt: str) -> tuple:
|
40
|
+
"""Generate text from prompt and return usage information
|
41
|
+
|
42
|
+
Returns:
|
43
|
+
tuple: (generated_text, usage_info)
|
44
|
+
"""
|
45
|
+
if not self._is_connected or self._client is None:
|
46
|
+
return "", {}
|
47
|
+
|
48
|
+
response = self._client.generate([prompt])
|
49
|
+
return response.generations[0][0].text, response.llm_output
|
50
|
+
|
51
|
+
@connection_check
|
52
|
+
def generate_with_metrics(self, prompt: str) -> Tuple[str, Dict[str, Any]]:
|
53
|
+
"""Generate text with timing and usage metrics
|
54
|
+
|
55
|
+
Returns:
|
56
|
+
tuple: (generated_text, metrics_info)
|
57
|
+
"""
|
58
|
+
if not self._is_connected or self._client is None:
|
59
|
+
return "", {"error": "LLM client not connected"}
|
60
|
+
|
61
|
+
handler = MetricCallbackHandler()
|
62
|
+
|
63
|
+
# Create streaming client with callback
|
64
|
+
streaming_client = OpenAI(
|
65
|
+
base_url=self.base_url,
|
66
|
+
api_key=self.api_key,
|
67
|
+
model=self.model,
|
68
|
+
streaming=True,
|
69
|
+
callbacks=[handler]
|
70
|
+
)
|
71
|
+
|
72
|
+
# Make a single request
|
73
|
+
response = streaming_client.generate([prompt], callbacks=[handler])
|
74
|
+
|
75
|
+
# Get base metrics from response
|
76
|
+
metrics = {}
|
77
|
+
|
78
|
+
# Extract token usage from response
|
79
|
+
llm_output = response.llm_output if hasattr(response, 'llm_output') else {}
|
80
|
+
|
81
|
+
# Check if token_usage exists in the response
|
82
|
+
token_usage = llm_output.get('token_usage', {})
|
83
|
+
if token_usage:
|
84
|
+
# If token_usage is available, copy it to our metrics
|
85
|
+
metrics.update(token_usage)
|
86
|
+
|
87
|
+
# Add model name if available
|
88
|
+
if 'model_name' in llm_output:
|
89
|
+
metrics['model'] = llm_output['model_name']
|
90
|
+
else:
|
91
|
+
metrics['model'] = self.model
|
92
|
+
|
93
|
+
# Calculate and add timing metrics
|
94
|
+
metrics['ttft'] = handler.ttft or 0.0
|
95
|
+
metrics['total_time'] = (handler.end_time or time.time()) - handler.start_time
|
96
|
+
metrics['tokens_per_second'] = handler.calculate_tokens_per_second()
|
97
|
+
metrics['completion_tokens'] = handler.token_count
|
98
|
+
|
99
|
+
return handler.result, metrics
|
100
|
+
|
101
|
+
@connection_check
|
102
|
+
def list_models(self) -> list:
|
103
|
+
"""List available models"""
|
104
|
+
if not self._is_connected:
|
105
|
+
return []
|
106
|
+
try:
|
107
|
+
response = requests.get(
|
108
|
+
f"{self.base_url}/models",
|
109
|
+
headers={"Authorization": f"Bearer {self.api_key}"}
|
110
|
+
)
|
111
|
+
if response.status_code == 200:
|
112
|
+
return [model['id'] for model in response.json()['data']]
|
113
|
+
return []
|
114
|
+
except Exception:
|
115
|
+
return []
|
116
|
+
|
117
|
+
@connection_check
|
118
|
+
def has_model(self, model: str) -> bool:
|
119
|
+
"""Check if model exists"""
|
120
|
+
if not self._is_connected:
|
121
|
+
return False
|
122
|
+
return model in self.list_models()
|
123
|
+
|
124
|
+
client = LLMClient(
|
125
|
+
base_url = cfn.LLM_BASE_URL,
|
126
|
+
api_key = cfn.LLM_API_KEY,
|
127
|
+
model = cfn.LLM_MODEL,
|
128
|
+
)
|
app/rag/llm/services.py
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
from loguru import logger
|
2
|
+
|
3
|
+
import app.rag.config as cfn
|
4
|
+
from .client import client
|
5
|
+
|
6
|
+
def doctor(resolve: bool):
|
7
|
+
# Check connection
|
8
|
+
is_connected = client.check_connection()
|
9
|
+
if not is_connected:
|
10
|
+
logger.error(f"- ❌ FAILED: LLM connection ({cfn.LLM_BASE_URL})")
|
11
|
+
else:
|
12
|
+
logger.info(f"- ✅ PASSED: LLM connection ({cfn.LLM_BASE_URL})")
|
13
|
+
|
14
|
+
# Check model availability
|
15
|
+
try:
|
16
|
+
if not is_connected:
|
17
|
+
logger.warning(f"- ⏭️ SKIPPED: LLM model (Server is not accessible)")
|
18
|
+
else:
|
19
|
+
# List models
|
20
|
+
models = client.list_models()
|
21
|
+
if cfn.LLM_MODEL not in models:
|
22
|
+
logger.error(f"- ❌ FAILED: LLM model not found ({cfn.LLM_MODEL})")
|
23
|
+
else:
|
24
|
+
logger.info(f"- ✅ PASSED: LLM model found (Model `{cfn.LLM_MODEL}` exists)")
|
25
|
+
except Exception as e:
|
26
|
+
logger.error(f"- ❌ FAILED: LLM model check ({str(e)})")
|
app/rag/llm/utilities.py
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
import time
|
2
|
+
from langchain.callbacks.base import BaseCallbackHandler
|
3
|
+
|
4
|
+
class MetricCallbackHandler(BaseCallbackHandler):
|
5
|
+
def __init__(self):
|
6
|
+
self.start_time = time.time()
|
7
|
+
self.ttft = None
|
8
|
+
self.first_token_time = None
|
9
|
+
self.result = ""
|
10
|
+
self.end_time = None
|
11
|
+
self.token_count = 0
|
12
|
+
self.token_timestamps = []
|
13
|
+
|
14
|
+
def on_llm_new_token(self, token: str, **kwargs):
|
15
|
+
current_time = time.time()
|
16
|
+
self.token_count += 1
|
17
|
+
self.token_timestamps.append(current_time)
|
18
|
+
|
19
|
+
if self.ttft is None:
|
20
|
+
self.ttft = current_time - self.start_time
|
21
|
+
self.first_token_time = current_time
|
22
|
+
|
23
|
+
self.result += token
|
24
|
+
|
25
|
+
def on_llm_end(self, *args, **kwargs):
|
26
|
+
self.end_time = time.time()
|
27
|
+
|
28
|
+
def calculate_tokens_per_second(self):
|
29
|
+
"""Calculate tokens per second after the first token"""
|
30
|
+
if self.token_count <= 1 or self.first_token_time is None or self.end_time is None:
|
31
|
+
return 0.0
|
32
|
+
|
33
|
+
# Calculate time from first token to completion (exclude TTFT)
|
34
|
+
generation_time = self.end_time - self.first_token_time
|
35
|
+
if generation_time <= 0:
|
36
|
+
return 0.0
|
37
|
+
|
38
|
+
# Exclude the first token from the count since we're measuring from after it arrived
|
39
|
+
tokens_after_first = self.token_count - 1
|
40
|
+
return tokens_after_first / generation_time
|
app/rag/models.py
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
from pydantic import BaseModel
|
2
|
+
|
3
|
+
class SystemStatusResponse(BaseModel):
|
4
|
+
"""
|
5
|
+
Response model for the system status endpoint.
|
6
|
+
"""
|
7
|
+
status: int
|
8
|
+
message: str
|
9
|
+
|
10
|
+
model_config = {
|
11
|
+
"json_schema_extra": {
|
12
|
+
"examples": [
|
13
|
+
{
|
14
|
+
"status": 200,
|
15
|
+
"message": "System is running normally"
|
16
|
+
}
|
17
|
+
]
|
18
|
+
}
|
19
|
+
}
|
app/rag/routers.py
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
from fastapi import APIRouter
|
2
|
+
|
3
|
+
from .models import SystemStatusResponse
|
4
|
+
|
5
|
+
system_router = APIRouter()
|
6
|
+
|
7
|
+
@system_router.get(
|
8
|
+
path = "/",
|
9
|
+
summary = "Root Endpoint",
|
10
|
+
description = "Root endpoint for the RAG API",
|
11
|
+
response_model = SystemStatusResponse,
|
12
|
+
)
|
13
|
+
async def root():
|
14
|
+
return SystemStatusResponse(
|
15
|
+
status = 200,
|
16
|
+
message = "RAG API is running. If you want to see API documentation, please visit /docs",
|
17
|
+
)
|
18
|
+
|
19
|
+
@system_router.get(
|
20
|
+
path = "/livez",
|
21
|
+
summary = "Liveness Probe",
|
22
|
+
description = "Check if the RAG API is running",
|
23
|
+
response_model = SystemStatusResponse,
|
24
|
+
)
|
25
|
+
async def livez():
|
26
|
+
return SystemStatusResponse(
|
27
|
+
status = 200,
|
28
|
+
message = "RAG API is live",
|
29
|
+
)
|
30
|
+
|
31
|
+
@system_router.get(
|
32
|
+
path = "/readyz",
|
33
|
+
summary = "Readiness Probe",
|
34
|
+
description = "Check if the RAG API is ready to serve requests",
|
35
|
+
response_model = SystemStatusResponse,
|
36
|
+
)
|
37
|
+
async def readyz():
|
38
|
+
return SystemStatusResponse(
|
39
|
+
status = 200,
|
40
|
+
message = "RAG API is ready to serve requests",
|
41
|
+
)
|
app/rag/utilities.py
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
import requests
|
2
|
+
from functools import wraps
|
3
|
+
|
4
|
+
def connection_check(func):
|
5
|
+
"""Check if the server is accessible. `base_url` and `_is_connected` must be provided."""
|
6
|
+
@wraps(func)
|
7
|
+
def wrapper(self, *args, **kwargs):
|
8
|
+
try:
|
9
|
+
requests.head(url=self.base_url, timeout=1)
|
10
|
+
self._is_connected = True
|
11
|
+
return func(self, *args, **kwargs)
|
12
|
+
except requests.exceptions.ConnectionError:
|
13
|
+
self._is_connected = False
|
14
|
+
return []
|
15
|
+
return wrapper
|
app/rag/v1/routers.py
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
import requests
|
2
|
+
from pymilvus import MilvusClient
|
3
|
+
from pymilvus.exceptions import MilvusException
|
4
|
+
|
5
|
+
import app.rag.config as cfn
|
6
|
+
from app.rag.utilities import connection_check
|
7
|
+
|
8
|
+
|
9
|
+
class VectorStoreClient(MilvusClient):
|
10
|
+
def __init__(self, base_url: str, user: str, password: str, database: str, collection: str, metric_type: str):
|
11
|
+
self.base_url = base_url
|
12
|
+
self.user = user
|
13
|
+
self.password = password
|
14
|
+
self.database = database
|
15
|
+
self.collection = collection
|
16
|
+
self.metric_type = metric_type
|
17
|
+
self._is_connected = True
|
18
|
+
self._is_database_exists = True
|
19
|
+
|
20
|
+
if self.check_connection():
|
21
|
+
try:
|
22
|
+
super().__init__(
|
23
|
+
uri = base_url,
|
24
|
+
db_name = database,
|
25
|
+
collection = collection,
|
26
|
+
user = user,
|
27
|
+
password = password,
|
28
|
+
metric_type = metric_type,
|
29
|
+
)
|
30
|
+
except MilvusException as e:
|
31
|
+
if e.code == 800: # database not found
|
32
|
+
self._is_database_exists = False
|
33
|
+
else:
|
34
|
+
raise
|
35
|
+
|
36
|
+
def check_connection(self) -> bool:
|
37
|
+
"""Check if the Milvus server is accessible"""
|
38
|
+
try:
|
39
|
+
requests.head(url=self.base_url, timeout=5)
|
40
|
+
except requests.exceptions.ConnectionError:
|
41
|
+
self._is_connected = False
|
42
|
+
return False
|
43
|
+
except requests.exceptions.ReadTimeout:
|
44
|
+
self._is_connected = False
|
45
|
+
return False
|
46
|
+
self._is_connected = True
|
47
|
+
return True
|
48
|
+
|
49
|
+
@connection_check
|
50
|
+
def get_databases(self) -> list:
|
51
|
+
"""Get list of available databases"""
|
52
|
+
if not self._is_database_exists:
|
53
|
+
return []
|
54
|
+
return self.list_databases()
|
55
|
+
|
56
|
+
@connection_check
|
57
|
+
def get_collections(self) -> list:
|
58
|
+
"""Get list of available collections"""
|
59
|
+
if not self._is_database_exists:
|
60
|
+
return []
|
61
|
+
return self.list_collections()
|
62
|
+
|
63
|
+
@connection_check
|
64
|
+
def has_database(self, database: str) -> bool:
|
65
|
+
"""Check if database exists"""
|
66
|
+
if not self._is_database_exists:
|
67
|
+
return False
|
68
|
+
return database in self.get_databases()
|
69
|
+
|
70
|
+
@connection_check
|
71
|
+
def has_collection(self, collection: str) -> bool:
|
72
|
+
"""Check if collection exists"""
|
73
|
+
if not self._is_database_exists:
|
74
|
+
return False
|
75
|
+
return collection in self.get_collections()
|
76
|
+
|
77
|
+
client = VectorStoreClient(
|
78
|
+
base_url = cfn.MILVUS_BASE_URL,
|
79
|
+
user = cfn.MILVUS_USER,
|
80
|
+
password = cfn.MILVUS_PASSWORD,
|
81
|
+
database = cfn.MILVUS_DATABASE,
|
82
|
+
collection = cfn.MILVUS_COLLECTION,
|
83
|
+
metric_type = cfn.MILVUS_METRIC_TYPE,
|
84
|
+
)
|
@@ -0,0 +1,56 @@
|
|
1
|
+
from loguru import logger
|
2
|
+
|
3
|
+
import app.rag.config as cfn
|
4
|
+
from .client import client
|
5
|
+
|
6
|
+
def doctor(resolve: bool):
|
7
|
+
# Check connection
|
8
|
+
is_connected = client.check_connection()
|
9
|
+
if not is_connected:
|
10
|
+
logger.error(f"- ❌ FAILED: Vector store connection ({cfn.MILVUS_BASE_URL})")
|
11
|
+
else:
|
12
|
+
logger.info(f"- ✅ PASSED: Vector store connection ({cfn.MILVUS_BASE_URL})")
|
13
|
+
|
14
|
+
# Check databases
|
15
|
+
databases = None
|
16
|
+
try:
|
17
|
+
databases = client.get_databases()
|
18
|
+
if not is_connected:
|
19
|
+
logger.warning("- ⏭️ SKIPPED: Vector store databases (Server is not accessible)")
|
20
|
+
else:
|
21
|
+
if not client.has_database(cfn.MILVUS_DATABASE):
|
22
|
+
logger.error(f"- ❌ FAILED: Vector store databases (Database '{cfn.MILVUS_DATABASE}' not found)")
|
23
|
+
if resolve:
|
24
|
+
logger.info(f"- 🔧 Resolving issue: Creating database '{cfn.MILVUS_DATABASE}'")
|
25
|
+
client.create_database(cfn.MILVUS_DATABASE)
|
26
|
+
else:
|
27
|
+
logger.info(f"- ✅ PASSED: Vector store databases (Database '{cfn.MILVUS_DATABASE}' exists)")
|
28
|
+
except Exception as e:
|
29
|
+
logger.error(f"- ❌ FAILED: Database check ({str(e)})")
|
30
|
+
|
31
|
+
# Check collections
|
32
|
+
try:
|
33
|
+
collections = client.get_collections()
|
34
|
+
if not is_connected:
|
35
|
+
logger.warning("- ⏭️ SKIPPED: Vector store collections (Server is not accessible)")
|
36
|
+
elif len(databases) == 0:
|
37
|
+
logger.warning("- ⏭️ SKIPPED: Vector store collections (No database available)")
|
38
|
+
elif len(collections) == 0:
|
39
|
+
logger.error("- ❌ FAILED: Vector store collections (No collections available)")
|
40
|
+
if resolve:
|
41
|
+
logger.info(f"- 🔧 Resolving issue: Creating collection '{cfn.MILVUS_COLLECTION}'")
|
42
|
+
client.create_collection(cfn.MILVUS_COLLECTION)
|
43
|
+
else:
|
44
|
+
if not client.has_collection(cfn.MILVUS_COLLECTION):
|
45
|
+
logger.error(f"- ❌ FAILED: Vector store collections (Collection '{cfn.MILVUS_COLLECTION}' not found)")
|
46
|
+
if resolve:
|
47
|
+
logger.info(f"- 🔧 Resolving issue: Creating collection '{cfn.MILVUS_COLLECTION}'")
|
48
|
+
client.create_collection(
|
49
|
+
collection_name = cfn.MILVUS_COLLECTION,
|
50
|
+
dimension = cfn.EMBEDDING_DIMENSION,
|
51
|
+
metric_type = cfn.MILVUS_METRIC_TYPE
|
52
|
+
)
|
53
|
+
else:
|
54
|
+
logger.info(f"- ✅ PASSED: Vector store collections (Collection '{cfn.MILVUS_COLLECTION}' exists)")
|
55
|
+
except Exception as e:
|
56
|
+
logger.error(f"- ❌ FAILED: Collection check ({str(e)})")
|
app/requirements.txt
CHANGED
@@ -1,11 +1,12 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# App
|
2
|
+
dynaconf < 3.3
|
3
3
|
loguru < 0.8
|
4
|
-
|
5
|
-
# Development
|
6
4
|
pytest < 8.4
|
7
|
-
|
5
|
+
fastapi < 0.116
|
6
|
+
uvicorn < 0.35
|
8
7
|
|
9
8
|
# RAG
|
10
9
|
ragas < 0.3
|
11
10
|
pymilvus < 2.6
|
11
|
+
langchain-openai < 0.4
|
12
|
+
langchain-ollama < 0.4
|
app/setup.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
+
import os, tomli
|
1
2
|
from setuptools import setup, find_packages
|
2
|
-
import os, sys
|
3
|
-
import tomli
|
4
3
|
|
5
4
|
# Load requirements
|
6
5
|
with open(os.path.join(os.path.dirname(__file__), 'requirements.txt'), 'r') as f:
|
@@ -21,7 +20,7 @@ setup(
|
|
21
20
|
install_requires = requirements,
|
22
21
|
entry_points = {
|
23
22
|
"console_scripts": [
|
24
|
-
f"{APP_NAME}=
|
23
|
+
f"{APP_NAME}=app.cli:main",
|
25
24
|
],
|
26
25
|
},
|
27
26
|
)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: pirag
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.2.2
|
4
4
|
Summary: CLI Projects of On-Premise RAG. You can use your own LLM and vector DB. Or just add remote LLM servers and vector DB.
|
5
5
|
Author-email: semir4in <semir4in@gmail.com>, jyje <jyjeon@outlook.com>
|
6
6
|
Project-URL: Homepage, https://github.com/jyje/pilot-onpremise-rag
|
@@ -9,12 +9,15 @@ Project-URL: Issue, https://github.com/jyje/pilot-onpremise-rag/issues
|
|
9
9
|
Requires-Python: >=3.9
|
10
10
|
Description-Content-Type: text/markdown
|
11
11
|
License-File: LICENSE
|
12
|
-
Requires-Dist:
|
12
|
+
Requires-Dist: dynaconf<3.3
|
13
13
|
Requires-Dist: loguru<0.8
|
14
14
|
Requires-Dist: pytest<8.4
|
15
|
-
Requires-Dist:
|
15
|
+
Requires-Dist: fastapi<0.116
|
16
|
+
Requires-Dist: uvicorn<0.35
|
16
17
|
Requires-Dist: ragas<0.3
|
17
18
|
Requires-Dist: pymilvus<2.6
|
19
|
+
Requires-Dist: langchain-openai<0.4
|
20
|
+
Requires-Dist: langchain-ollama<0.4
|
18
21
|
Dynamic: license-file
|
19
22
|
|
20
23
|
<div align="center">
|
@@ -0,0 +1,27 @@
|
|
1
|
+
app/main.py,sha256=H2M3jzG61MvEszebTdvrQc2PyHiKTwVoLFJo_W-T50s,2335
|
2
|
+
app/requirements.txt,sha256=SvJdCesmBDu3w8ANXuFkHUf08NsxIlI3PMmDCuPrUps,158
|
3
|
+
app/setup.py,sha256=nwUhqn3SLcm6L-WN0saHFisF-K9BpMR3qktszjBJcA4,736
|
4
|
+
app/rag/api.py,sha256=IdM296NbcyF4yzLRpTnsAiPRMntHBlTYJwW7rx-18qo,1077
|
5
|
+
app/rag/cli.py,sha256=IgzViBkIMIkdwYk4F3nrp-wMpBciza_yod6rt98HBZA,1703
|
6
|
+
app/rag/config.py,sha256=qenCAkJdgMWEMODuWWhtx6wJzsxDW7yUcY6nz37G33Q,4938
|
7
|
+
app/rag/models.py,sha256=VwkNFwzzTKeGUEkx4MPJR0Y2y1uaIMu37ja58Za70GY,415
|
8
|
+
app/rag/routers.py,sha256=Jv1rAmIl6-sRy5YLvEbRF2kpME_XYVC5Gm3Lxb6NAvw,1058
|
9
|
+
app/rag/utilities.py,sha256=AyKNakKmbNcAhjGUj9h2UUQGQV0A4759mJpTlCvMrCY,510
|
10
|
+
app/rag/agent/services.py,sha256=xi38u5cL1t5doVMnfOLIOb1aux1XCkqBf3yhKzQZBaw,199
|
11
|
+
app/rag/embedding/client.py,sha256=RKNKc1Tt0c_uLfNsd4ZWsBrEYmFEy59Xdromn-gKcg4,2163
|
12
|
+
app/rag/embedding/services.py,sha256=6LbbU5RetvO5DuB2AyLMw0r7Lnsi5u_mEoRusqDZu_E,1007
|
13
|
+
app/rag/llm/client.py,sha256=FdvbSq-_PMjYp3nD9iNzLiWnylFg8Zuc5cPnaPMLO-c,4231
|
14
|
+
app/rag/llm/services.py,sha256=5fQ_KdHpgt5PdHXQO54EnUSeQvyVtteXtRFbPb1Smwg,941
|
15
|
+
app/rag/llm/utilities.py,sha256=xLMxdwetxAetJP23uqygjy0zt_mCot4ToEZDl6zkGrA,1437
|
16
|
+
app/rag/test/client.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
17
|
+
app/rag/train/client.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
|
+
app/rag/v1/routers.py,sha256=mE-c-c_vNVN_V7M0-Z8OSGlzWTOa419sfxSV35Qs7DU,133
|
19
|
+
app/rag/v1/services.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
20
|
+
app/rag/vector_store/client.py,sha256=aj7xPOIua0c0Z_ZuVJ52NNQtrEpdbzyTxAM7-oNE2qM,2729
|
21
|
+
app/rag/vector_store/services.py,sha256=oslu4Yzubd7MYVhVEHDIV1pBh18VsrbvmW_1_5sMn-8,2705
|
22
|
+
pirag-0.2.2.dist-info/licenses/LICENSE,sha256=gBUmwRyDQYI4Q4Ju5S88urvB-B-nqsXN45n8oQ3DZ3Y,1079
|
23
|
+
pirag-0.2.2.dist-info/METADATA,sha256=VlARBEA9P4ZmyoEjVd2NXjHBTPWO0SuDI9hSZMjTf-o,5635
|
24
|
+
pirag-0.2.2.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
25
|
+
pirag-0.2.2.dist-info/entry_points.txt,sha256=1tHs5rP66AVq5SMEWRRIWRf_XqJo2Gb1TJl9-Kw_MSo,40
|
26
|
+
pirag-0.2.2.dist-info/top_level.txt,sha256=io9g7LCbfmTG1SFKgEOGXmCFB9uMP2H5lerm0HiHWQE,4
|
27
|
+
pirag-0.2.2.dist-info/RECORD,,
|
app/rag/agent.py
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
from langchain_openai.llms import OpenAI
|
2
|
-
from langchain_openai.embeddings import OpenAIEmbeddings
|
3
|
-
from pymilvus import MilvusClient
|
4
|
-
|
5
|
-
class Agent():
|
6
|
-
def __init__(
|
7
|
-
self,
|
8
|
-
llm_base_url: str,
|
9
|
-
llm_api_key: str,
|
10
|
-
llm_model: str,
|
11
|
-
embedding_base_url: str,
|
12
|
-
embedding_api_key: str,
|
13
|
-
embedding_model: str,
|
14
|
-
milvus_host: str,
|
15
|
-
milvus_database: str,
|
16
|
-
milvus_collection: str,
|
17
|
-
):
|
18
|
-
self.llm_base_url = llm_base_url
|
19
|
-
self.llm_api_key = llm_api_key
|
20
|
-
self.llm_model = llm_model
|
21
|
-
self.embedding_base_url = embedding_base_url
|
22
|
-
self.embedding_api_key = embedding_api_key
|
23
|
-
self.embedding_model = embedding_model
|
24
|
-
self.milvus_host = milvus_host
|
25
|
-
self.milvus_database = milvus_database
|
26
|
-
self.milvus_collection = milvus_collection
|
27
|
-
|
28
|
-
self._llm_client: OpenAI = None
|
29
|
-
self._embedding_client: OpenAIEmbeddings = None
|
30
|
-
self._milvus_client: MilvusClient = None
|
31
|
-
|
32
|
-
def retrieve_knowledge_base(self, query: str) -> str:
|
33
|
-
llm_client = self._get_llm_client()
|
34
|
-
embedding_client = self._get_embedding_client()
|
35
|
-
milvus_client = self._get_milvus_client()
|
36
|
-
|
37
|
-
|
38
|
-
def _get_llm_client(self) -> OpenAI:
|
39
|
-
if self._llm_client is None:
|
40
|
-
self._llm_client = OpenAI(
|
41
|
-
base_url=self.llm_base_url,
|
42
|
-
api_key=self.llm_api_key,
|
43
|
-
model=self.llm_model,
|
44
|
-
)
|
45
|
-
return self._llm_client
|
46
|
-
|
47
|
-
|
48
|
-
def _get_embedding_client(self) -> OpenAIEmbeddings:
|
49
|
-
if self._embedding_client is None:
|
50
|
-
self._embedding_client = OpenAIEmbeddings(
|
51
|
-
base_url=self.embedding_base_url,
|
52
|
-
api_key=self.embedding_api_key,
|
53
|
-
model=self.embedding_model,
|
54
|
-
)
|
55
|
-
return self._embedding_client
|
56
|
-
|
57
|
-
def _get_milvus_client(self) -> MilvusClient:
|
58
|
-
if self._milvus_client is None:
|
59
|
-
self._milvus_client = MilvusClient(
|
60
|
-
host=self.milvus_host,
|
61
|
-
database=self.milvus_database,
|
62
|
-
collection=self.milvus_collection,
|
63
|
-
)
|
64
|
-
return self._milvus_client
|
app/rag/ask/__init__.py
DELETED
app/rag/ask/config.py
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
import argparse
|
2
|
-
|
3
|
-
help = "Ask a question to the RAG system."
|
4
|
-
|
5
|
-
parser = argparse.ArgumentParser(
|
6
|
-
description = f"{help} Queries the knowledge base with natural language questions, retrieves relevant context, and generates accurate, contextually-aware responses based on the retrieved information",
|
7
|
-
add_help = False,
|
8
|
-
formatter_class = argparse.ArgumentDefaultsHelpFormatter,
|
9
|
-
)
|
app/rag/ask/router.py
DELETED
app/rag/doctor/__init__.py
DELETED
app/rag/doctor/config.py
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
import argparse
|
2
|
-
|
3
|
-
from app.rag.config import top_parser, common_parser
|
4
|
-
|
5
|
-
help = "Diagnose the RAG system."
|
6
|
-
|
7
|
-
parser = argparse.ArgumentParser(
|
8
|
-
description = f"{help} Performs comprehensive health checks on all components, validates configurations, and reports issues to ensure optimal system operation",
|
9
|
-
add_help = False,
|
10
|
-
formatter_class = argparse.ArgumentDefaultsHelpFormatter,
|
11
|
-
)
|
12
|
-
|
13
|
-
subparsers = parser.add_subparsers(
|
14
|
-
title = "subcommands",
|
15
|
-
dest = "subcommand",
|
16
|
-
)
|
17
|
-
|
18
|
-
subparsers.add_parser(
|
19
|
-
"check",
|
20
|
-
help = "Check RAG System. Scan all components of the system and diagnose status",
|
21
|
-
description = "Check RAG System. Scan all components of the system and diagnose status",
|
22
|
-
parents = [top_parser, common_parser],
|
23
|
-
add_help = False,
|
24
|
-
)
|
app/rag/doctor/router.py
DELETED
app/rag/test/__init__.py
DELETED
app/rag/test/config.py
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
import argparse
|
2
|
-
|
3
|
-
help = "Test the RAG system."
|
4
|
-
|
5
|
-
parser = argparse.ArgumentParser(
|
6
|
-
description = f"{help} Evaluates system performance by running predefined test cases, measuring accuracy, relevance, and latency metrics to validate retrieval and generation capabilities",
|
7
|
-
add_help = False,
|
8
|
-
formatter_class = argparse.ArgumentDefaultsHelpFormatter,
|
9
|
-
)
|
app/rag/test/router.py
DELETED
app/rag/train/__init__.py
DELETED