aidial-rag-eval 0.6.0.dev16__tar.gz → 0.6.0.dev20__tar.gz

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.
Files changed (51) hide show
  1. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/PKG-INFO +41 -12
  2. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/README.md +37 -8
  3. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/pyproject.toml +5 -4
  4. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/dataframe/metrics.py +33 -19
  5. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/evaluate.py +0 -2
  6. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/inference.py +45 -44
  7. aidial_rag_eval-0.6.0.dev20/src/aidial_rag_eval/generation/metric_binds.py +125 -0
  8. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/refusal.py +1 -7
  9. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/types.py +19 -6
  10. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/utils/segmented_text.py +38 -9
  11. aidial_rag_eval-0.6.0.dev20/src/aidial_rag_eval/metric_binds.py +19 -0
  12. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/types.py +3 -5
  13. aidial_rag_eval-0.6.0.dev16/src/aidial_rag_eval/generation/metric_binds.py +0 -174
  14. aidial_rag_eval-0.6.0.dev16/src/aidial_rag_eval/metric_binds.py +0 -15
  15. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/LICENSE +0 -0
  16. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/__init__.py +0 -0
  17. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/dataframe/__init__.py +0 -0
  18. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/dataframe/match_facts.py +0 -0
  19. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/dataframe/merge.py +0 -0
  20. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/dataset.py +0 -0
  21. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/facts/__init__.py +0 -0
  22. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/facts/citation.py +0 -0
  23. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/facts/exact.py +0 -0
  24. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/facts/match_str_facts.py +0 -0
  25. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/__init__.py +0 -0
  26. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/models/__init__.py +0 -0
  27. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/models/converters/__init__.py +0 -0
  28. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/models/converters/base_converter.py +0 -0
  29. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/models/converters/decontextualization_template.py +0 -0
  30. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/models/converters/llm_decontextualization_converter.py +0 -0
  31. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/models/inference_scorers/__init__.py +0 -0
  32. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/models/inference_scorers/base_inference_scorer.py +0 -0
  33. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/models/inference_scorers/inference_template.py +0 -0
  34. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/models/inference_scorers/llm_inference_scorer.py +0 -0
  35. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/models/lambdas.py +0 -0
  36. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/models/refusal_detectors/__init__.py +0 -0
  37. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/models/refusal_detectors/base_refusal_detector.py +0 -0
  38. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/models/refusal_detectors/llm_refusal_detector.py +0 -0
  39. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/models/refusal_detectors/refusal_template.py +0 -0
  40. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/models/statement_extractor/__init__.py +0 -0
  41. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/models/statement_extractor/base_statement_extractor.py +0 -0
  42. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/models/statement_extractor/llm_statement_extractor.py +0 -0
  43. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/models/statement_extractor/statement_extractor_template.py +0 -0
  44. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/utils/__init__.py +0 -0
  45. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/utils/exceptions.py +0 -0
  46. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/generation/utils/progress_bar.py +0 -0
  47. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/metrics.py +0 -0
  48. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/retrieval/__init__.py +0 -0
  49. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/retrieval/metrics.py +0 -0
  50. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/retrieval/types.py +0 -0
  51. {aidial_rag_eval-0.6.0.dev16 → aidial_rag_eval-0.6.0.dev20}/src/aidial_rag_eval/utils.py +0 -0
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aidial-rag-eval
3
- Version: 0.6.0.dev16
3
+ Version: 0.6.0.dev20
4
4
  Summary: Library for RAG evaluation
5
5
  License: Apache-2.0
6
6
  License-File: LICENSE
7
7
  Keywords: ai
8
8
  Author: EPAM RAIL
9
9
  Author-email: SpecialEPM-DIALDevTeam@epam.com
10
- Requires-Python: >=3.11,<4.0
10
+ Requires-Python: >=3.11,<3.15
11
11
  Classifier: License :: OSI Approved :: Apache Software License
12
12
  Classifier: Programming Language :: Python :: 3
13
13
  Classifier: Programming Language :: Python :: 3.11
@@ -19,12 +19,12 @@ Provides-Extra: s3fs
19
19
  Requires-Dist: fsspec (>=2024.3.1,<2025.0.0)
20
20
  Requires-Dist: langchain-core (>=0.3.80,<2)
21
21
  Requires-Dist: more-itertools (>=10.5.0,<11.0.0)
22
- Requires-Dist: nltk (>=3.8.1,<4.0.0)
23
22
  Requires-Dist: numpy (>=1.26.4,<3)
24
23
  Requires-Dist: pandas (>=2.2.2,<3.0.0)
25
24
  Requires-Dist: pyarrow (>=20.0.0)
