AutoRAG 0.0.0__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.
Files changed (184) hide show
  1. autorag/__init__.py +82 -0
  2. autorag/chunker.py +51 -0
  3. autorag/cli.py +209 -0
  4. autorag/dashboard.py +199 -0
  5. autorag/data/__init__.py +109 -0
  6. autorag/data/chunk/__init__.py +2 -0
  7. autorag/data/chunk/base.py +128 -0
  8. autorag/data/chunk/langchain_chunk.py +76 -0
  9. autorag/data/chunk/llama_index_chunk.py +96 -0
  10. autorag/data/chunk/run.py +38 -0
  11. autorag/data/legacy/__init__.py +0 -0
  12. autorag/data/legacy/corpus/__init__.py +2 -0
  13. autorag/data/legacy/corpus/langchain.py +47 -0
  14. autorag/data/legacy/corpus/llama_index.py +93 -0
  15. autorag/data/legacy/qacreation/__init__.py +6 -0
  16. autorag/data/legacy/qacreation/base.py +239 -0
  17. autorag/data/legacy/qacreation/llama_index.py +253 -0
  18. autorag/data/legacy/qacreation/llama_index_default_prompt.txt +54 -0
  19. autorag/data/legacy/qacreation/ragas.py +75 -0
  20. autorag/data/legacy/qacreation/simple.py +99 -0
  21. autorag/data/parse/__init__.py +1 -0
  22. autorag/data/parse/base.py +79 -0
  23. autorag/data/parse/clova.py +194 -0
  24. autorag/data/parse/langchain_parse.py +87 -0
  25. autorag/data/parse/llamaparse.py +126 -0
  26. autorag/data/parse/run.py +141 -0
  27. autorag/data/parse/table_hybrid_parse.py +134 -0
  28. autorag/data/qa/__init__.py +3 -0
  29. autorag/data/qa/evolve/__init__.py +0 -0
  30. autorag/data/qa/evolve/llama_index_query_evolve.py +64 -0
  31. autorag/data/qa/evolve/openai_query_evolve.py +81 -0
  32. autorag/data/qa/evolve/prompt.py +288 -0
  33. autorag/data/qa/extract_evidence.py +1 -0
  34. autorag/data/qa/filter/__init__.py +0 -0
  35. autorag/data/qa/filter/dontknow.py +117 -0
  36. autorag/data/qa/filter/passage_dependency.py +88 -0
  37. autorag/data/qa/filter/prompt.py +73 -0
  38. autorag/data/qa/generation_gt/__init__.py +0 -0
  39. autorag/data/qa/generation_gt/base.py +16 -0
  40. autorag/data/qa/generation_gt/llama_index_gen_gt.py +41 -0
  41. autorag/data/qa/generation_gt/openai_gen_gt.py +84 -0
  42. autorag/data/qa/generation_gt/prompt.py +27 -0
  43. autorag/data/qa/query/__init__.py +0 -0
  44. autorag/data/qa/query/llama_gen_query.py +82 -0
  45. autorag/data/qa/query/openai_gen_query.py +95 -0
  46. autorag/data/qa/query/prompt.py +201 -0
  47. autorag/data/qa/sample.py +26 -0
  48. autorag/data/qa/schema.py +322 -0
  49. autorag/data/utils/__init__.py +0 -0
  50. autorag/data/utils/util.py +103 -0
  51. autorag/deploy/__init__.py +9 -0
  52. autorag/deploy/api.py +303 -0
  53. autorag/deploy/base.py +235 -0
  54. autorag/deploy/gradio.py +74 -0
  55. autorag/deploy/swagger.yml +202 -0
  56. autorag/embedding/__init__.py +0 -0
  57. autorag/embedding/base.py +144 -0
  58. autorag/embedding/vllm.py +256 -0
  59. autorag/evaluation/__init__.py +3 -0
  60. autorag/evaluation/generation.py +88 -0
  61. autorag/evaluation/metric/__init__.py +22 -0
  62. autorag/evaluation/metric/deepeval_prompt.py +322 -0
  63. autorag/evaluation/metric/g_eval_prompts/coh_detailed.txt +32 -0
  64. autorag/evaluation/metric/g_eval_prompts/con_detailed.txt +33 -0
  65. autorag/evaluation/metric/g_eval_prompts/flu_detailed.txt +26 -0
  66. autorag/evaluation/metric/g_eval_prompts/rel_detailed.txt +33 -0
  67. autorag/evaluation/metric/generation.py +504 -0
  68. autorag/evaluation/metric/retrieval.py +115 -0
  69. autorag/evaluation/metric/retrieval_contents.py +65 -0
  70. autorag/evaluation/metric/util.py +88 -0
  71. autorag/evaluation/retrieval.py +83 -0
  72. autorag/evaluation/retrieval_contents.py +65 -0
  73. autorag/evaluation/util.py +43 -0
  74. autorag/evaluator.py +559 -0
  75. autorag/node_line.py +65 -0
  76. autorag/nodes/__init__.py +0 -0
  77. autorag/nodes/generator/__init__.py +4 -0
  78. autorag/nodes/generator/base.py +103 -0
  79. autorag/nodes/generator/llama_index_llm.py +169 -0
  80. autorag/nodes/generator/openai_llm.py +329 -0
  81. autorag/nodes/generator/run.py +148 -0
  82. autorag/nodes/generator/vllm.py +147 -0
  83. autorag/nodes/generator/vllm_api.py +191 -0
  84. autorag/nodes/hybridretrieval/__init__.py +2 -0
  85. autorag/nodes/hybridretrieval/base.py +58 -0
  86. autorag/nodes/hybridretrieval/hybrid_cc.py +227 -0
  87. autorag/nodes/hybridretrieval/hybrid_rrf.py +149 -0
  88. autorag/nodes/hybridretrieval/run.py +137 -0
  89. autorag/nodes/lexicalretrieval/__init__.py +1 -0
  90. autorag/nodes/lexicalretrieval/bm25.py +381 -0
  91. autorag/nodes/lexicalretrieval/run.py +148 -0
  92. autorag/nodes/passageaugmenter/__init__.py +2 -0
  93. autorag/nodes/passageaugmenter/base.py +76 -0
  94. autorag/nodes/passageaugmenter/pass_passage_augmenter.py +43 -0
  95. autorag/nodes/passageaugmenter/prev_next_augmenter.py +155 -0
  96. autorag/nodes/passageaugmenter/run.py +131 -0
  97. autorag/nodes/passagecompressor/__init__.py +4 -0
  98. autorag/nodes/passagecompressor/base.py +78 -0
  99. autorag/nodes/passagecompressor/longllmlingua.py +115 -0
  100. autorag/nodes/passagecompressor/pass_compressor.py +16 -0
  101. autorag/nodes/passagecompressor/refine.py +54 -0
  102. autorag/nodes/passagecompressor/run.py +186 -0
  103. autorag/nodes/passagecompressor/tree_summarize.py +56 -0
  104. autorag/nodes/passagefilter/__init__.py +6 -0
  105. autorag/nodes/passagefilter/base.py +40 -0
  106. autorag/nodes/passagefilter/pass_passage_filter.py +14 -0
  107. autorag/nodes/passagefilter/percentile_cutoff.py +58 -0
  108. autorag/nodes/passagefilter/recency.py +105 -0
  109. autorag/nodes/passagefilter/run.py +138 -0
  110. autorag/nodes/passagefilter/similarity_percentile_cutoff.py +134 -0
  111. autorag/nodes/passagefilter/similarity_threshold_cutoff.py +112 -0
  112. autorag/nodes/passagefilter/threshold_cutoff.py +78 -0
  113. autorag/nodes/passagereranker/__init__.py +16 -0
  114. autorag/nodes/passagereranker/base.py +44 -0
  115. autorag/nodes/passagereranker/cohere.py +118 -0
  116. autorag/nodes/passagereranker/colbert.py +213 -0
  117. autorag/nodes/passagereranker/flag_embedding.py +112 -0
  118. autorag/nodes/passagereranker/flag_embedding_llm.py +101 -0
  119. autorag/nodes/passagereranker/flashrank.py +245 -0
  120. autorag/nodes/passagereranker/jina.py +115 -0
  121. autorag/nodes/passagereranker/koreranker.py +136 -0
  122. autorag/nodes/passagereranker/mixedbreadai.py +126 -0
  123. autorag/nodes/passagereranker/monot5.py +190 -0
  124. autorag/nodes/passagereranker/openvino.py +191 -0
  125. autorag/nodes/passagereranker/pass_reranker.py +31 -0
  126. autorag/nodes/passagereranker/rankgpt.py +170 -0
  127. autorag/nodes/passagereranker/run.py +145 -0
  128. autorag/nodes/passagereranker/sentence_transformer.py +129 -0
  129. autorag/nodes/passagereranker/tart/__init__.py +1 -0
  130. autorag/nodes/passagereranker/tart/modeling_enc_t5.py +152 -0
  131. autorag/nodes/passagereranker/tart/tart.py +139 -0
  132. autorag/nodes/passagereranker/tart/tokenization_enc_t5.py +112 -0
  133. autorag/nodes/passagereranker/time_reranker.py +72 -0
  134. autorag/nodes/passagereranker/upr.py +160 -0
  135. autorag/nodes/passagereranker/voyageai.py +109 -0
  136. autorag/nodes/promptmaker/__init__.py +12 -0
  137. autorag/nodes/promptmaker/base.py +32 -0
  138. autorag/nodes/promptmaker/chat_fstring.py +73 -0
  139. autorag/nodes/promptmaker/fstring.py +49 -0
  140. autorag/nodes/promptmaker/long_context_reorder.py +83 -0
  141. autorag/nodes/promptmaker/run.py +283 -0
  142. autorag/nodes/promptmaker/window_replacement.py +85 -0
  143. autorag/nodes/queryexpansion/__init__.py +4 -0
  144. autorag/nodes/queryexpansion/base.py +62 -0
  145. autorag/nodes/queryexpansion/hyde.py +43 -0
  146. autorag/nodes/queryexpansion/multi_query_expansion.py +57 -0
  147. autorag/nodes/queryexpansion/pass_query_expansion.py +22 -0
  148. autorag/nodes/queryexpansion/query_decompose.py +111 -0
  149. autorag/nodes/queryexpansion/run.py +308 -0
  150. autorag/nodes/retrieval/__init__.py +0 -0
  151. autorag/nodes/retrieval/base.py +127 -0
  152. autorag/nodes/retrieval/run_util.py +152 -0
  153. autorag/nodes/semanticretrieval/__init__.py +1 -0
  154. autorag/nodes/semanticretrieval/run.py +148 -0
  155. autorag/nodes/semanticretrieval/vectordb.py +339 -0
  156. autorag/nodes/util.py +16 -0
  157. autorag/parser.py +37 -0
  158. autorag/schema/__init__.py +3 -0
  159. autorag/schema/base.py +35 -0
  160. autorag/schema/metricinput.py +99 -0
  161. autorag/schema/module.py +24 -0
  162. autorag/schema/node.py +144 -0
  163. autorag/strategy.py +165 -0
  164. autorag/support.py +235 -0
  165. autorag/utils/__init__.py +8 -0
  166. autorag/utils/cast.py +45 -0
  167. autorag/utils/preprocess.py +149 -0
  168. autorag/utils/util.py +759 -0
  169. autorag/validator.py +98 -0
  170. autorag/vectordb/__init__.py +75 -0
  171. autorag/vectordb/base.py +73 -0
  172. autorag/vectordb/chroma.py +118 -0
  173. autorag/vectordb/couchbase.py +239 -0
  174. autorag/vectordb/milvus.py +169 -0
  175. autorag/vectordb/pinecone.py +121 -0
  176. autorag/vectordb/qdrant.py +155 -0
  177. autorag/vectordb/weaviate.py +184 -0
  178. autorag/web.py +81 -0
  179. autorag-0.0.0.dist-info/METADATA +780 -0
  180. autorag-0.0.0.dist-info/RECORD +184 -0
  181. autorag-0.0.0.dist-info/WHEEL +5 -0
  182. autorag-0.0.0.dist-info/entry_points.txt +2 -0
  183. autorag-0.0.0.dist-info/licenses/LICENSE +201 -0
  184. autorag-0.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,128 @@
