Skip to content

Commit

Permalink
Merge branch 'main' into prompt_jpt
Browse files Browse the repository at this point in the history
  • Loading branch information
billmetangmo authored Jul 3, 2024
2 parents 2fc1e6b + 153e951 commit ee20b0e
Show file tree
Hide file tree
Showing 12 changed files with 397 additions and 31 deletions.
17 changes: 0 additions & 17 deletions .envrc.gitpod
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,3 @@ then
mv csvdiff_1.4.0_linux_64-bit.deb csvdiff.deb &&\
sudo dpkg -i csvdiff.deb
fi

if ! command -v aws &> /dev/null
then
pushd /tmp || exit
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip && sudo ./aws/install && rm awscliv2.zip && rm -rf aws/ &&\
mkdir "$WORKPLACE"/.aws && touch "$WORKPLACE"/.aws/credentials && touch "$WORKPLACE"/.aws/config &&\
export AWS_SHARED_CREDENTIALS_FILE=$WORKPLACE/.aws/credentials
export AWS_CONFIG_FILE=$WORKPLACE/.aws/config
export AWS_SDK_LOAD_CONFIG=1
aws configure
popd || exit
fi

echo "export AWS_SHARED_CREDENTIALS_FILE=$WORKPLACE/.aws/credentials" >> ~/.bashrc
echo "export AWS_CONFIG_FILE=$WORKPLACE/.aws/config" >> ~/.bashrc
echo "export AWS_SDK_LOAD_CONFIG=1" >> ~/.bashrc
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,7 @@ node_modules/**
package-lock.json
package.json

## To avoid commit of aws creds in gitpod env
.aws/

## To avoid commit of .envrc in gitpod because this cause gitpod to execute .envrc instead of gitpod.yml
.envrc
etl/experiments/.chainlit/**
Expand Down
2 changes: 0 additions & 2 deletions .gitpod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ tasks:
pushd etl/
pre-commit install
pre-commit install --hook-type commit-msg
aws s3 cp s3://mongulu-files/enrich_cache.sqlite enrich_cache.sqlite
curl "https://media.interieur.gouv.fr/rna/rna_waldec_20220301.zip" -o rna_waldec_20220301.zip
unzip rna_waldec_20220301.zip -d rna_waldec_20220301
rm -f rna_waldec_20220301.zip
Expand All @@ -22,4 +21,3 @@ vscode:
- vivaxy.vscode-conventional-commits
- sourcegraph.cody-ai
- donjayamanne.githistory
- amazonwebservices.aws-toolkit-vscode
41 changes: 37 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ If you are here, it means that you are interested in an in-house deployment of t

### Prerequisites

* Have a minimum of competence on the AWS and Terraform cloud
* Create a Sourcegraph account and get credentials to use [CodyAI](https://www.youtube.com/watch?v=_csyHcEcxDA)
* Create a AWS Builder ID to use [Code whisperer](https://www.youtube.com/watch?v=rHNMfOK8pWI) *[Optional]*
* [Devspace](https://www.devspace.sh/) installed locally
* Have admin access on a [Gogocarto](https://gogocarto.fr/projects)
* Go through the [Gogocarto tutorials](https://peertube.openstreetmap.fr/c/gogo_tutos/videos)
Expand All @@ -38,7 +36,6 @@ If you are here, it means that you are interested in an in-house deployment of t
Execute `filter-cameroon.ipynb` et `enrich-database.ipynb` notebooks :
```
pipenv shell
aws s3 cp s3://mongulu-files/enrich_cache.sqlite enrich_cache.sqlite
secretsfoundry run --script 'python filter-cameroon.py'
```

Expand All @@ -58,7 +55,7 @@ You can for example define icons by category (social object); ours are in `html/

```
cd etl/
secretsfoundry run -p --script "chainlit run experiments/ui.py"
secretsfoundry run --script "chainlit run experiments/ui.py"
```

### Deploy the chatbot
Expand All @@ -67,6 +64,42 @@ You can for example define icons by category (social object); ours are in `html/
devspace deploy
```

## Evaluation


### RAG base evaluation dataset

The list of runs `runs.csv` has been built by getting all the runs from the beginning using:
```
export LANGCHAIN_API_KEY=<key>
cd evals/
python3 rag-evals.py save_runs --days 400
```

Then we use [lilac](https://docs.lilacml.com/) to get the most interesting questions by clustering them per topic/category. "Associations in France" was the one chosen, and we also deleted some rows due to irrelevance.

> The clustering repartition is available here: [Clustering Repartition](https://github.com/mongulu-cm/tchoung-te/pull/127#issuecomment-2174444629)
Finally, you just need to do:
```
export LANGCHAIN_API_KEY=<key>
cd evals/
python3 rag.py ragas_eval tchoung-te --run_ids_file=runs.csv
python3 rag.py deepeval tchoung-te --run_ids_file=runs.csv
```

### RAG offline evaluation


Whenever you change a parameter that can affect RAG, you can execute all inputs present in evals/base_ragas_evaluation.csv using langsmith to track them. Then you just have to get the runs and execute above command. As it's just 27 elements, you will be able to compare results manually.

### Backtesting the prompt
```
cd etl/
python3 backtesting_prompt.py
```
Create the dataset on which you want to test the new prompt on langSmith. Then run the file above to backtest and see the results of the new prompt on the dataset. You would specify in the file the name of the dataset before running

## Contributors ✨

Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
Expand Down
1 change: 1 addition & 0 deletions etl/experiments/evals/.deepeval-cache.json

Large diffs are not rendered by default.

194 changes: 194 additions & 0 deletions etl/experiments/evals/base_ragas_evaluation.csv

Large diffs are not rendered by default.

134 changes: 134 additions & 0 deletions etl/experiments/evals/rag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import fire
from langsmith import Client
from datetime import datetime, timedelta
from tqdm import tqdm
from deepeval.test_case import LLMTestCase
from deepeval.dataset import EvaluationDataset
from deepeval.metrics.ragas import RAGASAnswerRelevancyMetric, RAGASFaithfulnessMetric
# from deepeval.metrics import ContextualRelevancyMetric, FaithfulnessMetric, AnswerRelevancyMetric
import datasets
from ragas import evaluate
from ragas.metrics import answer_relevancy, faithfulness, context_relevancy, context_utilization
import json
import csv


class EvaluationProcessor:
def __init__(self):
self.client = Client()

def _get_prompt(self, original_text, content_to_remove):
"""
Supprime chaque ligne de content_to_remove dans le texte original.
Paramètres:
original_text (str): Le texte original contenant les lignes à supprimer.
content_to_remove (str): Le contenu contenant les lignes à supprimer.
Retourne:
str: Le texte original avec les lignes spécifiées supprimées.
"""
original_lines = original_text.splitlines()
lines_to_remove = set(content_to_remove.splitlines())

filtered_lines = [line for line in original_lines if line not in lines_to_remove]
return '\n'.join(filtered_lines)

def _format_documents(self, docs):
formatted_output = ""
for item in docs:
formatted_output += item["page_content"] + "\n\n"
return formatted_output

def _save_results(self, results, output_format):
if output_format == 'json':
with open('results.json', 'w', encoding='utf-8') as f:
json.dump(results, f, ensure_ascii=False, indent=4)
elif output_format == 'csv':
keys = results[0].keys()
with open('results.csv', 'w', newline='', encoding='utf-8') as f:
dict_writer = csv.DictWriter(f, fieldnames=keys)
dict_writer.writeheader()
dict_writer.writerows(results)
else:
raise ValueError("Unsupported output format. Please use 'csv' or 'json'.")

def _process_runs(self, project_name, days=None, run_ids_file=None, output_format='csv'):
if days:
start_time = datetime.utcnow() - timedelta(days=days)
runs = self.client.list_runs(project_name=project_name, start_time=start_time, is_root=True)
elif run_ids_file:
with open(run_ids_file, 'r') as file:
run_ids = [line.strip() for line in file.readlines()]
runs = self.client.list_runs(project_name=project_name, run_ids=run_ids)
else:
raise ValueError("Either 'days' or 'run_ids_file' must be specified.")

results = []
for run in tqdm(runs, desc="Processing runs"):
child_runs = self.client.list_runs(trace_id=run.trace_id)
for child_run in child_runs:
if child_run.name == "Retriever":
docs = [doc['page_content'] for doc in child_run.outputs['documents']]
format_docs = self._format_documents(child_run.outputs['documents'])
if child_run.name == "ChatOpenAI":
if "SystemMessage" in child_run.inputs['messages'][0]['id']:
sys_message = child_run.inputs['messages'][0]['kwargs']['content']
prompt = self._get_prompt(sys_message, format_docs)
results.append({
'run_id': run.id,
'prompt': prompt,
'question': run.inputs['question'],
'answer': run.outputs['answer'] if run.outputs is not None else "",
'formatted_docs': format_docs,
'chat_history': run.inputs['chat_history'],
'docs': docs
})
return results

def save_runs(self, project_name, days=None, run_ids_file=None, output_format="csv"):
results = self._process_runs(project_name, days, run_ids_file)
self._save_results(results, output_format)

def ragas_eval(self, project_name, days=None, run_ids_file=None, output_format='csv'):
results = self._process_runs(project_name, days, run_ids_file)
ragas_dataset = {"question": [], "answer": [], "ground_truths": [], "contexts": []}

for result in results:
ragas_dataset["question"].append(result['question'])
ragas_dataset["answer"].append(result['answer'])
ragas_dataset["ground_truths"].append([])
ragas_dataset["contexts"].append(result['docs'])

hf_ragas_dataset = datasets.Dataset.from_dict(ragas_dataset)
evaluation_result = evaluate(
hf_ragas_dataset,
raise_exceptions=False,
metrics=[
context_relevancy,
faithfulness,
answer_relevancy,
context_utilization
]
)
df = evaluation_result.to_pandas()
if output_format == "csv":
df.to_csv("ragas_evaluation_results.csv", index=False)
elif output_format == "json":
df.to_json("ragas_evaluation_results.json", index=False)

def deepeval(self, project_name, days=None, run_ids_file=None):
results = self._process_runs(project_name, days, run_ids_file)
dataset = EvaluationDataset()
for result in results:
test_case = LLMTestCase(input=result['question'],
actual_output=result['answer'],
retrieval_context=result['docs'],
)
dataset.add_test_case(test_case)
faithfulness = RAGASFaithfulnessMetric(threshold=0.5)
relevancy = RAGASAnswerRelevancyMetric()
dataset.evaluate([faithfulness, relevancy])

if __name__ == '__main__':
fire.Fire(EvaluationProcessor)
23 changes: 23 additions & 0 deletions etl/experiments/evals/runs.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
ea84af53-f4ce-4eeb-b5bd-42bfd4d9d06e
fcdc9c6f-dc4c-446d-a7fc-7552bb8e0643
b5291b99-c6e8-4e9a-a454-9047dabe7bcd
c9fa9be2-d350-4f0d-ad7e-eac5125a4740
e5dfc187-e24a-45ab-aa0e-614a5d0796b0
d2cbc6a7-fead-4d98-a864-61997aedc9ea
02be1332-c9ef-4b5f-b173-92b52780f3e1
48e78219-b27f-425b-8242-bba7091354d3
2666c586-fc22-40c4-b86b-2850f6dfd8b1
a560b2cf-5f51-49e6-a5b8-254cc4381f57
0827e602-8df4-4ddc-98c6-899ae91f2253
fd983384-e78f-4bbc-9487-af51bfe26e16
71aa2783-2026-44cb-ae6d-c9d157063105
8d8e5d06-aba0-4292-ac34-58b44f98fdc6
4580340f-e146-4fa0-abaa-5128b60a02c4
36be4151-62cd-4824-8ae3-69e929d92e7e
ac339665-2f43-40c7-bc0d-50bffcad7d61
c4a188df-2ad6-4236-97ec-8bfc18cf6b91
895e76be-f6fc-4c56-9cd4-3469bdd40dba
9528ddb3-f62c-4c83-b028-dcb73d2d7683
f3aa4d09-e8ab-4cd5-a159-f43fddbfc47d
e657af9f-a4da-4861-83b7-315c9f4be594
8d0a4e00-5e3b-4184-8166-b09b60625a9e
3 changes: 3 additions & 0 deletions etl/filter-cameroon.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
from pandarallel import pandarallel
from rich.console import Console

# enrich_cache finally not used, it was store in aws but with clear params
# geocode is used now => store in local => 1000 requ free per day

# %%
start = time.time()
file_location = os.getcwd() + "/rna_waldec_20220301/"
Expand Down
2 changes: 1 addition & 1 deletion etl/ref-rna-real-mars-2022-enriched-qualified-contacts.csv
Original file line number Diff line number Diff line change
Expand Up @@ -2307,7 +2307,7 @@ W721000821,"subvenir aux besoins d'enfants camerounais orphelins ou en difficult
W721001480,"fédérer les camerounais de sablé-sur-sarthe et d'ailleurs autour d'un projet solidaire afin de créer du lien entre eux, de faire connaitre la culture camerounaise aux habitants de sablé-sur-sarthe, d'aider les personnes porteuses d'un handicap au cameroun et efin d'aider les orphelins du cameroun ; elle organisera pour se faire connaitre des manifestations culturelles afin de récolter des fonds et de faire connaitre l'association ; des contacts au cameroun faciliteront les actions entre le pays et l'association ; exploitation, fabrication et vente de produits alimentaires ainsi que la coiffure et toutes activités liées à la coiffure",29 RUE Saint-Nicolas 72300 Sablé-sur-Sarthe,Sarthe,Pays de la Loire,AMICALES/ GROUPEMENTS AFFINITAIRES/ GROUPEMENTS D'ENTRAIDE (HORS DÉFENSE DE DROITS FONDAMENTAUX),AMITIES CAMEROUNAISES - ASSOCIATION SABOLIENNE D'AIDE AUX PERSONNES HANDICAPEES CAMEROUNAISES ET AUX ORPHELINS DU CAMEROUN,,,29.0,RUE,Saint-Nicolas,72300.0,Sablé-sur-Sarthe,,AUTRES,-0.3267433,47.8381678,,
W721002294,"apporter aux populations locales dudit département une aide matérielle, morale , afin de limiter l'exode rural et de participer au désenclavement de la région et surtout de sensibiliser la population sur la question du sida et leur apporter les moyens de prévention",72300 Sablé-sur-Sarthe,Sarthe,Pays de la Loire,ASSOCIATIONS CARITATIVES/ HUMANITAIRES/ AIDE AU DÉVELOPPEMENT/ DÉVELOPPEMENT DU BÉNÉVOLAT,ASSOCIATION POUR LE DEVELOPPEMENT DU MUNGO ( CAMEROUN),,,,,,72300.0,Sablé-sur-Sarthe,,AUTRES,-0.3352048,47.8400712,,
W721002499,relayer l'association cf égalisation cameroum ( elle a pour objet de regrouper des familles camerounaises souhaitant recevoir des personnes et leur faire découvrir eux-mêmes leur région) en la faisant connaitre auprès du public en assurant la réservation dans les familles d'accueil,72300 Sablé-sur-Sarthe,Sarthe,Pays de la Loire,AMICALES/ GROUPEMENTS AFFINITAIRES/ GROUPEMENTS D'ENTRAIDE (HORS DÉFENSE DE DROITS FONDAMENTAUX),MA MAISON EST TA MAISON,,,,,,72300.0,Sablé-sur-Sarthe,,AUTRES,-0.3352048,47.8400712,,
W723000645,"promouvoir la culture camerounaise. veiller à la bonne intégration sociale de ses adhérents (activités sportives et culturelles, excursions, soirées thématiques...)",16 RUE de la Barillerie 72000 Mans,Sarthe,Pays de la Loire,CULTURE/ PRATIQUES D'ACTIVITÉS ARTISTIQUES/ PRATIQUES CULTURELLES,ASSOCIATION DES ETUDIANTS CAMEROUNAIS DU MANS (A.E.C.M.),https://www.facebook.com/aecmlemans,https://www.helloasso.com/associations/association-des-etudiants-camerounais-du-mans-aecm,16.0,RUE,de la Barillerie,72000.0,Mans,,AUTRES,0.1977338,48.0061424,infoaecm2003@gmail.com,0782291575
W723000645,"promouvoir la culture camerounaise. veiller à la bonne intégration sociale de ses adhérents (activités sportives et culturelles, excursions, soirées thématiques...)",16 RUE de la Barillerie 72000 Mans,Sarthe,Pays de la Loire,CULTURE/ PRATIQUES D'ACTIVITÉS ARTISTIQUES/ PRATIQUES CULTURELLES,ASSOCIATION DES ETUDIANTS CAMEROUNAIS DU MANS (A.E.C.M.),https://www.facebook.com/aecmlemans,https://www.helloasso.com/associations/association-des-etudiants-camerounais-du-mans-aecm,16.0,RUE,de la Barillerie,72000.0,Mans,,AUTRES,0.1977338,48.0061424,aecm2023@gmail.com,0782291575
W723002438,soutenir et entraider les différents membres de la diaspora camerounaise présente en sarthe ; aider et assister les familles restées au pays ; promouvoir la culture camerounaise ; organiser des soirées culturelles et des foires,1 RUE Alfred Kastler 72100 Le Mans,Sarthe,Pays de la Loire,AMICALES/ GROUPEMENTS AFFINITAIRES/ GROUPEMENTS D'ENTRAIDE (HORS DÉFENSE DE DROITS FONDAMENTAUX),ENTRE NOUS CAMEROUNAIS DE LA SARTHE,,,1.0,RUE,Alfred Kastler,72100.0,Le Mans,,AUTRES,0.200929,47.9761198,,
W723004407,"always one est une association à buts non lucratifs et apolitiques qui est née en france, des étudiants camerounais et qui oeuvre pour le développement en afrique et dans leurs pays en particulier en participant essentiellement à l'éducation morale et mentale qui sont deux éducations dont les programmes éducatifs locaux ne prennent pas grandement en compte, l'association sensibilise aussi les populations pour l'éradication des maux tel que le tribalisme, la corruption ,le favoritisme et bien d'autres et se bat aussi au respect des droits et devoirs qui sont les bases d'une relation entre un peuple et ses dirigeants",94 AV Rhin et danube 72000 Mans,Sarthe,Pays de la Loire,AMICALES/ GROUPEMENTS AFFINITAIRES/ GROUPEMENTS D'ENTRAIDE (HORS DÉFENSE DE DROITS FONDAMENTAUX),ALWAYS ONE,,,94.0,AV,Rhin et danube,72000.0,Mans,,AUTRES,0.1869615,48.0142916,,
W723004570,"promouvoir le traitement pour tous ; favoriser l'insertion sociale des enfants malades et défavorisés ; aider les jeunes adultes à trouver leur place dans la société ; apporter aux patients hémophiles ainsi qu'à leur famille une aide médicale et psycho-sociale au travers de nombreuses activités pédagogiques ; l'égalité des chances des enfants du cameroun est la priorité de l'association ; la médicalisation des enfants hémophiles leur permettra d'avoir une qualité de vie presque normale et, de là les mêmes chances d'intégration professionnelle une fois devenus adultes ; dans les pays en voie de développement tels que le cameroun, une majorité d'enfants privés de traitement deviennent des adultes marqués par un handicap partiel ou total",249 CHEM1 de Birac 82000 Montauban,Tarn-et-Garonne,Occitanie,SANTÉ,MIEUX VIVRE AVEC L'HEMOPHILIE AU CAMEROUN ( MIVIAH CAMEROUN),https://www.facebook.com/MiViAHCameroun/,,249.0,CHEM1,de Birac,82000.0,Montauban,,AUTRES,1.3549991,44.0175835,,
Expand Down
5 changes: 1 addition & 4 deletions etl/requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
nbdime==3.1.1
python-lsp-server[all]==1.4.1
jupyterlab-lsp== 3.10.1
nbqa==1.3.1
jupyterlab-tabular-data-editor==1.0.0
csvs-to-sqlite==1.3
ipython>=8.10.0 # not directly required, pinned by Snyk to avoid a vulnerability
numpy>=1.22.2 # not directly required, pinned by Snyk to avoid a vulnerability
setuptools>=65.5.1 # not directly required, pinned by Snyk to avoid a vulnerability
jupyter-server>=2.11.2 # not directly required, pinned by Snyk to avoid a vulnerability
tornado>=6.3.3 # not directly required, pinned by Snyk to avoid a vulnerability
pipdeptree==2.2.1
urllib3>=2.2.2 # not directly required, pinned by Snyk to avoid a vulnerability
3 changes: 2 additions & 1 deletion etl/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ geopy==2.2.0
pandarallel==1.6.1
pipdeptree==2.2.1
requests-cache==0.9.4
tqdm==4.64.0
tqdm==4.66.3
wheel==0.38.1
abbreviations==0.2.5
rich==12.4.4
Expand All @@ -25,3 +25,4 @@ chainlit==0.5.1
tornado>=6.3.3 # not directly required, pinned by Snyk to avoid a vulnerability
aiohttp>=3.9.0 # not directly required, pinned by Snyk to avoid a vulnerability
sentry_sdk==1.39.1
requests>=2.32.0 # not directly required, pinned by Snyk to avoid a vulnerability

0 comments on commit ee20b0e

Please sign in to comment.