26
- Requires-Dist: pydantic (>=2.7.1,<3.0.0)
25
+ Requires-Dist: pydantic (>=2.7.1)
27
26
  Requires-Dist: s3fs (>=2024.3.1,<2025.0.0) ; extra == "s3fs"
27
+ Requires-Dist: spacy (>=3.8.9,<4)
28
28
  Requires-Dist: tqdm (>=4.66.4,<5.0.0)
29
29
  Project-URL: Documentation, https://github.com/epam/ai-dial-rag-eval
30
30
  Project-URL: Homepage, https://github.com/epam/ai-dial-rag-eval
@@ -47,6 +47,27 @@ Install the library using [pip](https://pip.pypa.org/en/stable/getting-started):
47
47
  pip install aidial-rag-eval
48
48
  ```
49
49
 
50
+ ### spaCy language model
51
+
52
+ The generation metrics require the English language model for [spaCy](https://spacy.io/).
53
+ Download it after installation:
54
+
55
+ ```sh
56
+ python -m spacy download en_core_web_sm
57
+ ```
58
+
59
+ Alternatively, you can install the model directly via URL:
60
+
61
+ ```sh
62
+ pip install https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.8.0/en_core_web_sm-3.8.0-py3-none-any.whl
63
+ ```
64
+
65
+ Or as a [Poetry](https://python-poetry.org/) dependency:
66
+
67
+ ```toml
68
+ en-core-web-sm = {url = "https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.8.0/en_core_web_sm-3.8.0-py3-none-any.whl"}
69
+ ```
70
+
50
71
  ### Example
51
72
 
52
73
  The example of how to get retrieval metrics along with answer inference based on the context.
@@ -56,7 +77,8 @@ import pandas as pd
56
77
  from langchain_openai import AzureChatOpenAI
57
78
  from aidial_rag_eval import create_rag_eval_metrics_report
58
79
  from aidial_rag_eval.metric_binds import CONTEXT_TO_ANSWER_INFERENCE,\
59
- ANSWER_TO_GROUND_TRUTH_INFERENCE, GROUND_TRUTH_TO_ANSWER_INFERENCE
80
+ ANSWER_TO_GROUND_TRUTH_INFERENCE, GROUND_TRUTH_TO_ANSWER_INFERENCE,\
81
+ ANSWER_TO_FACTS_INFERENCE, FACTS_TO_ANSWER_INFERENCE
60
82
 
61
83
  llm = AzureChatOpenAI(model="gemini-2.5-flash-lite")
62
84
 
@@ -87,16 +109,18 @@ df_metrics = create_rag_eval_metrics_report(
87
109
  CONTEXT_TO_ANSWER_INFERENCE,
88
110
  ANSWER_TO_GROUND_TRUTH_INFERENCE,
89
111
  GROUND_TRUTH_TO_ANSWER_INFERENCE,
112
+ ANSWER_TO_FACTS_INFERENCE,
113
+ FACTS_TO_ANSWER_INFERENCE,
90
114
  ],
91
115
  )
92
- print(df_metrics[["facts_ranks", "recall", 'precision', 'mrr', 'f1', 'ctx_ans_inference', 'ans_gt_inference', 'gt_ans_inference']])
116
+ print(df_metrics[["facts_ranks", "recall", 'precision', 'mrr', 'f1', 'ctx_ans_inference', 'ans_gt_inference', 'gt_ans_inference', 'ans_fct_inference', 'fct_ans_inference']])
93
117
  ```
94
118
 
95
119
  It is expected to see the following results:
96
120
 
97
- | recall | precision | mrr | f1 | ctx_ans_inference | ans_gt_inference | gt_ans_inference |
98
- | ------ | --------- | --- | --- | ----------------- | ---------------- | ---------------- |
99
- | 0.5 | 0.5 | 0.5 | 0.5 | 1.0 | 0.5 | 1.0 |
121
+ | recall | precision | mrr | f1 | ctx_ans_inference | ans_gt_inference | gt_ans_inference | ans_fct_inference | fct_ans_inference |
122
+ | ------ | --------- | --- | --- | ----------------- | ---------------- | ---------------- | ----------------- | ----------------- |
123
+ | 0.5 | 0.5 | 0.5 | 0.5 | 1.0 | 0.5 | 1.0 | 0.5 | 1.0 |
100
124
 
101
125
  In this table:
102
126
 
@@ -106,17 +130,22 @@ In this table:
106
130
  - "ctx" refers to 'context'
107
131
  - "ans" refers to 'answer'
108
132
  - "gt" refers to 'ground truth answer'
109
- - "ctx_ans_inference" and "ans_gt_inference" values of 1.0 mean our answer can be derived directly from the context and the ground truth answer, respectively.
110
- - "gt_ans_inference" of 0.5, denotes that the ground truth answer can only be partially inferred from our answer.
133
+ - "fct" refers to 'facts'
134
+ - "ctx_ans_inference" of 1.0 means our answer can be fully derived from the context.
135
+ - "ans_gt_inference" of 0.5 means the ground truth answer is only partially entailed by our answer.
136
+ - "gt_ans_inference" of 1.0 means our answer can be fully derived from the ground truth answer.
137
+ - "ans_fct_inference" of 0.5 means only half of the ground truth facts are entailed by our answer (the Pacific Ocean fact is missing).
138
+ - "fct_ans_inference" of 1.0 means our answer can be fully derived from the ground truth facts.
111
139
 
112
140
  ## Recommended models
113
141
 
114
142
  The algorithm is token-intensive. Considering the balance between quality and price, the following models are recommended:
115
143
 
144
+ - **gemini-3.1-flash-lite**
116
145
  - **gemini-2.5-flash-lite**
117
146
  - **gpt-5-mini**
118
- - **gemini-2.0-flash-lite**
119
147
  - **gpt-5-nano**
148
+ - **gpt-5.4-mini**
120
149
 
121
150
  ## Developer environment
122
151
 
@@ -14,6 +14,27 @@ Install the library using [pip](https://pip.pypa.org/en/stable/getting-started):
14
14
  pip install aidial-rag-eval
15
15
  ```
16
16
 
17
+ ### spaCy language model
18
+
19
+ The generation metrics require the English language model for [spaCy](https://spacy.io/).
20
+ Download it after installation:
21
+
22
+ ```sh
23
+ python -m spacy download en_core_web_sm
24
+ ```
25
+
26
+ Alternatively, you can install the model directly via URL:
27
+
28
+ ```sh
29
+ pip install https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.8.0/en_core_web_sm-3.8.0-py3-none-any.whl
30
+ ```
31
+
32
+ Or as a [Poetry](https://python-poetry.org/) dependency:
33
+
34
+ ```toml
35
+ en-core-web-sm = {url = "https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.8.0/en_core_web_sm-3.8.0-py3-none-any.whl"}
36
+ ```
37
+
17
38
  ### Example
18
39
 
19
40
  The example of how to get retrieval metrics along with answer inference based on the context.
@@ -23,7 +44,8 @@ import pandas as pd
23
44
  from langchain_openai import AzureChatOpenAI
24
45
  from aidial_rag_eval import create_rag_eval_metrics_report
25
46
  from aidial_rag_eval.metric_binds import CONTEXT_TO_ANSWER_INFERENCE,\
26
- ANSWER_TO_GROUND_TRUTH_INFERENCE, GROUND_TRUTH_TO_ANSWER_INFERENCE
47
+ ANSWER_TO_GROUND_TRUTH_INFERENCE, GROUND_TRUTH_TO_ANSWER_INFERENCE,\
48
+ ANSWER_TO_FACTS_INFERENCE, FACTS_TO_ANSWER_INFERENCE
27
49
 
28
50
  llm = AzureChatOpenAI(model="gemini-2.5-flash-lite")
29
51
 
@@ -54,16 +76,18 @@ df_metrics = create_rag_eval_metrics_report(
54
76
  CONTEXT_TO_ANSWER_INFERENCE,
55
77
  ANSWER_TO_GROUND_TRUTH_INFERENCE,
56
78
  GROUND_TRUTH_TO_ANSWER_INFERENCE,
79
+ ANSWER_TO_FACTS_INFERENCE,
80
+ FACTS_TO_ANSWER_INFERENCE,
57
81
  ],
58
82
  )
59
- print(df_metrics[["facts_ranks", "recall", 'precision', 'mrr', 'f1', 'ctx_ans_inference', 'ans_gt_inference', 'gt_ans_inference']])
83
+ print(df_metrics[["facts_ranks", "recall", 'precision', 'mrr', 'f1', 'ctx_ans_inference', 'ans_gt_inference', 'gt_ans_inference', 'ans_fct_inference', 'fct_ans_inference']])
60
84
  ```
61
85
 
62
86
  It is expected to see the following results:
63
87
 
64
- | recall | precision | mrr | f1 | ctx_ans_inference | ans_gt_inference | gt_ans_inference |
65
- | ------ | --------- | --- | --- | ----------------- | ---------------- | ---------------- |
66
- | 0.5 | 0.5 | 0.5 | 0.5 | 1.0 | 0.5 | 1.0 |
88
+ | recall | precision | mrr | f1 | ctx_ans_inference | ans_gt_inference | gt_ans_inference | ans_fct_inference | fct_ans_inference |
89
+ | ------ | --------- | --- | --- | ----------------- | ---------------- | ---------------- | ----------------- | ----------------- |
90
+ | 0.5 | 0.5 | 0.5 | 0.5 | 1.0 | 0.5 | 1.0 | 0.5 | 1.0 |
67
91
 
68
92
  In this table:
69
93
 
@@ -73,17 +97,22 @@ In this table:
73
97
  - "ctx" refers to 'context'
74
98
  - "ans" refers to 'answer'
75
99
  - "gt" refers to 'ground truth answer'
76
- - "ctx_ans_inference" and "ans_gt_inference" values of 1.0 mean our answer can be derived directly from the context and the ground truth answer, respectively.
77
- - "gt_ans_inference" of 0.5, denotes that the ground truth answer can only be partially inferred from our answer.
100
+ - "fct" refers to 'facts'
101
+ - "ctx_ans_inference" of 1.0 means our answer can be fully derived from the context.
102
+ - "ans_gt_inference" of 0.5 means the ground truth answer is only partially entailed by our answer.
103
+ - "gt_ans_inference" of 1.0 means our answer can be fully derived from the ground truth answer.
104
+ - "ans_fct_inference" of 0.5 means only half of the ground truth facts are entailed by our answer (the Pacific Ocean fact is missing).
105
+ - "fct_ans_inference" of 1.0 means our answer can be fully derived from the ground truth facts.
78
106
 
79
107
  ## Recommended models
80
108
 
81
109
  The algorithm is token-intensive. Considering the balance between quality and price, the following models are recommended:
82
110
 
111
+ - **gemini-3.1-flash-lite**
83
112
  - **gemini-2.5-flash-lite**
84
113
  - **gpt-5-mini**
85
- - **gemini-2.0-flash-lite**
86
114
  - **gpt-5-nano**
115
+ - **gpt-5.4-mini**
87
116
 
88
117
  ## Developer environment
89
118
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "aidial-rag-eval"
3
- version = "0.6.0.dev16"
3
+ version = "0.6.0.dev20"
4
4
  description = "Library for RAG evaluation"
5
5
  authors = ["EPAM RAIL <SpecialEPM-DIALDevTeam@epam.com>"]
6
6
  homepage = "https://github.com/epam/ai-dial-rag-eval"
@@ -13,13 +13,13 @@ repository = "https://github.com/epam/ai-dial-rag-eval"
13
13
 
14
14
 
15
15
  [tool.poetry.dependencies]
16
- python = "^3.11"
16
+ python = ">=3.11, <3.15"
17
17
  numpy = ">=1.26.4,<3"
18
18
  pandas = "^2.2.2"
19
19
  fsspec = "^2024.3.1"
20
20
  s3fs = {version = "^2024.3.1", optional = true}
21
- pydantic = "^2.7.1"
22
- nltk = "^3.8.1"
21
+ pydantic = ">=2.7.1"
22
+ spacy = ">=3.8.9,<4"
23
23
  tqdm = "^4.66.4"
24
24
  langchain-core = ">=0.3.80,<2"
25
25
  more-itertools = "^10.5.0"
@@ -35,6 +35,7 @@ pytest-cov = "^4.1.0"
35
35
  pytest-mock = "^3.14.0"
36
36
  langchain-community = "^0.3.14"
37
37
  langchain-openai = "^0.2.1"
38
+ en-core-web-sm = {url = "https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.8.0/en_core_web_sm-3.8.0-py3-none-any.whl"}
38
39
 
39
40
  [tool.poetry.group.lint.dependencies]
40
41
  black = "^24.3.0"
@@ -8,13 +8,20 @@ from aidial_rag_eval.dataframe.match_facts import (
8
8
  apply_matcher_to_merged_dataframe,
9
9
  )
10
10
  from aidial_rag_eval.dataframe.merge import merge_ground_truth_and_answers
11
- from aidial_rag_eval.generation.metric_binds import metric_binds_dict
12
- from aidial_rag_eval.generation.types import MetricBind, inference_column
11
+ from aidial_rag_eval.generation.metric_binds import (
12
+ _wrapped_dataframe_inference,
13
+ _wrapped_dataframe_refusal,
14
+ )
15
+ from aidial_rag_eval.generation.types import (
16
+ InferenceMetricBind,
17
+ MetricBind,
18
+ RefusalMetricBind,
19
+ inference_column,
20
+ )
13
21
  from aidial_rag_eval.retrieval.metrics import (
14
22
  calculate_metrics as calculate_metrics_by_row,
15
23
  )
16
24
  from aidial_rag_eval.retrieval.types import Matcher
17
- from aidial_rag_eval.types import MergedColumns
18
25
 
19
26
 
20
27
  def apply_metrics_to_matched_results(match_result_data: pd.DataFrame) -> pd.DataFrame:
@@ -114,7 +121,6 @@ def calculate_generation_metrics(
114
121
  metric_binds: List[MetricBind],
115
122
  max_concurrency: int = 8,
116
123
  show_progress_bar: bool = True,
117
- auto_download_nltk: bool = True,
118
124
  ) -> pd.DataFrame:
119
125
  """
120
126
  Calculates RAG evaluation generation metrics from df_merged dataframe.
@@ -130,7 +136,7 @@ def calculate_generation_metrics(
130
136
  A Langchain chat model used for calculating generation metrics.
131
137
 
132
138
  metric_binds : List[MetricBind], optional, default=None
133
- A list of string constants from `aidial_rag_eval.metric_binds`
139
+ A list of metric bind instances from `aidial_rag_eval.metric_binds`
134
140
  specifying the generation metrics.
135
141
 
136
142
  max_concurrency : int, default=8
@@ -145,20 +151,32 @@ def calculate_generation_metrics(
145
151
  Returns generation metrics dataframe.
146
152
  """
147
153
  df_merged_copy = df_merged.copy()
148
- df_merged_copy[MergedColumns.JOINED_CONTEXT] = df_merged_copy[
149
- MergedColumns.CONTEXT
150
- ].apply(lambda x: "\n".join(x))
151
154
  metric_results = dict()
152
155
  for metric_bind in metric_binds:
153
- metric_results.update(
154
- metric_binds_dict[metric_bind](
156
+ if isinstance(metric_bind, InferenceMetricBind):
157
+ result = _wrapped_dataframe_inference(
158
+ df_merged=df_merged_copy,
159
+ premise_column=metric_bind.premise_column,
160
+ hypothesis_column=metric_bind.hypothesis_column,
161
+ llm=llm,
162
+ prefix=metric_bind.prefix,
163
+ premise_prefix_column=metric_bind.premise_prefix_column,
164
+ document_column=metric_bind.document_column,
165
+ max_concurrency=max_concurrency,
166
+ show_progress_bar=show_progress_bar,
167
+ )
168
+ elif isinstance(metric_bind, RefusalMetricBind):
169
+ result = _wrapped_dataframe_refusal(
155
170
  df_merged=df_merged_copy,
171
+ answer_column=metric_bind.answer_column,
156
172
  llm=llm,
173
+ prefix=metric_bind.prefix,
157
174
  max_concurrency=max_concurrency,
158
175
  show_progress_bar=show_progress_bar,
159
- auto_download_nltk=auto_download_nltk,
160
- ).to_dict(orient="series")
161
- )
176
+ )
177
+ else:
178
+ raise ValueError(f"Unknown metric bind type: {type(metric_bind)}")
179
+ metric_results.update(result.to_dict(orient="series"))
162
180
  df_metrics = pd.DataFrame(data=metric_results)
163
181
  nli_columns = [
164
182
  column for column in metric_results.keys() if column.endswith(inference_column)
@@ -180,7 +198,6 @@ def create_generation_metrics_report(
180
198
  metric_binds: List[MetricBind],
181
199
  max_concurrency: int = 8,
182
200
  show_progress_bar: bool = True,
183
- auto_download_nltk: bool = True,
184
201
  ) -> pd.DataFrame:
185
202
  """
186
203
  Calculates RAG evaluation generation metrics from input dataframes.
@@ -201,7 +218,7 @@ def create_generation_metrics_report(
201
218
  A Langchain chat model used for calculating generation metrics.
202
219
 
203
220
  metric_binds : List[MetricBind], optional, default=None
204
- A list of string constants from `aidial_rag_eval.metric_binds`
221
+ A list of metric bind instances from `aidial_rag_eval.metric_binds`
205
222
  specifying the generation metrics.
206
223
 
207
224
  max_concurrency : int, default=8
@@ -223,7 +240,6 @@ def create_generation_metrics_report(
223
240
  metric_binds,
224
241
  max_concurrency,
225
242
  show_progress_bar,
226
- auto_download_nltk,
227
243
  )
228
244
  return pd.merge(df_merged, df_metrics, left_index=True, right_index=True)
229
245
 
@@ -236,7 +252,6 @@ def create_rag_eval_metrics_report(
236
252
  metric_binds: Optional[List[MetricBind]] = None,
237
253
  max_concurrency: int = 8,
238
254
  show_progress_bar: bool = True,
239
- auto_download_nltk: bool = True,
240
255
  ) -> pd.DataFrame:
241
256
  """
242
257
  Calculates RAG evaluation metrics from input dataframes.
@@ -261,7 +276,7 @@ def create_rag_eval_metrics_report(
261
276
  A Langchain chat model used for calculating generation metrics.
262
277
 
263
278
  metric_binds : List[MetricBind], optional, default=None
264
- A list of string constants from `aidial_rag_eval.metric_binds`
279
+ A list of metric bind instances from `aidial_rag_eval.metric_binds`
265
280
  specifying the generation metrics.
266
281
 
267
282
  max_concurrency : int, default=8
@@ -287,6 +302,5 @@ def create_rag_eval_metrics_report(
287
302
  metric_binds,
288
303
  max_concurrency,
289
304
  show_progress_bar,
290
- auto_download_nltk,
291
305
  )
292
306
  return pd.concat([df_merged, retrieval_metrics, generation_metrics], axis=1)
@@ -21,7 +21,6 @@ def evaluate(
21
21
  metric_binds: Optional[List[MetricBind]] = None,
22
22
  max_concurrency: int = 8,
23
23
  show_progress_bar: bool = True,
24
- auto_download_nltk: bool = False,
25
24
  ) -> Dataset:
26
25
  """
27
26
  Calculates RAG evaluation metrics from input
@@ -83,7 +82,6 @@ def evaluate(
83
82
  metric_binds=metric_binds,
84
83
  max_concurrency=max_concurrency,
85
84
  show_progress_bar=show_progress_bar,
86
- auto_download_nltk=auto_download_nltk,
87
85
  )
88
86
  aggregated_metrics = df_final.mean(numeric_only=True)
89
87
  assert isinstance(aggregated_metrics, pd.Series)
@@ -30,13 +30,15 @@ from aidial_rag_eval.types import Documents, Question
30
30
 
31
31
  T = TypeVar("T")
32
32
 
33
+ _LIST_DELIMITER = "\n"
34
+
33
35
 
34
36
  def _join_documents(documents: Documents) -> JoinedDocumentsName:
35
37
  return " ; ".join(documents)
36
38
 
37
39
 
38
40
  def _make_inference_task_inputs(
39
- premises: List[Premise],
41
+ adjusted_premises: List[str],
40
42
  statements: List[Union[HypothesisStatements, ErrorInfo]],
41
43
  document_names: List[JoinedDocumentsName],
42
44
  ) -> List[InferenceInputs]:
@@ -45,7 +47,7 @@ def _make_inference_task_inputs(
45
47
 
46
48
  Parameters
47
49
  -----------
48
- premises : List[str]
50
+ adjusted_premises : List[str]
49
51
  A list of premises from which we want to derive hypotheses in pairs.
50
52
 
51
53
  statements : List[Union[HypothesisStatements, ErrorInfo]]
@@ -73,7 +75,7 @@ def _make_inference_task_inputs(
73
75
  [
74
76
  InferenceInputs(
75
77
  hypothesis_id=i,
76
- premise=premises[i],
78
+ premise=adjusted_premises[i],
77
79
  statements=list_statements,
78
80
  document_name=document_names[i],
79
81
  )
@@ -83,7 +85,7 @@ def _make_inference_task_inputs(
83
85
  else [
84
86
  InferenceInputs(
85
87
  hypothesis_id=i,
86
- premise=premises[i],
88
+ premise=adjusted_premises[i],
87
89
  statements=[],
88
90
  document_name=document_names[i],
89
91
  error=statement_result,
@@ -203,7 +205,6 @@ def _segment_hypotheses(
203
205
  llm: BaseChatModel,
204
206
  max_concurrency: int = 8,
205
207
  show_progress_bar: bool = True,
206
- auto_download_nltk: bool = True,
207
208
  ) -> Tuple[List[SegmentedText], List[Union[SegmentedText, ErrorInfo]]]:
208
209
  """
209
210
  Function that segments hypotheses into hypothesis segments(roughly into
@@ -212,8 +213,9 @@ def _segment_hypotheses(
212
213
  Parameters
213
214
  -----------
214
215
 
215
- hypotheses : List[str]
216
+ hypotheses : List[Union[str, List[str]]]
216
217
  The text of the hypothesis.
218
+ Each hypothesis can be a single text or a list of text fragments.
217
219
 
218
220
  llm : BaseChatModel
219
221
  The Langchain chat model used for calculating inference.
@@ -236,7 +238,11 @@ def _segment_hypotheses(
236
238
  max_concurrency=max_concurrency,
237
239
  )
238
240
  segmented_hypotheses = [
239
- SegmentedText.from_text(text=hypothesis, auto_download_nltk=auto_download_nltk)
241
+ (
242
+ SegmentedText.from_list(hypothesis, _LIST_DELIMITER)
243
+ if not isinstance(hypothesis, str)
244
+ else SegmentedText.from_text(hypothesis)
245
+ )
240
246
  for hypothesis in hypotheses
241
247
  ]
242
248
  if show_progress_bar:
@@ -291,18 +297,17 @@ def _extract_statements(
291
297
  return extractor.extract(segmented_hypotheses, show_progress_bar)
292
298
 
293
299
 
294
- def _add_questions_to_premises(
295
- premises: List[Premise],
296
- questions: Optional[List[Question]],
297
- auto_download_nltk: bool,
298
- ) -> List[Premise]:
299
- adjusted_premises: List[Premise] = list(premises)
300
- if questions is not None:
301
- for i, question in enumerate(questions):
302
- question_split = SegmentedText.from_text(
303
- text=question, auto_download_nltk=auto_download_nltk
300
+ def _prepend_premise_prefixes(
301
+ normalized_premises: List[str],
302
+ premise_prefixes: Optional[List[Question]],
303
+ ) -> List[str]:
304
+ adjusted_premises: List[str] = list(normalized_premises)
305
+ if premise_prefixes is not None:
306
+ for i, prefix in enumerate(premise_prefixes):
307
+ prefix_split = SegmentedText.from_text(text=prefix)
308
+ adjusted_premises[i] = _LIST_DELIMITER.join(
309
+ [prefix_split.segments[-1], normalized_premises[i]]
304
310
  )
305
- adjusted_premises[i] = question_split.segments[-1] + "\n" + premises[i]
306
311
  return adjusted_premises
307
312
 
308
313
 
@@ -310,11 +315,10 @@ def _infer_statements(
310
315
  premises: List[Premise],
311
316
  statements: List[Union[HypothesisStatements, ErrorInfo]],
312
317
  llm: BaseChatModel,
313
- questions: Optional[List[Question]] = None,
318
+ premise_prefixes: Optional[List[Question]] = None,
314
319
  list_documents: Optional[List[Documents]] = None,
315
320
  max_concurrency: int = 8,
316
321
  show_progress_bar: bool = True,
317
- auto_download_nltk: bool = True,
318
322
  ) -> List[List[Tuple[InferenceInputs, InferenceScore]]]:
319
323
  """
320
324
  Function that infers statements.
@@ -325,8 +329,9 @@ def _infer_statements(
325
329
  Parameters
326
330
  -----------
327
331
 
328
- premises : List[str]
332
+ premises : List[Union[str, List[str]]]
329
333
  The text of the premise from which the hypothesis will be inferred.
334
+ Each premise can be a single text or a list of text fragments.
330
335
 
331
336
  statements : List[Union[HypothesisStatements, ErrorInfo]]
332
337
  A deeply nested list of statements, where the outermost
@@ -358,9 +363,10 @@ def _infer_statements(
358
363
  For items that failed in any stage, InferenceScore will have inference=None
359
364
  and the error field set.
360
365
  """
361
- adjusted_premises = _add_questions_to_premises(
362
- premises, questions, auto_download_nltk
363
- )
366
+ normalized_premises: List[str] = [
367
+ _LIST_DELIMITER.join(p) if not isinstance(p, str) else p for p in premises
368
+ ]
369
+ adjusted_premises = _prepend_premise_prefixes(normalized_premises, premise_prefixes)
364
370
 
365
371
  document_names: List[JoinedDocumentsName] = (
366
372
  [""] * len(statements)
@@ -391,14 +397,12 @@ def segment_hypotheses(
391
397
  llm: BaseChatModel,
392
398
  max_concurrency: int = 8,
393
399
  show_progress_bar: bool = True,
394
- auto_download_nltk: bool = True,
395
400
  ) -> List[Union[SegmentedText, ErrorInfo]]:
396
401
  return _segment_hypotheses(
397
402
  hypotheses=hypotheses,
398
403
  llm=llm,
399
404
  max_concurrency=max_concurrency,
400
405
  show_progress_bar=show_progress_bar,
401
- auto_download_nltk=auto_download_nltk,
402
406
  )[1]
403
407
 
404
408
 
@@ -422,21 +426,19 @@ def infer_statements(
422
426
  premises: List[Premise],
423
427
  statements: List[HypothesisStatements],
424
428
  llm: BaseChatModel,
425
- questions: Optional[List[Question]] = None,
429
+ premise_prefixes: Optional[List[Question]] = None,
426
430
  list_documents: Optional[List[Documents]] = None,
427
431
  max_concurrency: int = 8,
428
432
  show_progress_bar: bool = True,
429
- auto_download_nltk: bool = True,
430
433
  ) -> List[List[Tuple[InferenceInputs, InferenceScore]]]:
431
434
  return _infer_statements(
432
435
  premises=premises,
433
436
  statements=cast(List[Union[HypothesisStatements, ErrorInfo]], statements),
434
437
  llm=llm,
435
- questions=questions,
438
+ premise_prefixes=premise_prefixes,
436
439
  list_documents=list_documents,
437
440
  max_concurrency=max_concurrency,
438
441
  show_progress_bar=show_progress_bar,
439
- auto_download_nltk=auto_download_nltk,
440
442
  )
441
443
 
442
444
 
@@ -480,11 +482,10 @@ def calculate_batch_inference(
480
482
  premises: List[Premise],
481
483
  hypotheses: List[Hypothesis],
482
484
  llm: BaseChatModel,
483
- questions: Optional[List[Question]] = None,
485
+ premise_prefixes: Optional[List[Question]] = None,
484
486
  list_documents: Optional[List[Documents]] = None,
485
487
  max_concurrency: int = 8,
486
488
  show_progress_bar: bool = True,
487
- auto_download_nltk: bool = True,
488
489
  ) -> List[InferenceReturn]:
489
490
  """
490
491
  Calculates pairwise the inference of a hypotheses from a premises.
@@ -492,11 +493,13 @@ def calculate_batch_inference(
492
493
  Parameters
493
494
  -----------
494
495
 
495
- premises : List[str]
496
+ premises : List[Union[str, List[str]]]
496
497
  The text of the premise from which the hypothesis will be inferred.
498
+ Each premise can be a single text or a list of text fragments.
497
499
 
498
- hypotheses : List[str]
500
+ hypotheses : List[Union[str, List[str]]]
499
501
  The text of the hypothesis.
502
+ Each hypothesis can be a single text or a list of text fragments.
500
503
 
501
504
  llm : BaseChatModel
502
505
  The Langchain chat model used for calculating inference.
@@ -530,7 +533,6 @@ def calculate_batch_inference(
530
533
  llm=llm,
531
534
  max_concurrency=max_concurrency,
532
535
  show_progress_bar=show_progress_bar,
533
- auto_download_nltk=auto_download_nltk,
534
536
  )
535
537
  statements: List[Union[HypothesisStatements, ErrorInfo]] = _extract_statements(
536
538
  segmented_hypotheses=decontextualized_segmented_hypotheses,
@@ -543,11 +545,10 @@ def calculate_batch_inference(
543
545
  premises=premises,
544
546
  statements=statements,
545
547
  llm=llm,
546
- questions=questions,
548
+ premise_prefixes=premise_prefixes,
547
549
  list_documents=list_documents,
548
550
  max_concurrency=max_concurrency,
549
551
  show_progress_bar=show_progress_bar,
550
- auto_download_nltk=auto_download_nltk,
551
552
  )
552
553
  )
553
554
 
@@ -581,11 +582,10 @@ def calculate_inference(
581
582
  premise: Premise,
582
583
  hypothesis: Hypothesis,
583
584
  llm: BaseChatModel,
584
- question: Optional[Question] = None,
585
+ premise_prefix: Optional[Question] = None,
585
586
  documents: Optional[Documents] = None,
586
587
  max_concurrency: int = 8,
587
588
  show_progress_bar: bool = True,
588
- auto_download_nltk: bool = True,
589
589
  ) -> InferenceReturn:
590
590
  """
591
591
  Calculates the inference of a hypothesis from a premise.
@@ -593,11 +593,13 @@ def calculate_inference(
593
593
  Parameters
594
594
  -----------
595
595
 
596
- premise : str
596
+ premise : Union[str, List[str]]
597
597
  The text of the premise from which the hypothesis will be inferred.
598
+ Can be a single text or a list of text fragments.
598
599
 
599
- hypothesis : str
600
+ hypothesis : Union[str, List[str]]
600
601
  The text of the hypothesis.
602
+ Can be a single text or a list of text fragments.
601
603
 
602
604
  llm : BaseChatModel
603
605
  The Langchain chat model used for calculating inference.
@@ -621,16 +623,15 @@ def calculate_inference(
621
623
  along with a JSON string that explains how the inference was derived and
622
624
  highlights string used for highlighting each segment of the hypothesis.
623
625
  """
624
- questions = None if question is None else [question]
626
+ premise_prefixes = None if premise_prefix is None else [premise_prefix]
625
627
  list_documents = None if documents is None else [documents]
626
628
  inference_returns = calculate_batch_inference(
627
629
  premises=[premise],
628
630
  hypotheses=[hypothesis],
629
631
  llm=llm,
630
- questions=questions,
632
+ premise_prefixes=premise_prefixes,
631
633
  list_documents=list_documents,
632
634
  max_concurrency=max_concurrency,
633
635
  show_progress_bar=show_progress_bar,
634
- auto_download_nltk=auto_download_nltk,
635
636
  )
636
637
  return inference_returns[0]