Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
e6224a7
added optimization code
Sahana24 Apr 15, 2026
0f8f87f
first integrated version , RAG throw an exception
farshad68 Apr 24, 2026
1f1a562
add new dependencies
farshad68 Apr 24, 2026
b2a5ec2
Merge branch 'develop' into feature/optimization
farshad68 Apr 24, 2026
4f9a4a0
add more logs and fallback
farshad68 Apr 29, 2026
bb37d53
make config simple - now we just rewrite the base config - no patching
farshad68 Apr 29, 2026
78bb9af
make dataset names and args not hardcoded in optimization __init__
farshad68 May 4, 2026
a5ee350
chore: update uv.lock after dependency changes
farshad68 May 4, 2026
1f02723
refactor code
farshad68 May 6, 2026
c40629c
The original script worked, but it was hard‑coded (datasets, prompts,…
farshad68 May 7, 2026
c9568cf
improve ingestion performance
carowa292 May 26, 2026
14e9f7b
fix mypy error
carowa292 May 26, 2026
eb21b9f
WIP: retrieval optimisation
hannred May 27, 2026
eb844b8
WIP: improve parameter handling
hannred May 27, 2026
4cae5d7
make search faster
carowa292 May 27, 2026
38d090b
hack to ingest kcenter dump with new updater mechanism
carowa292 May 27, 2026
2f6e15f
include time in objective function & minor fixes
hannred May 29, 2026
cd22a85
fix mypy issues
hannred May 29, 2026
fbb402c
optimisation adjustments
hannred Jun 9, 2026
d618c0b
add resume mechanism for retrieval optimisation
hannred Jun 11, 2026
5cf3c75
add type to function
farshad68 Jun 11, 2026
80402cf
merge develop branch
farshad68 Jun 11, 2026
3bab6bc
set api_key with mock value for test
farshad68 Jun 12, 2026
4786715
remove chunk_size and chunk_overlap because optimizing them with out…
farshad68 Jun 12, 2026
8a351de
fix Ollama timeout and colbert reranking issues
hannred Jun 12, 2026
bd9bedb
Add an ability to upload traning examples file
denkv Jun 16, 2026
6c50f4f
support csv file and dedicated path for dataset
farshad68 Jun 17, 2026
f49e83a
Merge branch 'feature/optimization' of https://github.com/Learn2RAG/c…
farshad68 Jun 17, 2026
6eb05a1
add type ignore overrides for datasets module
farshad68 Jun 17, 2026
edd85df
Preview an uploaded training data file
denkv Jun 25, 2026
77ffb6c
Use per-pipeline `opt_config`
denkv Jun 25, 2026
2ee979c
Add missing `importer_config` for optimizaiton pipeline
denkv Jun 25, 2026
f17ae3b
Create and pass `registry.json` for optimization
denkv Jun 25, 2026
085df97
Start optimization from the pipeline details page
denkv Jun 25, 2026
40dac13
Merge branch 'develop' into feature/optimization
denkv Jun 25, 2026
1447c05
Fix logging config
denkv Jun 25, 2026
018a203
Fix source and path keys
denkv Jun 25, 2026
6ba58ac
Revert "set api_key with mock value for test"
denkv Jun 25, 2026
62f9f7e
Merge commit '6ba58acab6aa491cc06ae386a6b3b1c3f5d0ae88'; branch 'deve…
denkv Jun 25, 2026
116930c
Create the storage directory before saving the file
denkv Jul 13, 2026
f99fc4b
Merge feature/optimization and resolve conflicts
farshad68 Jul 14, 2026
a903917
Merge branch 'develop' into feature/optimization
farshad68 Jul 20, 2026
a5b6a8c
add first working version of the test for optimization
farshad68 Jul 22, 2026
ea97ec8
update test
farshad68 Jul 22, 2026
ed40be7
add test evaluation q and a
farshad68 Jul 22, 2026
2d17e94
add strategy for selecting the optimization algorithm
farshad68 Jul 22, 2026
cbf1cf0
add type
farshad68 Jul 22, 2026
ec76dc5
refactor retrieval optimization
carowa292 Jul 24, 2026
f17c4d4
pin dependencies, use smac 2.4.0 (no swig required)
carowa292 Jul 24, 2026
a4cfa3a
Merge pull request #51 from Learn2RAG/feature/retrieval_optimization
farshad68 Jul 27, 2026
ac80d0e
use ; as seperator
farshad68 Jul 27, 2026
67b1c0e
HF decide for seperator of a csv file
farshad68 Aug 4, 2026
2f6e7f3
Fix the optimization pipeline
denkv Aug 5, 2026
ea4379a
Merge
denkv Aug 5, 2026
a5e0f83
we detect the csv file seperator first
farshad68 Aug 5, 2026
bcdd884
Merge remote-tracking branch 'origin/feature/optimization-tested' int…
farshad68 Aug 6, 2026
cebae41
merge
farshad68 Aug 7, 2026
d8b159d
merge develop for solve the tests problem
farshad68 Aug 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions learn2rag/compose/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,15 @@ def start(self) -> None:
try:
for file in self.content.get('files', []):
file_path = Path(file['path']).expanduser().absolute()
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.write_text(file['content'])
if not file_path.exists() or file.get('force', True):
file_path.parent.mkdir(parents=True, exist_ok=True)
if 'content' in file:
content = file['content']
elif 'src' in file:
content = Path(file['src']).read_text()
else:
raise NotImplementedError(file)
file_path.write_text(content)
except Exception as e:
con.rollback()
raise e
Expand Down
3 changes: 2 additions & 1 deletion learn2rag/evaluation/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,6 @@ def process_qa(dataset_name: str, qa_rows: Any) -> None:
# qa_rows = read_dataset_qa('hotpot_qa', 'distractor', 'validation')
# process_qa('hotpot_qa', qa_rows.select(range(3)))

qa_rows = read_dataset_qa('WikiEval', '', 'train')
target_path = pathlib.Path('./datasets/WikiEval/source')
qa_rows = read_dataset_qa(target_path, split='train')
process_qa('WikiEval', qa_rows)
37 changes: 32 additions & 5 deletions learn2rag/evaluation/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
import logging
import datasets
import json_stream # type: ignore[import-untyped]
from typing import Any, Callable
from typing import Any, Callable, cast
import pandas as pd

import learn2rag.pipeline.ingestion
from learn2rag.pipeline.config import opt_config
Expand Down Expand Up @@ -78,13 +79,39 @@ def ingest_dataset_documents(dataset_name: str) -> None:
# FIXME
# learn2rag.pipeline.ingestion.index(user_config, opt_config)

def read_dataset_qa(file_path: pathlib.Path | str, split: str | None = None) -> Any:
target_path = pathlib.Path(file_path)
logging.debug(f'Loading dataset from: {target_path}')

if not target_path.exists():
raise FileNotFoundError(f"Dataset path does not exist: {target_path}")

if target_path.suffix.lower() == '.csv':
logging.debug('load csv file')
with open(target_path, 'r', encoding='utf-8') as f:
first_line = f.readline()
try:
# Sniff for comma, semicolon, or tab
dialect = csv.Sniffer().sniff(first_line, delimiters=",;\t")
detected_sep = dialect.delimiter
except csv.Error:
# Fallback to standard comma if sniffing fails
detected_sep = ','

logging.debug(f'load csv file with delimiter: "{detected_sep}"')
dataset_dict = datasets.load_dataset('csv', data_files=str(target_path), sep=detected_sep)
else:
logging.debug(f'load HF dataset ')
dataset_dict = datasets.load_from_disk(str(target_path))

def read_dataset_qa(dataset_name: str, subdirectory: str, split: str | None=None) -> Any:
logging.debug(f'{dataset_name=}')
dataset_work_dir = pathlib.Path('./datasets') / dataset_name
dataset_dict = datasets.load_from_disk(dataset_work_dir / 'source' / subdirectory)
return dataset_dict[split] if split is not None else dataset_dict

# def read_dataset_qa(dataset_name: str, subdirectory: str, split: str | None=None) -> Any:
# logging.debug(f'{dataset_name=}')
# dataset_work_dir = pathlib.Path('./datasets') / dataset_name
# dataset_dict = datasets.load_from_disk(dataset_work_dir / 'source' / subdirectory)
# return dataset_dict[split] if split is not None else dataset_dict


def basic_pipeline(dataset_name: str, question: str) -> dict[str, Any]:
user_config = {
Expand Down
98 changes: 98 additions & 0 deletions learn2rag/optimization/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import logging
import pathlib
import os
import json
import collections.abc
import copy
import yaml
import argparse
from typing import Any, Dict, Callable
from collections.abc import Mapping

from . import baseline_optimization
from . import retrieval_optimization

OPTIMIZATION_STRATEGIES: Dict[str, Callable[..., Any]] = {
"baseline": baseline_optimization.run,
"retrieval": retrieval_optimization.run,
}


#TODO : now we need to copy the dataset to here manually it should consider in installation maybe !
# {storage_path}/datasets/WikiEval/
def main() -> None:
parser = argparse.ArgumentParser(description="Run RAG baseline optimization.")
parser.add_argument("task", help="Module task name (e.g., learn2rag.optimization)")
parser.add_argument("--logging-config", type=str, help="Path to logging config yml")
parser.add_argument("--registry-path", type=str, help="Path to registry.json")
parser.add_argument("--dataset", type=str, default="WikiEval")
parser.add_argument("--questions", type=int, default=10)
parser.add_argument("--trials", type=int, default=10)
parser.add_argument(
"--strategy",
type=str,
default="baseline",
choices=list(OPTIMIZATION_STRATEGIES.keys()),
help="Which optimization algorithm to run"
)
args, unknown = parser.parse_known_args()

if args.logging_config and pathlib.Path(args.logging_config).exists():
with open(args.logging_config, 'r') as f:
config = yaml.safe_load(f)
logging.config.dictConfig(config)

logger = logging.getLogger(__name__)
logger.info(f"Running task: {args.task}")
logger.info(f"Optimization started for {args.dataset} using strategy: {args.strategy}")

logging.info(f"Optimization started for {args.dataset}")
#TODO : read or get dataset_name and maxquestions and n_trails

output_dir = pathlib.Path("./optimization/output/")
output_dir.mkdir(parents=True, exist_ok=True)

run_optimization = OPTIMIZATION_STRATEGIES[args.strategy]
run_optimization(args.dataset, args.questions, args.trials, output_dir, args.registry_path)

logging.info("optimization is done")
results_path = output_dir /args.dataset/ "optimization_results.json"
logging.info(f"save optimized results here : {results_path}")
if not results_path.exists():
logging.warning(f"Optimization results not found at {results_path}")
return

with open(results_path, "r") as f:
full_results = json.load(f)

best_config = full_results.get("best_config", {})

target_config_path = os.environ.get("PIPELINE_OPT_CONFIG", "learn2rag/pipeline/opt_config.json")

existing_config = {}
if os.path.exists(target_config_path):
try:
with open(target_config_path, "r", encoding="utf-8") as f:
existing_config = json.load(f)
except json.JSONDecodeError:
logging.error(f"Existing config at {target_config_path} is corrupted. It will be overwritten.")

updated_config = deep_update(copy.deepcopy(existing_config), best_config)

pathlib.Path(target_config_path).parent.mkdir(parents=True, exist_ok=True)
with open(target_config_path, "w", encoding="utf-8") as f:
json.dump(updated_config, f, indent=4)

logging.info(f"Successfully updated opt_config at: {target_config_path}")

def deep_update(source: dict[str, Any], overrides:Mapping[str, Any]) -> dict[str, Any]:
"""Recursively updates a dictionary."""
for key, value in overrides.items():
if isinstance(value, collections.abc.Mapping) and key in source:
deep_update(source.get(key, {}), value)
else:
source[key] = value
return source

if __name__ == "__main__":
main()
Loading
Loading