ragas-examples 0.3.5__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.
- ragas_examples/__init__.py +17 -0
- ragas_examples/_version.py +34 -0
- ragas_examples/agent_evals/__init__.py +0 -0
- ragas_examples/agent_evals/agent.py +409 -0
- ragas_examples/agent_evals/evals.py +78 -0
- ragas_examples/benchmark_llm/__init__.py +0 -0
- ragas_examples/benchmark_llm/datasets/discount_benchmark.csv +11 -0
- ragas_examples/benchmark_llm/evals.py +274 -0
- ragas_examples/benchmark_llm/prompt.py +71 -0
- ragas_examples/prompt_evals/__init__.py +0 -0
- ragas_examples/prompt_evals/evals.py +75 -0
- ragas_examples/prompt_evals/prompt.py +32 -0
- ragas_examples/rag_eval/__init__.py +0 -0
- ragas_examples/rag_eval/evals.py +84 -0
- ragas_examples/rag_eval/rag.py +481 -0
- ragas_examples/text2sql/__init__.py +36 -0
- ragas_examples/text2sql/analyze_errors.py +198 -0
- ragas_examples/text2sql/data_utils.py +380 -0
- ragas_examples/text2sql/datasets/booksql_sample.csv +100 -0
- ragas_examples/text2sql/db_utils.py +458 -0
- ragas_examples/text2sql/evals.py +387 -0
- ragas_examples/text2sql/prompt.txt +111 -0
- ragas_examples/text2sql/prompt_v2.txt +135 -0
- ragas_examples/text2sql/prompt_v3.txt +144 -0
- ragas_examples/text2sql/text2sql_agent.py +522 -0
- ragas_examples/text2sql/validate_sql_dataset.py +317 -0
- ragas_examples/workflow_eval/__init__.py +0 -0
- ragas_examples/workflow_eval/evals.py +107 -0
- ragas_examples/workflow_eval/workflow.py +670 -0
- ragas_examples-0.3.5.dist-info/METADATA +130 -0
- ragas_examples-0.3.5.dist-info/RECORD +34 -0
- ragas_examples-0.3.5.dist-info/WHEEL +5 -0
- ragas_examples-0.3.5.dist-info/licenses/LICENSE +201 -0
- ragas_examples-0.3.5.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import asyncio
|
|
3
|
+
import datetime
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
from typing import List, Optional
|
|
8
|
+
|
|
9
|
+
import pandas as pd
|
|
10
|
+
|
|
11
|
+
from ragas import experiment
|
|
12
|
+
from ragas.dataset import Dataset
|
|
13
|
+
from ragas.metrics.discrete import discrete_metric
|
|
14
|
+
from ragas.metrics.result import MetricResult
|
|
15
|
+
|
|
16
|
+
from .prompt import DEFAULT_MODEL, run_prompt
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@discrete_metric(name="discount_accuracy", allowed_values=["correct", "incorrect"])
|
|
20
|
+
def discount_accuracy(prediction: str, expected_discount):
|
|
21
|
+
"""Check if the discount prediction is correct."""
|
|
22
|
+
parsed_json = json.loads(prediction)
|
|
23
|
+
predicted_discount = parsed_json.get("discount_percentage")
|
|
24
|
+
expected_discount_int = int(expected_discount)
|
|
25
|
+
|
|
26
|
+
if predicted_discount == expected_discount_int:
|
|
27
|
+
return MetricResult(
|
|
28
|
+
value="correct",
|
|
29
|
+
reason=f"Correctly calculated discount={expected_discount_int}%",
|
|
30
|
+
)
|
|
31
|
+
else:
|
|
32
|
+
return MetricResult(
|
|
33
|
+
value="incorrect",
|
|
34
|
+
reason=f"Expected discount={expected_discount_int}%; Got discount={predicted_discount}%",
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def create_benchmark_experiment(model_name: str, experiment_name: str):
|
|
39
|
+
"""Factory function to create experiment functions for different models."""
|
|
40
|
+
|
|
41
|
+
@experiment()
|
|
42
|
+
async def benchmark_experiment(row):
|
|
43
|
+
# Get model response (run blocking call in thread to keep async runner responsive)
|
|
44
|
+
response = await asyncio.to_thread(
|
|
45
|
+
run_prompt, row["customer_profile"], model=model_name
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
# Parse response (strict JSON mode expected)
|
|
49
|
+
try:
|
|
50
|
+
parsed_json = json.loads(response)
|
|
51
|
+
predicted_discount = parsed_json.get("discount_percentage")
|
|
52
|
+
except Exception:
|
|
53
|
+
predicted_discount = None
|
|
54
|
+
|
|
55
|
+
# Score the response
|
|
56
|
+
score = discount_accuracy.score(
|
|
57
|
+
prediction=response, expected_discount=row["expected_discount"]
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
**row,
|
|
62
|
+
"model": model_name,
|
|
63
|
+
"experiment_name": experiment_name,
|
|
64
|
+
"response": response,
|
|
65
|
+
"predicted_discount": predicted_discount,
|
|
66
|
+
"score": score.value,
|
|
67
|
+
"score_reason": score.reason,
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return benchmark_experiment
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def load_dataset():
|
|
74
|
+
"""Load the dataset from CSV file."""
|
|
75
|
+
# Get the directory where this file is located
|
|
76
|
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
77
|
+
|
|
78
|
+
dataset = Dataset.load(
|
|
79
|
+
name="discount_benchmark", backend="local/csv", root_dir=current_dir
|
|
80
|
+
)
|
|
81
|
+
return dataset
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def compare_inputs_to_output(
|
|
85
|
+
inputs: List[str], output_path: Optional[str] = None
|
|
86
|
+
) -> str:
|
|
87
|
+
"""Compare multiple experiment CSVs and write a combined CSV.
|
|
88
|
+
|
|
89
|
+
- Requires 'id' column in all inputs; uses it as the alignment key
|
|
90
|
+
- Builds output with id + canonical columns + per-experiment response/score/reason columns
|
|
91
|
+
- Returns the full output path
|
|
92
|
+
"""
|
|
93
|
+
if not inputs or len(inputs) < 2:
|
|
94
|
+
raise ValueError("At least two input CSV files are required for comparison")
|
|
95
|
+
|
|
96
|
+
# Load all inputs
|
|
97
|
+
dataframes = []
|
|
98
|
+
experiment_names = []
|
|
99
|
+
for path in inputs:
|
|
100
|
+
df = pd.read_csv(path)
|
|
101
|
+
if "experiment_name" not in df.columns:
|
|
102
|
+
raise ValueError(f"Missing 'experiment_name' column in {path}")
|
|
103
|
+
exp_name = str(df["experiment_name"].iloc[0])
|
|
104
|
+
experiment_names.append(exp_name)
|
|
105
|
+
dataframes.append(df)
|
|
106
|
+
|
|
107
|
+
canonical_cols = ["customer_profile", "description", "expected_discount"]
|
|
108
|
+
base_df = dataframes[0]
|
|
109
|
+
|
|
110
|
+
# Require 'id' in all inputs
|
|
111
|
+
if not all("id" in df.columns for df in dataframes):
|
|
112
|
+
raise ValueError(
|
|
113
|
+
"All input CSVs must contain an 'id' column to align rows. Re-run experiments after adding 'id' to your dataset."
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# Validate duplicates and matching sets of IDs
|
|
117
|
+
key_sets = []
|
|
118
|
+
for idx, df in enumerate(dataframes):
|
|
119
|
+
keys = df["id"].astype(str)
|
|
120
|
+
if keys.duplicated().any():
|
|
121
|
+
dupes = keys[keys.duplicated()].head(3).tolist()
|
|
122
|
+
raise ValueError(
|
|
123
|
+
f"Input {inputs[idx]} contains duplicate id values. Examples: {dupes}"
|
|
124
|
+
)
|
|
125
|
+
key_sets.append(set(keys.tolist()))
|
|
126
|
+
|
|
127
|
+
base_keys = key_sets[0]
|
|
128
|
+
for i, ks in enumerate(key_sets[1:], start=1):
|
|
129
|
+
if ks != base_keys:
|
|
130
|
+
missing_in_other = list(base_keys - ks)[:5]
|
|
131
|
+
missing_in_base = list(ks - base_keys)[:5]
|
|
132
|
+
raise ValueError(
|
|
133
|
+
"Inputs do not contain the same set of IDs.\n"
|
|
134
|
+
f"- Missing in file {i + 1}: {missing_in_other}\n"
|
|
135
|
+
f"- Extra in file {i + 1}: {missing_in_base}"
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
# Validate canonical columns exist in base
|
|
139
|
+
missing = [c for c in canonical_cols if c not in base_df.columns]
|
|
140
|
+
if missing:
|
|
141
|
+
raise ValueError(f"First CSV missing required columns: {missing}")
|
|
142
|
+
|
|
143
|
+
# Build combined on base order using 'id' as alignment key
|
|
144
|
+
base_ids_str = base_df["id"].astype(str)
|
|
145
|
+
combined = base_df[["id"] + canonical_cols].copy()
|
|
146
|
+
|
|
147
|
+
# Append per-experiment outputs by aligned ID
|
|
148
|
+
for df, exp_name in zip(dataframes, experiment_names):
|
|
149
|
+
df = df.copy()
|
|
150
|
+
df["id"] = df["id"].astype(str)
|
|
151
|
+
df = df.set_index("id")
|
|
152
|
+
for col in ["response", "score", "score_reason"]:
|
|
153
|
+
if col not in df.columns:
|
|
154
|
+
raise ValueError(
|
|
155
|
+
f"Column '{col}' not found in one input. Please provide per-row '{col}'."
|
|
156
|
+
)
|
|
157
|
+
combined[f"{exp_name}_response"] = base_ids_str.map(df["response"])
|
|
158
|
+
combined[f"{exp_name}_score"] = base_ids_str.map(df["score"])
|
|
159
|
+
combined[f"{exp_name}_score_reason"] = base_ids_str.map(df["score_reason"])
|
|
160
|
+
|
|
161
|
+
# Determine output path
|
|
162
|
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
163
|
+
experiments_dir = os.path.join(current_dir, "experiments")
|
|
164
|
+
os.makedirs(experiments_dir, exist_ok=True)
|
|
165
|
+
|
|
166
|
+
if output_path is None or output_path.strip() == "":
|
|
167
|
+
run_id = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
|
|
168
|
+
output_path = os.path.join(experiments_dir, f"{run_id}-comparison.csv")
|
|
169
|
+
else:
|
|
170
|
+
# If relative path, place under experiments dir
|
|
171
|
+
if not os.path.isabs(output_path):
|
|
172
|
+
output_path = os.path.join(experiments_dir, output_path)
|
|
173
|
+
|
|
174
|
+
# Sort by id for user-friendly reading
|
|
175
|
+
if "id" in combined.columns:
|
|
176
|
+
combined = combined.sort_values(by="id").reset_index(drop=True)
|
|
177
|
+
combined.to_csv(output_path, index=False)
|
|
178
|
+
|
|
179
|
+
# Print per-experiment accuracy summary
|
|
180
|
+
for df, exp_name in zip(dataframes, experiment_names):
|
|
181
|
+
try:
|
|
182
|
+
acc = (df["score"] == "correct").mean()
|
|
183
|
+
print(f"{exp_name} Accuracy: {acc:.2%}")
|
|
184
|
+
except Exception:
|
|
185
|
+
pass
|
|
186
|
+
|
|
187
|
+
return output_path
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
async def run_command(model: str, name: Optional[str]) -> None:
|
|
191
|
+
"""Run a single experiment using the provided model and name."""
|
|
192
|
+
if "OPENAI_API_KEY" not in os.environ:
|
|
193
|
+
print("❌ Error: OpenAI API key not found!")
|
|
194
|
+
print("Please set your API key: export OPENAI_API_KEY=your_actual_key")
|
|
195
|
+
return
|
|
196
|
+
|
|
197
|
+
print("Loading dataset...")
|
|
198
|
+
dataset = load_dataset()
|
|
199
|
+
print(f"Dataset loaded with {len(dataset)} samples")
|
|
200
|
+
|
|
201
|
+
run_id = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
|
|
202
|
+
exp_name = name or model
|
|
203
|
+
|
|
204
|
+
# Ensure output directory exists (experiment framework saves under experiments/)
|
|
205
|
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
206
|
+
experiments_dir = os.path.join(current_dir, "experiments")
|
|
207
|
+
os.makedirs(experiments_dir, exist_ok=True)
|
|
208
|
+
|
|
209
|
+
benchmark_experiment = create_benchmark_experiment(
|
|
210
|
+
model_name=model, experiment_name=exp_name
|
|
211
|
+
)
|
|
212
|
+
print(f"Running model evaluation ({model})...")
|
|
213
|
+
results = await benchmark_experiment.arun(dataset, name=f"{run_id}-{exp_name}")
|
|
214
|
+
print(f"✅ {exp_name}: {len(results)} cases evaluated")
|
|
215
|
+
print(f"Results saved to: {os.path.join(experiments_dir, results.name)}.csv")
|
|
216
|
+
|
|
217
|
+
# Accuracy summary
|
|
218
|
+
accuracy = sum(1 for r in results if r["score"] == "correct") / max(1, len(results))
|
|
219
|
+
print(f"{exp_name} Accuracy: {accuracy:.2%}")
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def compare_command(inputs: List[str], output: Optional[str]) -> None:
|
|
223
|
+
output_path = compare_inputs_to_output(inputs, output)
|
|
224
|
+
print(f"Combined comparison saved to: {output_path}")
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
228
|
+
parser = argparse.ArgumentParser(description="Benchmark LLM evaluation CLI")
|
|
229
|
+
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
230
|
+
|
|
231
|
+
# run subcommand
|
|
232
|
+
run_parser = subparsers.add_parser("run", help="Run a single experiment")
|
|
233
|
+
run_parser.add_argument(
|
|
234
|
+
"--model", type=str, default=DEFAULT_MODEL, help="Model name to evaluate"
|
|
235
|
+
)
|
|
236
|
+
run_parser.add_argument(
|
|
237
|
+
"--name",
|
|
238
|
+
type=str,
|
|
239
|
+
default=None,
|
|
240
|
+
help="Experiment name (defaults to model name)",
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
# compare subcommand
|
|
244
|
+
cmp_parser = subparsers.add_parser(
|
|
245
|
+
"compare", help="Combine multiple experiment CSVs"
|
|
246
|
+
)
|
|
247
|
+
cmp_parser.add_argument(
|
|
248
|
+
"--inputs", nargs="+", required=True, help="Input CSV files to compare"
|
|
249
|
+
)
|
|
250
|
+
cmp_parser.add_argument(
|
|
251
|
+
"--output",
|
|
252
|
+
type=str,
|
|
253
|
+
default=None,
|
|
254
|
+
help="Output CSV path (defaults to experiments/<timestamp>-comparison.csv)",
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
return parser
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
if __name__ == "__main__":
|
|
261
|
+
parser = build_parser()
|
|
262
|
+
args = parser.parse_args()
|
|
263
|
+
|
|
264
|
+
if args.command == "run":
|
|
265
|
+
import asyncio
|
|
266
|
+
|
|
267
|
+
asyncio.run(run_command(model=args.model, name=args.name))
|
|
268
|
+
sys.exit(0)
|
|
269
|
+
elif args.command == "compare":
|
|
270
|
+
compare_command(inputs=args.inputs, output=args.output)
|
|
271
|
+
sys.exit(0)
|
|
272
|
+
else:
|
|
273
|
+
parser.print_help()
|
|
274
|
+
sys.exit(2)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from openai import OpenAI
|
|
4
|
+
|
|
5
|
+
DEFAULT_MODEL = "gpt-4.1-nano-2025-04-14"
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_client() -> OpenAI:
|
|
9
|
+
"""Lazily create an OpenAI client, requiring the API key only when used.
|
|
10
|
+
|
|
11
|
+
This avoids raising errors during module import (e.g., when running --help).
|
|
12
|
+
"""
|
|
13
|
+
api_key = os.getenv("OPENAI_API_KEY")
|
|
14
|
+
if not api_key:
|
|
15
|
+
raise RuntimeError(
|
|
16
|
+
"OPENAI_API_KEY is not set. Please export it before running prompts."
|
|
17
|
+
)
|
|
18
|
+
return OpenAI(api_key=api_key)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
SYSTEM_PROMPT = """
|
|
22
|
+
You are a discount calculation assistant. I will provide a customer profile and you must calculate their discount percentage and explain your reasoning.
|
|
23
|
+
|
|
24
|
+
Discount rules:
|
|
25
|
+
- Age 65+ OR student status: 15% discount
|
|
26
|
+
- Annual income < $30,000: 20% discount
|
|
27
|
+
- Premium member for 2+ years: 10% discount
|
|
28
|
+
- New customer (< 6 months): 5% discount
|
|
29
|
+
|
|
30
|
+
Rules can stack up to a maximum of 35% discount.
|
|
31
|
+
|
|
32
|
+
Respond in JSON format only:
|
|
33
|
+
{
|
|
34
|
+
"discount_percentage": number,
|
|
35
|
+
"reason": "clear explanation of which rules apply and calculations",
|
|
36
|
+
"applied_rules": ["list", "of", "applied", "rule", "names"]
|
|
37
|
+
}
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def run_prompt(prompt: str, model: str = DEFAULT_MODEL):
|
|
42
|
+
"""Run the discount calculation prompt with the specified model."""
|
|
43
|
+
client = get_client()
|
|
44
|
+
response = client.chat.completions.create(
|
|
45
|
+
model=model,
|
|
46
|
+
response_format={"type": "json_object"},
|
|
47
|
+
messages=[
|
|
48
|
+
{"role": "system", "content": SYSTEM_PROMPT},
|
|
49
|
+
{"role": "user", "content": prompt},
|
|
50
|
+
],
|
|
51
|
+
)
|
|
52
|
+
response = response.choices[0].message.content.strip()
|
|
53
|
+
return response
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
if __name__ == "__main__":
|
|
57
|
+
customer_profile = """
|
|
58
|
+
Customer Profile:
|
|
59
|
+
- Name: Sarah Johnson
|
|
60
|
+
- Age: 67
|
|
61
|
+
- Student: No
|
|
62
|
+
- Annual Income: $45,000
|
|
63
|
+
- Premium Member: Yes, for 3 years
|
|
64
|
+
- Account Age: 3 years
|
|
65
|
+
"""
|
|
66
|
+
print("=== System Prompt ===")
|
|
67
|
+
print(SYSTEM_PROMPT)
|
|
68
|
+
print("\n=== Customer Profile ===")
|
|
69
|
+
print(customer_profile)
|
|
70
|
+
print(f"\n=== Running Prompt with default model {DEFAULT_MODEL} ===")
|
|
71
|
+
print(run_prompt(customer_profile, model=DEFAULT_MODEL))
|
|
File without changes
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from ragas import Dataset, experiment
|
|
2
|
+
from ragas.metrics.discrete import discrete_metric
|
|
3
|
+
from ragas.metrics.result import MetricResult
|
|
4
|
+
|
|
5
|
+
from .prompt import run_prompt
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@discrete_metric(name="accuracy", allowed_values=["pass", "fail"])
|
|
9
|
+
def my_metric(prediction: str, actual: str):
|
|
10
|
+
"""Calculate accuracy of the prediction."""
|
|
11
|
+
return (
|
|
12
|
+
MetricResult(value="pass", reason="")
|
|
13
|
+
if prediction == actual
|
|
14
|
+
else MetricResult(value="fail", reason="")
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@experiment()
|
|
19
|
+
async def run_experiment(row):
|
|
20
|
+
response = run_prompt(row["text"])
|
|
21
|
+
score = my_metric.score(prediction=response, actual=row["label"])
|
|
22
|
+
|
|
23
|
+
experiment_view = {
|
|
24
|
+
**row,
|
|
25
|
+
"response": response,
|
|
26
|
+
"score": score.value,
|
|
27
|
+
}
|
|
28
|
+
return experiment_view
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def load_dataset():
|
|
32
|
+
# Create a dataset
|
|
33
|
+
dataset = Dataset(
|
|
34
|
+
name="test_dataset",
|
|
35
|
+
backend="local/csv",
|
|
36
|
+
root_dir=".",
|
|
37
|
+
)
|
|
38
|
+
dataset_dict = [
|
|
39
|
+
{"text": "I loved the movie! It was fantastic.", "label": "positive"},
|
|
40
|
+
{"text": "The movie was terrible and boring.", "label": "negative"},
|
|
41
|
+
{"text": "It was an average film, nothing special.", "label": "positive"},
|
|
42
|
+
{"text": "Absolutely amazing! Best movie of the year.", "label": "positive"},
|
|
43
|
+
{"text": "I did not like it at all, very disappointing.", "label": "negative"},
|
|
44
|
+
{"text": "It was okay, not the best but not the worst.", "label": "positive"},
|
|
45
|
+
{
|
|
46
|
+
"text": "I have mixed feelings about it, some parts were good, others not so much.",
|
|
47
|
+
"label": "positive",
|
|
48
|
+
},
|
|
49
|
+
{"text": "What a masterpiece! I would watch it again.", "label": "positive"},
|
|
50
|
+
{
|
|
51
|
+
"text": "I would not recommend it to anyone, it was that bad.",
|
|
52
|
+
"label": "negative",
|
|
53
|
+
},
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
for sample in dataset_dict:
|
|
57
|
+
row = {"text": sample["text"], "label": sample["label"]}
|
|
58
|
+
dataset.append(row)
|
|
59
|
+
|
|
60
|
+
# make sure to save it
|
|
61
|
+
dataset.save()
|
|
62
|
+
return dataset
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
async def main():
|
|
66
|
+
dataset = load_dataset()
|
|
67
|
+
experiment_results = await run_experiment.arun(dataset)
|
|
68
|
+
print("Experiment completed successfully!")
|
|
69
|
+
print("Experiment results:", experiment_results)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
if __name__ == "__main__":
|
|
73
|
+
import asyncio
|
|
74
|
+
|
|
75
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from openai import OpenAI
|
|
4
|
+
|
|
5
|
+
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
SYSTEM_PROMPT = """
|
|
9
|
+
You are a helpful assistant. I will provide a movie review and you will classify it as either positive or negative.
|
|
10
|
+
Please respond with "positive" or "negative" only.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def run_prompt(prompt: str):
|
|
15
|
+
response = client.chat.completions.create(
|
|
16
|
+
model="gpt-4o",
|
|
17
|
+
messages=[
|
|
18
|
+
{"role": "system", "content": SYSTEM_PROMPT},
|
|
19
|
+
{"role": "user", "content": prompt},
|
|
20
|
+
],
|
|
21
|
+
)
|
|
22
|
+
response = (
|
|
23
|
+
response.choices[0].message.content.strip()
|
|
24
|
+
if response.choices[0].message.content
|
|
25
|
+
else ""
|
|
26
|
+
)
|
|
27
|
+
return response
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
if __name__ == "__main__":
|
|
31
|
+
prompt = "The movie was fantastic and I loved every moment of it!"
|
|
32
|
+
print(run_prompt(prompt))
|
|
File without changes
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from openai import OpenAI
|
|
4
|
+
|
|
5
|
+
from ragas import Dataset, experiment
|
|
6
|
+
from ragas.llms import instructor_llm_factory
|
|
7
|
+
from ragas.metrics import DiscreteMetric
|
|
8
|
+
|
|
9
|
+
from .rag import default_rag_client
|
|
10
|
+
|
|
11
|
+
openai_client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
|
|
12
|
+
rag_client = default_rag_client(llm_client=openai_client)
|
|
13
|
+
llm = instructor_llm_factory("openai", model="gpt-4o", client=openai_client)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def load_dataset():
|
|
17
|
+
dataset = Dataset(
|
|
18
|
+
name="test_dataset",
|
|
19
|
+
backend="local/csv",
|
|
20
|
+
root_dir=".",
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
data_samples = [
|
|
24
|
+
{
|
|
25
|
+
"question": "What is ragas 0.3",
|
|
26
|
+
"grading_notes": "- experimentation as the central pillar - provides abstraction for datasets, experiments and metrics - supports evals for RAG, LLM workflows and Agents",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"question": "how are experiment results stored in ragas 0.3?",
|
|
30
|
+
"grading_notes": "- configured using different backends like local, gdrive, etc - stored under experiments/ folder in the backend storage",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"question": "What metrics are supported in ragas 0.3?",
|
|
34
|
+
"grading_notes": "- provides abstraction for discrete, numerical and ranking metrics",
|
|
35
|
+
},
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
for sample in data_samples:
|
|
39
|
+
row = {"question": sample["question"], "grading_notes": sample["grading_notes"]}
|
|
40
|
+
dataset.append(row)
|
|
41
|
+
|
|
42
|
+
# make sure to save it
|
|
43
|
+
dataset.save()
|
|
44
|
+
return dataset
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
my_metric = DiscreteMetric(
|
|
48
|
+
name="correctness",
|
|
49
|
+
prompt="Check if the response contains points mentioned from the grading notes and return 'pass' or 'fail'.\nResponse: {response} Grading Notes: {grading_notes}",
|
|
50
|
+
allowed_values=["pass", "fail"],
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@experiment()
|
|
55
|
+
async def run_experiment(row):
|
|
56
|
+
response = rag_client.query(row["question"])
|
|
57
|
+
|
|
58
|
+
score = my_metric.score(
|
|
59
|
+
llm=llm,
|
|
60
|
+
response=response.get("answer", " "),
|
|
61
|
+
grading_notes=row["grading_notes"],
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
experiment_view = {
|
|
65
|
+
**row,
|
|
66
|
+
"response": response.get("answer", ""),
|
|
67
|
+
"score": score.value,
|
|
68
|
+
"log_file": response.get("logs", " "),
|
|
69
|
+
}
|
|
70
|
+
return experiment_view
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
async def main():
|
|
74
|
+
dataset = load_dataset()
|
|
75
|
+
print("dataset loaded successfully", dataset)
|
|
76
|
+
experiment_results = await run_experiment.arun(dataset)
|
|
77
|
+
print("Experiment completed successfully!")
|
|
78
|
+
print("Experiment results:", experiment_results)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
if __name__ == "__main__":
|
|
82
|
+
import asyncio
|
|
83
|
+
|
|
84
|
+
asyncio.run(main())
|