Skip to content

Commit 9f5cccc

Browse files
authored
feat: added basics for upload (#1741)
1 parent 57c6cbf commit 9f5cccc

File tree

8 files changed

+124
-29
lines changed

8 files changed

+124
-29
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,4 +168,6 @@ cython_debug/
168168
experiments/
169169
**/fil-result/
170170
src/ragas/_version.py
171-
.vscode
171+
.vscode
172+
.envrc
173+
uv.lock

pyproject.toml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
[project]
22
name = "ragas"
3+
requires-python = ">=3.9"
34
dependencies = [
45
"numpy",
56
"datasets",
@@ -40,6 +41,32 @@ docs = [
4041
"mkdocs-git-committers-plugin-2",
4142
"mkdocs-git-revision-date-localized-plugin",
4243
]
44+
dev = [
45+
"rich",
46+
"ruff",
47+
"isort",
48+
"black[jupyter]",
49+
"pyright",
50+
"llama_index",
51+
"notebook",
52+
"sphinx-autobuild",
53+
"sentence-transformers",
54+
"transformers",
55+
"fastembed",
56+
"graphene",
57+
"rouge_score",
58+
"nltk",
59+
"rapidfuzz",
60+
"pandas",
61+
"datacompy",
62+
]
63+
test = [
64+
"pytest",
65+
"pytest-xdist[psutil]",
66+
"pytest-asyncio",
67+
"llama_index",
68+
"nbmake",
69+
]
4370
[tool.setuptools]
4471
package-dir = {"" = "src"}
4572

src/ragas/dataset_schema.py

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414

1515
from ragas.callbacks import ChainRunEncoder, parse_run_traces
1616
from ragas.cost import CostCallbackHandler
17+
from ragas.exceptions import UploadException
1718
from ragas.messages import AIMessage, HumanMessage, ToolCall, ToolMessage
18-
from ragas.utils import RAGAS_API_URL, safe_nanmean
19+
from ragas.sdk import RAGAS_API_URL, RAGAS_APP_URL, upload_packet
20+
from ragas.utils import safe_nanmean
1921

2022
if t.TYPE_CHECKING:
2123
from pathlib import Path
@@ -509,8 +511,6 @@ def total_cost(
509511
def upload(self, base_url: str = RAGAS_API_URL, verbose: bool = True) -> str:
510512
from datetime import datetime, timezone
511513

512-
import requests
513-
514514
timestamp = datetime.now(timezone.utc).isoformat()
515515
root_trace = [
516516
trace for trace in self.ragas_traces.values() if trace.parent_run_id is None
@@ -523,19 +523,28 @@ def upload(self, base_url: str = RAGAS_API_URL, verbose: bool = True) -> str:
523523
},
524524
cls=ChainRunEncoder,
525525
)
526-
527-
response = requests.post(
528-
f"{base_url}/alignment/evaluation",
529-
data=packet,
530-
headers={"Content-Type": "application/json"},
526+
response = upload_packet(
527+
path="/alignment/evaluation",
528+
data_json_string=packet,
529+
base_url=base_url,
531530
)
532531

533-
if response.status_code != 200:
534-
raise Exception(f"Failed to upload results: {response.text}")
535-
532+
# check status codes
536533
evaluation_endpoint = (
537-
f"https://app.ragas.io/alignment/evaluation/{root_trace.run_id}"
534+
f"{RAGAS_APP_URL}/alignment/evaluation/{root_trace.run_id}"
538535
)
536+
if response.status_code == 409:
537+
# this evalution already exists
538+
if verbose:
539+
print(f"Evaluation run already exists. View at {evaluation_endpoint}")
540+
return evaluation_endpoint
541+
elif response.status_code != 200:
542+
# any other error
543+
raise UploadException(
544+
status_code=response.status_code,
545+
message=f"Failed to upload results: {response.text}",
546+
)
547+
539548
if verbose:
540549
print(f"Evaluation results uploaded! View at {evaluation_endpoint}")
541550
return evaluation_endpoint
@@ -563,15 +572,13 @@ def __getitem__(self, key):
563572

564573

565574
class MetricAnnotation(BaseModel):
566-
567575
root: t.Dict[str, t.List[SampleAnnotation]]
568576

569577
def __getitem__(self, key):
570578
return SingleMetricAnnotation(name=key, samples=self.root[key])
571579

572580
@classmethod
573581
def from_json(cls, path, metric_name: t.Optional[str]) -> "MetricAnnotation":
574-
575582
dataset = json.load(open(path))
576583
if metric_name is not None and metric_name not in dataset:
577584
raise ValueError(f"Split {metric_name} not found in the dataset.")
@@ -613,7 +620,6 @@ def select(self, indices: t.List[int]) -> "SingleMetricAnnotation":
613620

614621
@classmethod
615622
def from_json(cls, path) -> "SingleMetricAnnotation":
616-
617623
dataset = json.load(open(path))
618624

619625
return cls(
@@ -622,7 +628,6 @@ def from_json(cls, path) -> "SingleMetricAnnotation":
622628
)
623629

624630
def filter(self, function: t.Optional[t.Callable] = None):
625-
626631
if function is None:
627632
function = lambda x: True # noqa: E731
628633

src/ragas/exceptions.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,13 @@ class LLMDidNotFinishException(RagasException):
3939
def __init__(self):
4040
msg = "The LLM generation was not completed. Please increase try increasing the max_tokens and try again."
4141
super().__init__(msg)
42+
43+
44+
class UploadException(RagasException):
45+
"""
46+
Exception raised when the app fails to upload the results.
47+
"""
48+
49+
def __init__(self, status_code: int, message: str):
50+
self.status_code = status_code
51+
super().__init__(message)

src/ragas/executor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
import typing as t
66
from dataclasses import dataclass, field
77

8+
import nest_asyncio
89
import numpy as np
910
from tqdm.auto import tqdm
1011

1112
from ragas.run_config import RunConfig
1213
from ragas.utils import batched
1314

14-
import nest_asyncio
1515
nest_asyncio.apply()
1616

1717
logger = logging.getLogger(__name__)

src/ragas/sdk.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
"""
2+
SDK module for interacting with the Ragas API service.
3+
"""
4+
5+
import os
6+
from functools import lru_cache
7+
8+
import requests
9+
10+
from ragas._version import __version__
11+
from ragas.exceptions import UploadException
12+
13+
# endpoint for uploading results
14+
RAGAS_API_URL = "https://api.ragas.io"
15+
RAGAS_APP_URL = "https://app.ragas.io"
16+
RAGAS_API_SOURCE = "ragas_py"
17+
18+
19+
@lru_cache(maxsize=1)
20+
def get_app_token() -> str:
21+
app_token = os.environ.get("RAGAS_APP_TOKEN")
22+
if app_token is None:
23+
raise ValueError("RAGAS_APP_TOKEN is not set")
24+
return app_token
25+
26+
27+
def upload_packet(path: str, data_json_string: str, base_url: str = RAGAS_API_URL):
28+
app_token = get_app_token()
29+
response = requests.post(
30+
f"{base_url}/api/v1{path}",
31+
data=data_json_string,
32+
headers={
33+
"Content-Type": "application/json",
34+
"x-app-token": app_token,
35+
"x-source": RAGAS_API_SOURCE,
36+
"x-app-version": __version__,
37+
},
38+
)
39+
if response.status_code == 403:
40+
raise UploadException(
41+
status_code=response.status_code,
42+
message="AUTHENTICATION_ERROR: The app token is invalid. Please check your RAGAS_APP_TOKEN environment variable.",
43+
)
44+
return response

src/ragas/testset/synthesizers/testset_schema.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
RagasDataset,
1616
SingleTurnSample,
1717
)
18-
from ragas.utils import RAGAS_API_URL
18+
from ragas.exceptions import UploadException
19+
from ragas.sdk import RAGAS_API_URL, RAGAS_APP_URL, upload_packet
1920

2021

2122
class TestsetSample(BaseSample):
@@ -136,16 +137,24 @@ def total_cost(
136137
)
137138

138139
def upload(self, base_url: str = RAGAS_API_URL, verbose: bool = True) -> str:
139-
import requests
140-
141140
packet = TestsetPacket(samples_original=self.samples, run_id=self.run_id)
142-
response = requests.post(
143-
f"{base_url}/alignment/testset", json=packet.model_dump()
141+
response = upload_packet(
142+
path="/alignment/testset",
143+
data_json_string=packet.model_dump_json(),
144+
base_url=base_url,
144145
)
145-
if response.status_code != 200:
146-
raise Exception(f"Failed to upload results: {response.text}")
147-
148-
testset_endpoint = f"https://app.ragas.io/alignment/testset/{packet.run_id}"
146+
testset_endpoint = f"{RAGAS_APP_URL}/alignment/testset/{self.run_id}"
147+
if response.status_code == 409:
148+
# this testset already exists
149+
if verbose:
150+
print(f"Testset already exists. View at {testset_endpoint}")
151+
return testset_endpoint
152+
elif response.status_code != 200:
153+
# any other error
154+
raise UploadException(
155+
status_code=response.status_code,
156+
message=f"Failed to upload results: {response.text}",
157+
)
149158
if verbose:
150159
print(f"Testset uploaded! View at {testset_endpoint}")
151160
return testset_endpoint

src/ragas/utils.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
RAGAS_SUPPORTED_LANGUAGE_CODES = {
2121
v.__name__.lower(): k for k, v in LANGUAGE_CODES.items()
2222
}
23-
# endpoint for uploading results
24-
RAGAS_API_URL = "https://api.ragas.io"
2523

2624

2725
@lru_cache(maxsize=1)

0 commit comments

Comments
 (0)