1
+ import functools
2
+ import logging
3
+ from typing import Tuple, List, Dict, Any
4
+
5
+ import pandas as pd
6
+
7
+ from autorag.embedding.base import EmbeddingModel
8
+ from autorag.data import chunk_modules, sentence_splitter_modules
9
+ from autorag.utils import result_to_dataframe
10
+
11
+ logger = logging.getLogger("AutoRAG")
12
+
13
+
14
+ def chunker_node(func):
15
+ @functools.wraps(func)
16
+ @result_to_dataframe(["doc_id", "contents", "path", "start_end_idx", "metadata"])
17
+ def wrapper(
18
+ parsed_result: pd.DataFrame, chunk_method: str, **kwargs
19
+ ) -> Tuple[
20
+ List[str], List[str], List[str], List[Tuple[int, int]], List[Dict[str, Any]]
21
+ ]:
22
+ logger.info(f"Running chunker - {func.__name__} module...")
23
+
24
+ # get texts from parsed_result
25
+ texts = parsed_result["texts"].tolist()
26
+
27
+ # get filenames from parsed_result when 'add_file_name' is setting
28
+ file_name_language = kwargs.pop("add_file_name", None)
29
+ metadata_list = make_metadata_list(parsed_result)
30
+
31
+ # run chunk module
32
+ if func.__name__ in ["llama_index_chunk", "langchain_chunk"]:
33
+ chunk_instance = __get_chunk_instance(
34
+ func.__name__, chunk_method.lower(), **kwargs
35
+ )
36
+ result = func(
37
+ texts=texts,
38
+ chunker=chunk_instance,
39
+ file_name_language=file_name_language,
40
+ metadata_list=metadata_list,
41
+ )
42
+ del chunk_instance
43
+ return result
44
+ else:
45
+ raise ValueError(f"Unsupported module_type: {func.__name__}")
46
+
47
+ return wrapper
48
+
49
+
50
+ def make_metadata_list(parsed_result: pd.DataFrame) -> List[Dict[str, str]]:
51
+ metadata_list = [{} for _ in range(len(parsed_result["texts"]))]
52
+
53
+ def _make_metadata_pure(
54
+ lst: List[str], key: str, metadata_lst: List[Dict[str, str]]
55
+ ):
56
+ for value, metadata in zip(lst, metadata_lst):
57
+ metadata[key] = value
58
+
59
+ for column in ["page", "last_modified_datetime", "path"]:
60
+ if column in parsed_result.columns:
61
+ _make_metadata_pure(parsed_result[column].tolist(), column, metadata_list)
62
+ return metadata_list
63
+
64
+
65
+ def __get_chunk_instance(module_type: str, chunk_method: str, **kwargs):
66
+ # Add sentence_splitter to kwargs
67
+ sentence_available_methods = [
68
+ "semantic_llama_index",
69
+ "semanticdoublemerging",
70
+ "sentencewindow",
71
+ ]
72
+ if chunk_method in sentence_available_methods:
73
+ # llama index default sentence_splitter is 'nltk -PunktSentenceTokenizer'
74
+ if "sentence_splitter" in kwargs.keys():
75
+ sentence_splitter_str = kwargs.pop("sentence_splitter")
76
+ sentence_splitter_func = sentence_splitter_modules[sentence_splitter_str]()
77
+ kwargs.update({"sentence_splitter": sentence_splitter_func})
78
+
79
+ def get_embedding_model(_embed_model_str: str, _module_type: str):
80
+ if _embed_model_str == "openai":
81
+ if _module_type == "langchain_chunk":
82
+ _embed_model_str = "openai_langchain"
83
+ return EmbeddingModel.load(_embed_model_str)()
84
+
85
+ # Add embed_model to kwargs
86
+ embedding_available_methods = ["semantic_llama_index", "semantic_langchain"]
87
+ if chunk_method in embedding_available_methods:
88
+ # there is no default embed_model, so we have to get it parameter and add it.
89
+ if "embed_model" not in kwargs.keys():
90
+ raise ValueError(f"embed_model is required for {chunk_method} method.")
91
+ embed_model_str = kwargs.pop("embed_model")
92
+ embed_model = get_embedding_model(embed_model_str, module_type)
93
+ if chunk_method == "semantic_llama_index":
94
+ kwargs.update({"embed_model": embed_model})
95
+ elif chunk_method == "semantic_langchain":
96
+ kwargs.update({"embeddings": embed_model})
97
+
98
+ return chunk_modules[chunk_method](**kwargs)
99
+
100
+
101
+ def add_file_name(
102
+ file_name_language: str, file_names: List[str], chunk_texts: List[str]
103
+ ) -> List[str]:
104
+ if file_name_language == "en":
105
+ return list(
106
+ map(
107
+ lambda x: f"file_name: {x[1]}\n contents: {x[0]}",
108
+ zip(chunk_texts, file_names),
109
+ )
110
+ )
111
+ elif file_name_language == "ko":
112
+ return list(
113
+ map(
114
+ lambda x: f"파일 제목: {x[1]}\n 내용: {x[0]}",
115
+ zip(chunk_texts, file_names),
116
+ )
117
+ )
118
+ elif file_name_language == "ja":
119
+ return list(
120
+ map(
121
+ lambda x: f"ファイル名: {x[1]}\n 内容: {x[0]}",
122
+ zip(chunk_texts, file_names),
123
+ )
124
+ )
125
+ else:
126
+ raise ValueError(
127
+ f"Unsupported file_name_language: {file_name_language}. Choose from 'en' ,'ko' or 'ja."
128
+ )
@@ -0,0 +1,76 @@
1
+ import os
2
+ from itertools import chain
3
+ import uuid
4
+ from typing import Tuple, List, Dict, Any, Optional
5
+
6
+ from langchain_text_splitters import TextSplitter
7
+
8
+ from autorag.data.chunk.base import chunker_node, add_file_name
9
+ from autorag.data.utils.util import add_essential_metadata, get_start_end_idx
10
+
11
+
12
+ @chunker_node
13
+ def langchain_chunk(
14
+ texts: List[str],
15
+ chunker: TextSplitter,
16
+ file_name_language: Optional[str] = None,
17
+ metadata_list: Optional[List[Dict[str, str]]] = None,
18
+ ) -> Tuple[
19
+ List[str], List[str], List[str], List[Tuple[int, int]], List[Dict[str, Any]]
20
+ ]:
21
+ """
22
+ Chunk texts from the parsed result to use langchain chunk method
23
+
24
+ :param texts: The list of texts to chunk from the parsed result
25
+ :param chunker: A langchain TextSplitter(Chunker) instance.
26
+ :param file_name_language: The language to use 'add_file_name' feature.
27
+ You need to set one of 'English' and 'Korean'
28
+ The 'add_file_name' feature is to add a file_name to chunked_contents.
29
+ This is used to prevent hallucination by retrieving contents from the wrong document.
30
+ Default form of 'English' is "file_name: {file_name}\n contents: {content}"
31
+ :param metadata_list: The list of dict of metadata from the parsed result
32
+ :return: tuple of lists containing the chunked doc_id, contents, path, start_idx, end_idx and metadata
33
+ """
34
+ results = [
35
+ langchain_chunk_pure(text, chunker, file_name_language, meta)
36
+ for text, meta in zip(texts, metadata_list)
37
+ ]
38
+
39
+ doc_id, contents, path, start_end_idx, metadata = (
40
+ list(chain.from_iterable(item)) for item in zip(*results)
41
+ )
42
+
43
+ return doc_id, contents, path, start_end_idx, metadata
44
+
45
+
46
+ def langchain_chunk_pure(
47
+ text: str,
48
+ chunker: TextSplitter,
49
+ file_name_language: Optional[str] = None,
50
+ _metadata: Optional[Dict[str, str]] = None,
51
+ ):
52
+ # chunk
53
+ chunk_results = chunker.create_documents([text], metadatas=[_metadata])
54
+
55
+ # make doc_id
56
+ doc_id = list(str(uuid.uuid4()) for _ in range(len(chunk_results)))
57
+
58
+ # make path
59
+ path_lst = list(map(lambda x: x.metadata.get("path", ""), chunk_results))
60
+
61
+ # make contents and start_end_idx
62
+ if file_name_language:
63
+ chunked_file_names = list(map(lambda x: os.path.basename(x), path_lst))
64
+ chunked_texts = list(map(lambda x: x.page_content, chunk_results))
65
+ start_end_idx = list(map(lambda x: get_start_end_idx(text, x), chunked_texts))
66
+ contents = add_file_name(file_name_language, chunked_file_names, chunked_texts)
67
+ else:
68
+ contents = list(map(lambda node: node.page_content, chunk_results))
69
+ start_end_idx = list(map(lambda x: get_start_end_idx(text, x), contents))
70
+
71
+ # make metadata
72
+ metadata = list(
73
+ map(lambda node: add_essential_metadata(node.metadata), chunk_results)
74
+ )
75
+
76
+ return doc_id, contents, path_lst, start_end_idx, metadata
@@ -0,0 +1,96 @@
1
+ import os.path
2
+ from itertools import chain
3
+ from typing import Tuple, List, Dict, Any, Optional
4
+
5
+ from llama_index.core import Document
6
+ from llama_index.core.node_parser.interface import NodeParser
7
+
8
+ from autorag.utils.util import process_batch, get_event_loop
9
+ from autorag.data.chunk.base import chunker_node, add_file_name
10
+ from autorag.data.utils.util import (
11
+ add_essential_metadata_llama_text_node,
12
+ get_start_end_idx,
13
+ )
14
+
15
+
16
+ @chunker_node
17
+ def llama_index_chunk(
18
+ texts: List[str],
19
+ chunker: NodeParser,
20
+ file_name_language: Optional[str] = None,
21
+ metadata_list: Optional[List[Dict[str, str]]] = None,
22
+ batch: int = 8,
23
+ ) -> Tuple[
24
+ List[str], List[str], List[str], List[Tuple[int, int]], List[Dict[str, Any]]
25
+ ]:
26
+ """
27
+ Chunk texts from the parsed result to use llama index chunk method
28
+
29
+ :param texts: The list of texts to chunk from the parsed result
30
+ :param chunker: A llama index NodeParser(Chunker) instance.
31
+ :param file_name_language: The language to use 'add_file_name' feature.
32
+ You need to set one of 'English' and 'Korean'
33
+ The 'add_file_name' feature is to add a file_name to chunked_contents.
34
+ This is used to prevent hallucination by retrieving contents from the wrong document.
35
+ Default form of 'English' is "file_name: {file_name}\n contents: {content}"
36
+ :param metadata_list: The list of dict of metadata from the parsed result
37
+ :param batch: The batch size for chunk texts. Default is 8
38
+ :return: tuple of lists containing the chunked doc_id, contents, path, start_idx, end_idx and metadata
39
+ """
40
+ tasks = [
41
+ llama_index_chunk_pure(text, chunker, file_name_language, meta)
42
+ for text, meta in zip(texts, metadata_list)
43
+ ]
44
+ loop = get_event_loop()
45
+ results = loop.run_until_complete(process_batch(tasks, batch))
46
+
47
+ doc_id, contents, path, start_end_idx, metadata = (
48
+ list(chain.from_iterable(item)) for item in zip(*results)
49
+ )
50
+
51
+ return list(doc_id), list(contents), list(path), list(start_end_idx), list(metadata)
52
+
53
+
54
+ async def llama_index_chunk_pure(
55
+ text: str,
56
+ chunker: NodeParser,
57
+ file_name_language: Optional[str] = None,
58
+ _metadata: Optional[Dict[str, str]] = None,
59
+ ):
60
+ # set document
61
+ document = [Document(text=text, metadata=_metadata)]
62
+
63
+ # chunk document
64
+ chunk_results = await chunker.aget_nodes_from_documents(documents=document)
65
+
66
+ # make doc_id
67
+ doc_id = list(map(lambda node: node.node_id, chunk_results))
68
+
69
+ # make path
70
+ path_lst = list(map(lambda x: x.metadata.get("path", ""), chunk_results))
71
+
72
+ # make contents and start_end_idx
73
+ if file_name_language:
74
+ chunked_file_names = list(map(lambda x: os.path.basename(x), path_lst))
75
+ chunked_texts = list(map(lambda x: x.text, chunk_results))
76
+ start_end_idx = list(
77
+ map(
78
+ lambda x: get_start_end_idx(text, x),
79
+ chunked_texts,
80
+ )
81
+ )
82
+ contents = add_file_name(file_name_language, chunked_file_names, chunked_texts)
83
+ else:
84
+ contents = list(map(lambda x: x.text, chunk_results))
85
+ start_end_idx = list(map(lambda x: get_start_end_idx(text, x), contents))
86
+
87
+ metadata = list(
88
+ map(
89
+ lambda node: add_essential_metadata_llama_text_node(
90
+ node.metadata, node.relationships
91
+ ),
92
+ chunk_results,
93
+ )
94
+ )
95
+
96
+ return doc_id, contents, path_lst, start_end_idx, metadata
@@ -0,0 +1,38 @@
1
+ import os
2
+ from typing import Callable, List, Dict
3
+ import pandas as pd
4
+
5
+ from autorag.strategy import measure_speed
6
+
7
+
8
+ def run_chunker(
9
+ modules: List[Callable],
10
+ module_params: List[Dict],
11
+ parsed_result: pd.DataFrame,
12
+ project_dir: str,
13
+ ):
14
+ results, execution_times = zip(
15
+ *map(
16
+ lambda x: measure_speed(x[0], parsed_result=parsed_result, **x[1]),
17
+ zip(modules, module_params),
18
+ )
19
+ )
20
+ average_times = list(map(lambda x: x / len(results[0]), execution_times))
21
+
22
+ # save results to parquet files
23
+ filepaths = list(
24
+ map(lambda x: os.path.join(project_dir, f"{x}.parquet"), range(len(modules)))
25
+ )
26
+ list(map(lambda x: x[0].to_parquet(x[1], index=False), zip(results, filepaths)))
27
+ filenames = list(map(lambda x: os.path.basename(x), filepaths))
28
+
29
+ summary_df = pd.DataFrame(
30
+ {
31
+ "filename": filenames,
32
+ "module_name": list(map(lambda module: module.__name__, modules)),
33
+ "module_params": module_params,
34
+ "execution_time": average_times,
35
+ }
36
+ )
37
+ summary_df.to_csv(os.path.join(project_dir, "summary.csv"), index=False)
38
+ return summary_df
File without changes
@@ -0,0 +1,2 @@
1
+ from .langchain import langchain_documents_to_parquet
2
+ from .llama_index import llama_documents_to_parquet, llama_text_node_to_parquet
@@ -0,0 +1,47 @@
1
+ import uuid
2
+ from typing import List, Optional
3
+
4
+ import pandas as pd
5
+ from langchain_core.documents import Document
6
+
7
+ from autorag.data.utils.util import add_essential_metadata
8
+ from autorag.utils.util import save_parquet_safe
9
+
10
+
11
+ def langchain_documents_to_parquet(
12
+ langchain_documents: List[Document],
13
+ output_filepath: Optional[str] = None,
14
+ upsert: bool = False,
15
+ ) -> pd.DataFrame:
16
+ """
17
+ Langchain documents to corpus dataframe.
18
+ Corpus dataframe will be saved to filepath(file_dir/filename) if given.
19
+ Return corpus dataframe whether the filepath is given.
20
+ You can use this method to create corpus.parquet after load and chunk using Llama Index.
21
+
22
+ :param langchain_documents: List of langchain documents.
23
+ :param output_filepath: Optional filepath to save the parquet file.
24
+ If None, the function will return the processed_data as pd.DataFrame, but do not save as parquet.
25
+ File directory must exist. File extension must be .parquet
26
+ :param upsert: If true, the function will overwrite the existing file if it exists.
27
+ Default is False.
28
+ :return: Corpus data as pd.DataFrame
29
+ """
30
+
31
+ corpus_df = pd.DataFrame(
32
+ list(
33
+ map(
34
+ lambda doc: {
35
+ "doc_id": str(uuid.uuid4()),
36
+ "contents": doc.page_content,
37
+ "metadata": add_essential_metadata(doc.metadata),
38
+ },
39
+ langchain_documents,
40
+ )
41
+ )
42
+ )
43
+
44
+ if output_filepath is not None:
45
+ save_parquet_safe(corpus_df, output_filepath, upsert=upsert)
46
+
47
+ return corpus_df
@@ -0,0 +1,93 @@
1
+ import uuid
2
+ from typing import List, Optional
3
+
4
+ import pandas as pd
5
+ from llama_index.core import Document
6
+ from llama_index.core.schema import TextNode
7
+
8
+ from autorag.data.utils.util import (
9
+ add_essential_metadata,
10
+ add_essential_metadata_llama_text_node,
11
+ )
12
+ from autorag.utils.util import save_parquet_safe
13
+
14
+
15
+ def llama_documents_to_parquet(
16
+ llama_documents: List[Document],
17
+ output_filepath: Optional[str] = None,
18
+ upsert: bool = False,
19
+ ) -> pd.DataFrame:
20
+ """
21
+ Llama Index documents to corpus dataframe.
22
+ Corpus dataframe will be saved to filepath(file_dir/filename) if given.
23
+ Return corpus dataframe whether the filepath is given.
24
+ You can use this method to create corpus.parquet after load and chunk using Llama Index.
25
+
26
+ :param llama_documents: List[Document]
27
+ :param output_filepath: Optional filepath to save the parquet file.
28
+ If None, the function will return the processed_data as pd.DataFrame, but do not save as parquet.
29
+ File directory must exist. File extension must be .parquet
30
+ :param upsert: If true, the function will overwrite the existing file if it exists.
31
+ Default is False.
32
+ :return: Corpus data as pd.DataFrame
33
+ """
34
+
35
+ doc_lst = pd.DataFrame(
36
+ list(
37
+ map(
38
+ lambda doc: {
39
+ "doc_id": str(uuid.uuid4()),
40
+ "contents": doc.text,
41
+ "metadata": add_essential_metadata(doc.metadata),
42
+ },
43
+ llama_documents,
44
+ )
45
+ )
46
+ )
47
+
48
+ processed_df = pd.DataFrame(doc_lst)
49
+
50
+ if output_filepath is not None:
51
+ save_parquet_safe(processed_df, output_filepath, upsert=upsert)
52
+
53
+ return processed_df
54
+
55
+
56
+ def llama_text_node_to_parquet(
57
+ text_nodes: List[TextNode],
58
+ output_filepath: Optional[str] = None,
59
+ upsert: bool = False,
60
+ ) -> pd.DataFrame:
61
+ """
62
+ Llama Index text nodes to corpus dataframe.
63
+ Corpus dataframe will be saved to filepath(file_dir/filename) if given.
64
+ Return corpus dataframe whether the filepath is given.
65
+ You can use this method to create corpus.parquet after load and chunk using Llama Index.
66
+
67
+ :param text_nodes: List of llama index text nodes.
68
+ :param output_filepath: Optional filepath to save the parquet file.
69
+ If None, the function will return the processed_data as pd.DataFrame, but do not save as parquet.
70
+ File directory must exist. File extension must be .parquet
71
+ :param upsert: If true, the function will overwrite the existing file if it exists.
72
+ Default is False.
73
+ :return: Corpus data as pd.DataFrame
74
+ """
75
+ corpus_df = pd.DataFrame(
76
+ list(
77
+ map(
78
+ lambda node: {
79
+ "doc_id": node.node_id,
80
+ "contents": node.text,
81
+ "metadata": add_essential_metadata_llama_text_node(
82
+ node.metadata, node.relationships
83
+ ),
84
+ },
85
+ text_nodes,
86
+ )
87
+ )
88
+ )
89
+
90
+ if output_filepath is not None:
91
+ save_parquet_safe(corpus_df, output_filepath, upsert=upsert)
92
+
93
+ return corpus_df
@@ -0,0 +1,6 @@
1
+ from .base import make_single_content_qa, make_qa_with_existing_qa
2
+ from .llama_index import (
3
+ generate_qa_llama_index,
4
+ generate_answers,
5
+ generate_qa_llama_index_by_ratio,
6
+ )