alexneakameni commited on
Commit
50d55b1
·
verified ·
1 Parent(s): 4e88eb8

Create app from nganga-ai/dikoka repository

Browse files
Files changed (50) hide show
  1. .gitattributes +2 -0
  2. .gitignore +173 -0
  3. app.py +138 -0
  4. chroma_db/4daca867-b763-4a6b-8b5b-fdf70e3d9ead/data_level0.bin +3 -0
  5. chroma_db/4daca867-b763-4a6b-8b5b-fdf70e3d9ead/header.bin +3 -0
  6. chroma_db/4daca867-b763-4a6b-8b5b-fdf70e3d9ead/index_metadata.pickle +3 -0
  7. chroma_db/4daca867-b763-4a6b-8b5b-fdf70e3d9ead/length.bin +3 -0
  8. chroma_db/4daca867-b763-4a6b-8b5b-fdf70e3d9ead/link_lists.bin +3 -0
  9. chroma_db/chroma.sqlite3 +3 -0
  10. data/chroma_db/4daca867-b763-4a6b-8b5b-fdf70e3d9ead/data_level0.bin +3 -0
  11. data/chroma_db/4daca867-b763-4a6b-8b5b-fdf70e3d9ead/header.bin +3 -0
  12. data/chroma_db/4daca867-b763-4a6b-8b5b-fdf70e3d9ead/index_metadata.pickle +3 -0
  13. data/chroma_db/4daca867-b763-4a6b-8b5b-fdf70e3d9ead/length.bin +3 -0
  14. data/chroma_db/4daca867-b763-4a6b-8b5b-fdf70e3d9ead/link_lists.bin +3 -0
  15. data/chroma_db/chroma.sqlite3 +3 -0
  16. requirements.txt +15 -0
  17. saved_summaries/eng/final_summary_297054.txt +9 -0
  18. saved_summaries/eng/final_summary_297054_Volume_2.txt +11 -0
  19. saved_summaries/eng/level_2_chunk_0_20250202_120459.txt +7 -0
  20. saved_summaries/eng/level_2_chunk_0_20250202_123011.txt +7 -0
  21. saved_summaries/eng/level_2_chunk_1_20250202_120509.txt +7 -0
  22. saved_summaries/eng/level_2_chunk_1_20250202_123019.txt +7 -0
  23. saved_summaries/eng/level_2_chunk_2_20250202_120519.txt +7 -0
  24. saved_summaries/eng/level_2_chunk_2_20250202_123028.txt +7 -0
  25. saved_summaries/eng/level_2_chunk_3_20250202_120528.txt +7 -0
  26. saved_summaries/eng/level_2_chunk_3_20250202_123035.txt +5 -0
  27. saved_summaries/fr/final_summary_297054.txt +9 -0
  28. saved_summaries/fr/final_summary_297054_Volume_2.txt +11 -0
  29. saved_summaries/fr/level_2_chunk_0_20250202_120459.txt +7 -0
  30. saved_summaries/fr/level_2_chunk_0_20250202_123011.txt +7 -0
  31. saved_summaries/fr/level_2_chunk_1_20250202_120509.txt +7 -0
  32. saved_summaries/fr/level_2_chunk_1_20250202_123019.txt +7 -0
  33. saved_summaries/fr/level_2_chunk_2_20250202_120519.txt +7 -0
  34. saved_summaries/fr/level_2_chunk_2_20250202_123028.txt +7 -0
  35. saved_summaries/fr/level_2_chunk_3_20250202_120528.txt +7 -0
  36. saved_summaries/fr/level_2_chunk_3_20250202_123035.txt +5 -0
  37. saved_summaries/question_eng.json +0 -0
  38. saved_summaries/question_fr.json +0 -0
  39. src/__init__.py +6 -0
  40. src/database.py +20 -0
  41. src/rag_pipeline/__init__.py +0 -0
  42. src/rag_pipeline/prompts.py +71 -0
  43. src/rag_pipeline/rag_system.py +110 -0
  44. src/utilities/__init__.py +0 -0
  45. src/utilities/embedding.py +127 -0
  46. src/utilities/llm_models.py +46 -0
  47. src/vector_store/__init__.py +0 -0
  48. src/vector_store/document_loader.py +163 -0
  49. src/vector_store/prompts.py +24 -0
  50. src/vector_store/vector_store.py +115 -0
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ chroma_db/chroma.sqlite3 filter=lfs diff=lfs merge=lfs -text
37
+ data/chroma_db/chroma.sqlite3 filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py,cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ #uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ #poetry.lock
109
+
110
+ # pdm
111
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
112
+ #pdm.lock
113
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
114
+ # in version control.
115
+ # https://pdm.fming.dev/latest/usage/project/#working-with-version-control
116
+ .pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
121
+ __pypackages__/
122
+
123
+ # Celery stuff
124
+ celerybeat-schedule
125
+ celerybeat.pid
126
+
127
+ # SageMath parsed files
128
+ *.sage.py
129
+
130
+ # Environments
131
+ .env
132
+ .venv
133
+ env/
134
+ venv/
135
+ ENV/
136
+ env.bak/
137
+ venv.bak/
138
+
139
+ # Spyder project settings
140
+ .spyderproject
141
+ .spyproject
142
+
143
+ # Rope project settings
144
+ .ropeproject
145
+
146
+ # mkdocs documentation
147
+ /site
148
+
149
+ # mypy
150
+ .mypy_cache/
151
+ .dmypy.json
152
+ dmypy.json
153
+
154
+ # Pyre type checker
155
+ .pyre/
156
+
157
+ # pytype static type analyzer
158
+ .pytype/
159
+
160
+ # Cython debug symbols
161
+ cython_debug/
162
+
163
+ # PyCharm
164
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
165
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
166
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
167
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
168
+ #.idea/
169
+
170
+ # PyPI configuration file
171
+ .pypirc
172
+
173
+ *.out
app.py ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import random
3
+ from typing import List
4
+
5
+ import gradio as gr
6
+
7
+ from src.database import load_dataset, load_final_summaries, load_questions
8
+ from src.rag_pipeline.rag_system import RAGSystem
9
+
10
+ os.environ["TOKENIZERS_PARALLELISM"] = "true"
11
+
12
+
13
+ class ChatInterface:
14
+ """
15
+ A class to create and manage the chat interface for the Dikoka AI assistant.
16
+ """
17
+
18
+ def __init__(self, rag_system: RAGSystem):
19
+ """
20
+ Initialize the ChatInterface with a RAG system.
21
+ """
22
+ self.rag_system = rag_system
23
+ self.history_depth = int(os.getenv("MAX_MESSAGES") or 5) * 2
24
+ self.questions = []
25
+ self.summaries = []
26
+
27
+ def respond(self, message: str, history: List[List[str]]):
28
+ """
29
+ Generate a response to the user's message using the RAG system.
30
+ """
31
+ result = ""
32
+ history = [
33
+ (turn["role"], turn["content"]) for turn in history[-self.history_depth :]
34
+ ]
35
+ for text in self.rag_system.query(message, history):
36
+ result += text
37
+ yield result
38
+ return result
39
+
40
+ def sample_questions(self):
41
+ """
42
+ Sample a few random questions from the loaded questions.
43
+ """
44
+ random_questions = random.sample(self.questions, 3)
45
+ example_questions = "\n".join(
46
+ ["## Examples of questions"]
47
+ + [f"- {question}" for question in random_questions]
48
+ )
49
+ return example_questions
50
+
51
+ def sample_summaries(self):
52
+ """
53
+ Sample a random summary from the loaded summaries.
54
+ """
55
+ random_summary = random.choice(self.summaries)
56
+ return random_summary
57
+
58
+ def load_data(self, lang: str):
59
+ """
60
+ Load questions and summaries for the specified language.
61
+ """
62
+ self.questions = load_questions(lang)
63
+ self.summaries = load_final_summaries(lang)
64
+
65
+ def create_interface(self) -> gr.Blocks:
66
+ """
67
+ Create the Gradio interface for the chat application.
68
+ """
69
+ self.load_data("fr")
70
+
71
+ description = (
72
+ "Dikoka an AI assistant providing information on the Franco-Cameroonian Commission's"
73
+ " findings regarding France's role and engagement in Cameroon during the suppression"
74
+ " of independence and opposition movements between 1945 and 1971.\n\n"
75
+ "🌟 **Code Repository**: [Dikoka GitHub](https://github.com/Nganga-AI/dikoka)"
76
+ )
77
+
78
+ with gr.Blocks() as demo:
79
+ with gr.Row(equal_height=True):
80
+ with gr.Column():
81
+ with gr.Row():
82
+ with gr.Column():
83
+ dpd = gr.Dropdown(
84
+ choices=["fr", "eng"],
85
+ value="fr",
86
+ label="Choose language",
87
+ )
88
+ dpd.change(self.load_data, inputs=dpd)
89
+ with gr.Column(scale=2):
90
+ gr.Markdown("## Summary")
91
+ with gr.Row():
92
+ with gr.Column():
93
+ self.sample_resume = gr.Markdown(self.sample_summaries())
94
+ with gr.Row():
95
+ sample_summary = gr.Button("Sample Summary")
96
+ sample_summary.click(
97
+ fn=self.sample_summaries,
98
+ inputs=[],
99
+ outputs=self.sample_resume,
100
+ )
101
+ with gr.Column(scale=2):
102
+ gr.ChatInterface(
103
+ fn=self.respond,
104
+ type="messages",
105
+ title="Dikoka",
106
+ description=description,
107
+ )
108
+ with gr.Row():
109
+ self.example_questions = gr.Markdown(self.sample_questions())
110
+ with gr.Row():
111
+ sample_button = gr.Button("Sample New Questions")
112
+ sample_button.click(
113
+ fn=self.sample_questions,
114
+ inputs=[],
115
+ outputs=self.example_questions,
116
+ )
117
+ return demo
118
+
119
+
120
+ def get_rag_system(top_k_documents):
121
+ """
122
+ Initialize and return a RAG system with the specified number of top documents.
123
+ """
124
+ rag = RAGSystem("data/chroma_db", batch_size=64, top_k_documents=top_k_documents)
125
+ if not os.path.exists(rag.vector_store_management.persist_directory):
126
+ documents = load_dataset(os.getenv("LANG"))
127
+ rag.initialize_vector_store(documents)
128
+ return rag
129
+
130
+
131
+ # Usage example:
132
+ if __name__ == "__main__":
133
+ top_k_docs = int(os.getenv("N_CONTEXT") or 5)
134
+ rag_system = get_rag_system(top_k_documents=top_k_docs)
135
+
136
+ chat_interface = ChatInterface(rag_system)
137
+ demo = chat_interface.create_interface()
138
+ demo.launch(share=False)
chroma_db/4daca867-b763-4a6b-8b5b-fdf70e3d9ead/data_level0.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5f4de2593e1b32f66ecf2d58e107a40a949249409fd88eacce4fa6d5af28bf04
3
+ size 4656000
chroma_db/4daca867-b763-4a6b-8b5b-fdf70e3d9ead/header.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a112506f487c99e6ff26e0319a7743a8ecaecf4c640132cd07af9aff04135984
3
+ size 100
chroma_db/4daca867-b763-4a6b-8b5b-fdf70e3d9ead/index_metadata.pickle ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:aff0347f05636ae8947bb372ffe6386043ad6c35909370c9cd74ef8127acf388
3
+ size 229997
chroma_db/4daca867-b763-4a6b-8b5b-fdf70e3d9ead/length.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:be5b1c36a9a63d9cca9bbaaf700ff548646596c0951f98f35502b57333eadad7
3
+ size 16000
chroma_db/4daca867-b763-4a6b-8b5b-fdf70e3d9ead/link_lists.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:84b95327037dc7b063da5af4957a00979a0cfc710bd70372ac92f0d4004e2183
3
+ size 34836
chroma_db/chroma.sqlite3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9efbbbbc951f272bf4eb05b014fdfc281a99c1ac8ac8913cfe5b953410622c6c
3
+ size 50978816
data/chroma_db/4daca867-b763-4a6b-8b5b-fdf70e3d9ead/data_level0.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5f4de2593e1b32f66ecf2d58e107a40a949249409fd88eacce4fa6d5af28bf04
3
+ size 4656000
data/chroma_db/4daca867-b763-4a6b-8b5b-fdf70e3d9ead/header.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a112506f487c99e6ff26e0319a7743a8ecaecf4c640132cd07af9aff04135984
3
+ size 100
data/chroma_db/4daca867-b763-4a6b-8b5b-fdf70e3d9ead/index_metadata.pickle ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:aff0347f05636ae8947bb372ffe6386043ad6c35909370c9cd74ef8127acf388
3
+ size 229997
data/chroma_db/4daca867-b763-4a6b-8b5b-fdf70e3d9ead/length.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:be5b1c36a9a63d9cca9bbaaf700ff548646596c0951f98f35502b57333eadad7
3
+ size 16000
data/chroma_db/4daca867-b763-4a6b-8b5b-fdf70e3d9ead/link_lists.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:84b95327037dc7b063da5af4957a00979a0cfc710bd70372ac92f0d4004e2183
3
+ size 34836
data/chroma_db/chroma.sqlite3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9efbbbbc951f272bf4eb05b014fdfc281a99c1ac8ac8913cfe5b953410622c6c
3
+ size 50978816
requirements.txt ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ langchain-ollama==0.2.2
2
+ langchain-groq==0.2.3
3
+ langchain-community==0.3.14
4
+ langchain-chroma==0.1.4
5
+ langchain-huggingface
6
+ langchain==0.3.14
7
+ ollama==0.4.5
8
+ chromadb==0.5.23
9
+ # OCR
10
+ tqdm==4.67.1
11
+ gradio
12
+ rank_bm25==0.2.2
13
+ groq==0.15.0
14
+ tiktoken==0.8.0
15
+ einops==0.8.0
saved_summaries/eng/final_summary_297054.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ In the mid-20th century, Cameroon became a focal point for anti-colonial tensions as French authorities sought to suppress the Union des Populations du Cameroun (UPC), a key nationalist movement pushing for independence. During this period, Roland Pré, the French Haut-Commissaire, implemented strategic measures aimed at countering UPC influence amidst growing demands for autonomy. This era was marked by increased surveillance and aggressive repression, particularly in regions like Sanaga-Maritime, where leaders such as Achille Mbembe and Ernest Ouandié mobilized resistance through political and military training.
2
+
3
+ French tactics included deploying armed forces to disrupt protests and arrest demonstrators, resulting in the imprisonment of approximately 47 UPC supporters. These actions highlighted France's determination to maintain colonial control despite international decolonization pressures. Pré's approach combined administrative reforms and military measures, reflecting a broader French strategy to weaken anti-colonial movements by fostering pro-French factions and implementing decentralizing policies.
4
+
5
+ Parallel to these efforts in Cameroon, France adapted its military strategies globally through the development of "guerre révolutionnaire" or revolutionary warfare. This innovative approach emerged as conventional tactics proved inadequate against insurgencies like those in Algeria and Vietnam. Colonel Charles Lacheroy was instrumental in this strategy, which emphasized psychological operations designed to destabilize existing social orders and erode state authority, combining these with traditional military actions to gain civilian support.
6
+
7
+ These developments coincided with diplomatic efforts at the United Nations, where intense negotiations over French trusteeship agreements for Cameroon highlighted global tensions between colonial powers and emerging norms of self-governance. During the Fourth Committee sessions in December 1946, delegates criticized France's proposals for inadequately prioritizing Cameroonian interests, advocating for amendments to ensure future administrations were accountable to the UN rather than colonial authorities.
8
+
9
+ These discussions reflected a broader shift towards decolonization post-World War II, emphasizing local autonomy and international oversight. As global norms increasingly favored self-governance, these diplomatic efforts marked an important step in redefining colonial administration through legal frameworks recognizing indigenous rights and autonomy. Together, these military, political, and diplomatic dynamics illustrate the complexities of resisting colonial rule in mid-20th-century Africa and underscore the persistent struggle for Cameroon's independence within this turbulent historical context.
saved_summaries/eng/final_summary_297054_Volume_2.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ During Cameroon's transition from French colonial rule to independence between 1950s and early 1970s, several complex dynamics unfolded as both nations navigated military autonomy, control, and lingering colonial influences. In December 1960, France aimed to maintain influence over the forming Cameroonian forces through a secretive directive issued by Prime Minister Michel Debré on November 25, bypassing traditional command channels. This created friction within French military hierarchy, particularly between General Sizaire of the CIFFC and other entities, exacerbated when Sizaire learned about the instruction through delayed correspondence from Pierre Messmer in January 1961.
2
+
3
+ To address these challenges, proposals emerged for restructuring French military presence into two distinct commands: a Mixed Military Force (MMF) under the ambassador's authority and a separate Forces Françaises au Cameroun (FFC), managed by Zone Militaire n°2. This restructuring aimed to streamline operations while safeguarding France’s strategic interests as Cameroon moved towards military independence, highlighting tensions inherent in decolonization.
4
+
5
+ As Cameroon transitioned further into autonomy during the late 1960s and early 1970s, domestic unrest in France complicated bilateral relations and delayed military support initiatives pursued by President Ahmadou Ahidjo. While Cameroonian officers sought greater sovereignty and younger commanders began exercising independence from French counterparts, regional stability remained a concern. In response, Cameroon expanded its educational opportunities with nations like the USSR and Greece to reduce reliance on French training.
6
+
7
+ French influence persisted in regions such as Bamiléké, where indirect support continued through logistics and preventive measures despite ongoing tensions over control and command approaches. These dynamics underscored broader post-independence challenges, balancing aspirations for national sovereignty against enduring colonial ties.
8
+
9
+ Parallel to these military and political transitions, severe human rights abuses emerged during Cameroon's decolonization process. French-backed forces employed coercive interrogation techniques like the "kalimba" method, involving electric shocks to extract confessions under duress. Such practices were often downplayed in official reports, despite testimonies revealing widespread violence against Cameroonian political figures and continuity of colonial-era repression strategies.
10
+
11
+ This period reflects broader themes of post-independence transitions, emphasizing challenges in maintaining order while transitioning from oppressive colonial legacies. Acknowledging these historical injustices is crucial to understanding their impact on national identity formation and governance in newly independent states like Cameroon. The synthesis of military restructuring efforts, sovereignty aspirations, and human rights abuses provides a comprehensive overview of the complexities inherent in decolonization.
saved_summaries/eng/level_2_chunk_0_20250202_120459.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ In mid-1950s Cameroon, anti-colonial tensions intensified as French authorities sought to suppress the Union des Populations du Cameroun (UPC). Roland Pré, the French Haut-Commissaire, played a critical role in implementing strategies aimed at countering UPC influence amidst growing demands for independence. This period was marked by strategic confrontations and repressive measures against the UPC.
2
+
3
+ Key events included increased surveillance and aggressive repression in regions like Sanaga-Maritime, where leaders such as Achille Mbembe and Ernest Ouandié attempted to mobilize resistance through political and military training. French tactics involved deploying armed guards from Douala and Ngambè to disrupt protests and arrest demonstrators, including actions leading to the imprisonment of about 47 UPC supporters.
4
+
5
+ These incidents highlight the violent nature of the conflict and France's determination to maintain colonial control in response to international decolonization pressures. The events underscored the broader struggle for Cameroon’s independence, illustrating Pré's multifaceted approach that combined administrative reforms and military measures against the anti-colonial movement.
6
+
7
+ This summary aligns with previous discussions by emphasizing Pré's strategic efforts to dilute UPC influence through fostering pro-French factions and implementing decentralizing policies. These actions were part of a broader French colonial strategy during this turbulent period, reflecting the complexities of resisting colonial rule in mid-20th-century Africa.
saved_summaries/eng/level_2_chunk_0_20250202_123011.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ In December 1960, as France transitioned military control to Cameroon by January 1, 1961, significant challenges emerged, particularly highlighted in an "Instruction personnelle et secrète" issued on November 25 by French Prime Minister Michel Debré. This directive aimed to maintain French influence over the newly forming Cameroonian forces during decolonization but bypassed traditional military command channels, creating friction within the French military hierarchy.
2
+
3
+ The confusion primarily stemmed from unclear responsibilities between the Command of Forces Interarmées Françaises au Cameroun (CIFFC), led by General Sizaire, and other French military entities. This discord was exacerbated when General Sizaire only learned about the instruction through a letter dated January 2, 1961, sent by Minister Pierre Messmer, who criticized its secretive nature.
4
+
5
+ To address these challenges, there were calls for clearer delineation of command structures to prevent further conflicts. In response, Pierre Messmer proposed restructuring French military presence into two distinct commands: a Mixed Military Force (MMF) under the ambassador's authority and a separate command for Forces Françaises au Cameroun (FFC), overseen by Zone Militaire n°2 (Zom n°2). These measures aimed to streamline operations and solidify France's strategic interests as Cameroon moved towards military independence.
6
+
7
+ Overall, this period highlights the complexities and tensions inherent in decolonization, particularly regarding maintaining influence while transitioning control over military forces.
saved_summaries/eng/level_2_chunk_1_20250202_120509.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ In the mid-1950s, Cameroon experienced heightened anti-colonial tensions as French authorities intensified efforts to suppress the Union des Populations du Cameroun (UPC), a key nationalist movement. Under Roland Pré, the French Haut-Commissaire, strategic measures were implemented to counter UPC influence amid growing independence demands. This period was characterized by increased surveillance and aggressive repression, particularly in regions like Sanaga-Maritime.
2
+
3
+ Leaders such as Achille Mbembe and Ernest Ouandié sought to galvanize resistance through political and military training, prompting French authorities to deploy armed guards from Douala and Ngambè. These forces disrupted protests and led to the arrest of around 47 UPC supporters, highlighting the violent nature of the conflict and France's determination to maintain colonial control.
4
+
5
+ These events underscored Cameroon’s broader struggle for independence, illustrating Pré's multifaceted strategy that combined administrative reforms with military actions against anti-colonial movements. This approach was part of a larger French colonial strategy during this turbulent period in mid-20th-century Africa, reflecting the complexities faced by those resisting colonial rule.
6
+
7
+ This summary aligns with previous discussions on Pré’s efforts to weaken UPC influence through pro-French factions and decentralization policies, emphasizing the persistent struggle for Cameroon's independence against international decolonization pressures.
saved_summaries/eng/level_2_chunk_1_20250202_123019.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ In the late 1960s to early 1970s, Cameroon navigated a complex transition towards military autonomy from France, marked by efforts to assert sovereignty while managing residual colonial influences. The process culminated in complete control over its military forces by 1969. Tensions were prevalent between French and Cameroonian officers, particularly as younger Cameroonian commanders began exercising more independence, often disregarding their experienced French counterparts.
2
+
3
+ During this period, President Ahmadou Ahidjo actively sought enhanced military support from France to ensure regional stability without direct intervention. However, domestic unrest in France during 1968 delayed these efforts, complicating bilateral relations. To address the challenges of relying solely on French military training, Cameroon explored educational opportunities with other nations such as the USSR and Greece.
4
+
5
+ French involvement remained significant in certain regions like Bamiléké, where indirect support continued through logistics and preventive measures. Despite ongoing tensions over control and differing approaches to command, these agreements underscored the nuanced dynamics between seeking autonomy and maintaining established colonial ties within Cameroon's military sector during decolonization.
6
+
7
+ This phase reflects broader themes of post-independence transitions, emphasizing both the aspirations for national sovereignty and the enduring complexities of former colonial relationships in shaping new national identities.
saved_summaries/eng/level_2_chunk_2_20250202_120519.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ In the mid-20th century, France adapted its military strategies to address insurgencies during decolonization, particularly through the development of "guerre révolutionnaire" or revolutionary warfare. This approach emerged in response to the limitations of conventional tactics against movements such as those in Algeria and Vietnam. Colonel Charles Lacheroy was instrumental in formulating this strategy, which emphasized a multi-stage process beginning with psychological operations designed to destabilize existing social orders and erode state authority.
2
+
3
+ Lacheroy's framework highlighted the integration of psychological operations into military planning, aiming to influence public perception and loyalty to either gain support or suppress insurgencies. His insights were informed by observations from conflicts in Vietnam and Algeria, where insurgents effectively utilized non-military tactics against colonial powers. During the Algerian War of Independence, these strategies were combined with traditional combat operations to both engage insurgents and win civilian "hearts and minds."
4
+
5
+ The text underscores a pivotal shift in military history as France sought to address modern insurgency complexities through a blend of psychological and conventional warfare techniques. This adaptation was crucial for maintaining control over its colonies during an era marked by increasing demands for independence.
6
+
7
+ This summary aligns with previous discussions on French colonial strategies, focusing on the broader context of Cameroon's anti-colonial struggles in the 1950s, as outlined earlier. The emphasis here is on France's evolving military doctrine to counter nationalist movements like the UPC (Union des Populations du Cameroun) amid growing international pressures for decolonization.
saved_summaries/eng/level_2_chunk_2_20250202_123028.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ The text provides an in-depth examination of the coercive interrogation methods employed by French-backed forces, particularly the Bataillon Mixte Malgache (BMM), during Cameroon's transition from colonial rule to independence in the 1950s and early 1960s. These methods included brutal tactics such as forced confessions under duress, prominently featuring the "kalimba" method which involved electric shocks intended to extract information regardless of suspects' well-being.
2
+
3
+ Despite their severity, official reports frequently downplayed or omitted these coercive practices, portraying suspect cooperation as voluntary following persuasion by BMM agents. Specific incidents, including interrogations at places like Fort Kéniéba involving electric shock tactics, highlight the harsh treatment detainees endured during this period.
4
+
5
+ The text underscores scholarly critiques and personal testimonies that reveal extensive violence against Cameroonian political figures, reflecting a continuity of colonial-era repression strategies despite efforts to develop localized police training. These abuses contributed to broader patterns of oppression in post-colonial Cameroon, emphasizing the need for historical acknowledgment and justice for these human rights violations.
6
+
7
+ This account fits into a larger narrative of transitioning from colonial rule while grappling with enduring influences and practices inherited from that period, which affected national identity formation and governance in newly independent states.
saved_summaries/eng/level_2_chunk_3_20250202_120528.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ In December 1946, during the United Nations' Fourth Committee sessions in New York, intense negotiations centered on France's proposed trusteeship agreements for Cameroon. Over a span of ten days, delegates scrutinized eight draft agreements and considered 229 amendment proposals, reflecting global tensions between colonial powers and emerging norms of self-governance.
2
+
3
+ Delegates criticized French drafts for inadequately prioritizing the interests and autonomy of Cameroon’s inhabitants, with concerns raised about vague language that could contradict the UN's goal to establish genuine local governance. Representatives from nations like India, Haiti, and Egypt highlighted discrepancies between these colonial drafts and the principles of self-determination outlined in the UN Charter. They advocated for amendments ensuring that any future administration would be accountable to the United Nations rather than colonial powers such as France.
4
+
5
+ Proposals aimed at enhancing local autonomy and oversight under international law gained traction, reflecting a broader shift toward decolonization post-World War II. These discussions marked an important step towards redefining colonial administration through legal frameworks recognizing indigenous rights and autonomy, setting the stage for Cameroon's eventual path to independence.
6
+
7
+ This summary continues from previous discussions on French colonial strategies by highlighting pivotal diplomatic efforts at the UN that reshaped international approaches to decolonization, emphasizing how emerging norms increasingly favored self-governance.
saved_summaries/eng/level_2_chunk_3_20250202_123035.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ The text continues to explore severe human rights abuses during Cameroon's transition from colonial rule to independence, focusing on coercive interrogation methods employed by French-backed forces, including British collaboration. Techniques like the "kalimba" method involved electric shocks aimed at extracting information with little regard for detainees' well-being. Official reports often downplayed these brutal practices, framing suspect confessions as voluntary.
2
+
3
+ Specific incidents and testimonies reveal the harsh realities of interrogation tactics, such as those at Fort Kéniéba, illustrating a pattern of violence against Cameroonian political figures that mirrors colonial repression strategies. These abuses are contextualized within efforts to establish localized police forces in post-colonial Cameroon, highlighting the challenges of maintaining order while transitioning from colonial practices.
4
+
5
+ The text emphasizes the need for acknowledging these historical injustices to fully understand this period in Cameroonian history, underscoring broader patterns of oppression and their impact on national identity and governance. This narrative fits into a larger context of grappling with colonial legacies in newly independent states.
saved_summaries/fr/final_summary_297054.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ Au milieu du 20ème siècle, le Cameroun est devenu un point focal des tensions anticolonialistes alors que les autorités françaises cherchaient à réprimer l'Union des Populations du Cameroun (UPC), un mouvement nationaliste clé prônant l'indépendance. Pendant cette période, Roland Pré, le Haut-Commissaire français, a mis en œuvre des mesures stratégiques visant à contrer l'influence de l'UPC au milieu des demandes croissantes d'autonomie. Cette ère était marquée par une surveillance accrue et une répression agressive, particulièrement dans des régions comme le Sanaga-Maritime, où des leaders tels qu'Achille Mbembe et Ernest Ouandié ont mobilisé la résistance à travers la formation politique et militaire.
2
+
3
+ Les tactiques françaises incluaient le déploiement de forces armées pour perturber les manifestations et arrêter les manifestants, entraînant l'emprisonnement d'environ 47 partisans de l'UPC. Ces actions ont souligné la détermination de la France à maintenir le contrôle colonial malgré les pressions internationales en faveur du désengagement colonial. L'approche de Pré combinait des réformes administratives et des mesures militaires, reflétant une stratégie française plus large visant à affaiblir les mouvements anticolonialistes en favorisant des factions pro-françaises et en mettant en œuvre des politiques décentralisatrices.
4
+
5
+ Parallèlement à ces efforts au Cameroun, la France a adapté ses stratégies militaires à l'échelle mondiale grâce au développement de la "guerre révolutionnaire" ou guerre révolutionnaire. Cette approche innovante est apparue alors que les tactiques conventionnelles se révélaient insuffisantes contre des insurgences comme celles en Algérie et au Vietnam. Le Colonel Charles Lacheroy a joué un rôle instrumental dans cette stratégie, qui mettait l'accent sur les opérations psychologiques conçues pour déstabiliser les ordres sociaux existants et éroder l'autorité de l'État, en combinant ces éléments avec des actions militaires traditionnelles pour obtenir le soutien des civils.
6
+
7
+ Ces développements ont coïncidé avec des efforts diplomatiques à l'Organisation des Nations Unies, où des négociations intenses sur les accords de tutelle française concernant le Cameroun mettaient en lumière les tensions mondiales entre les puissances coloniales et les nouvelles normes d'autogouvernance. Lors des sessions du Quatrième Comité en décembre 1946, les délégués ont critiqué les propositions de la France pour ne pas prioriser suffisamment les intérêts camerounais, plaidant pour des amendements afin d'assurer que les futures administrations seraient responsables devant l'ONU plutôt que devant les autorités coloniales.
8
+
9
+ Ces discussions reflétaient un changement plus large vers le désengagement post-Seconde Guerre mondiale, soulignant l'autonomie locale et la surveillance internationale. À mesure que les normes mondiales favorisaient de plus en plus l'autogouvernance, ces efforts diplomatiques marquaient une étape importante dans la redéfinition de l'administration coloniale à travers des cadres juridiques reconnaissant les droits et l'autonomie autochtones. Ensemble, ces dynamiques militaires, politiques et diplomatiques illustrent les complexités de la résistance au règne colonial en Afrique au milieu du 20ème siècle et soulignent le combat persistant pour l'indépendance du Cameroun dans ce contexte historique tumultueux.
saved_summaries/fr/final_summary_297054_Volume_2.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Pendant la transition du Cameroun sous domination coloniale française vers l'indépendance entre les années 1950 et le début des années 1970, plusieurs dynamiques complexes se sont déroulées alors que les deux nations naviguaient dans l'autonomie militaire, le contrôle et les influences coloniales persistantes. En décembre 1960, la France a cherché à maintenir son influence sur les forces camerounaises en formation grâce à une directive secrète émise par le Premier ministre Michel Debré le 25 novembre, contournant les canaux de commandement traditionnels. Cela a créé des tensions au sein de la hiérarchie militaire française, notamment entre le général Sizaire du CIFFC et d'autres entités, exacerbées lorsque Sizaire a appris l'instruction par une correspondance retardée de Pierre Messmer en janvier 1961.
2
+
3
+ Pour faire face à ces défis, des propositions sont apparues pour restructurer la présence militaire française en deux commandements distincts : une Force Militaire Mixte (FMM) sous l'autorité de l'ambassadeur et une Forces Françaises au Cameroun (FFC), gérée par la Zone Militaire n°2. Cette réorganisation visait à rationaliser les opérations tout en protégeant les intérêts stratégiques de la France alors que le Cameroun se dirigeait vers l'indépendance militaire, mettant en lumière les tensions inhérentes au processus de décolonisation.
4
+
5
+ À mesure que le Cameroun passait à une autonomie accrue dans les années 1960 et au début des années 1970, les troubles intérieurs en France compliquaient les relations bilatérales et retardèrent les initiatives d'aide militaire poursuivies par le président Ahmadou Ahidjo. Alors que les officiers camerounais cherchaient une plus grande souveraineté et que des commandants plus jeunes commençaient à exercer leur indépendance vis-à-vis de leurs homologues français, la stabilité régionale demeurait une préoccupation. En réponse, le Cameroun a élargi ses opportunités d'éducation avec des nations comme l'URSS et la Grèce pour réduire sa dépendance à la formation française.
6
+
7
+ L'influence française a persisté dans des régions telles que les Bamiléké, où un soutien indirect est continué grâce au logistique et aux mesures préventives malgré les tensions persistantes sur le contrôle et les approches de commandement. Ces dynamiques ont souligné les défis post-indépendance plus larges, équilibrant les aspirations à la souveraineté nationale contre des liens coloniaux durables.
8
+
9
+ Parallèlement à ces transitions militaires et politiques, d'importantes violations des droits de l'homme sont apparues pendant le processus de décolonisation du Cameroun. Les forces soutenues par la France ont employé des techniques interrogatoires coercitives comme la méthode "kalimba", impliquant des chocs électriques pour extraire des aveux sous la contrainte. De telles pratiques étaient souvent atténuées dans les rapports officiels, malgré les témoignages révélant une violence généralisée contre les figures politiques camerounaises et la continuité des stratégies de répression de l'ère coloniale.
10
+
11
+ Cette période reflète les thèmes plus larges des transitions post-indépendance, mettant en évidence les défis pour maintenir l'ordre tout en passant de héritages coloniaux oppressifs. Reconnaître ces injustices historiques est essentiel pour comprendre leur impact sur la formation de l'identité nationale et le gouvernement dans des États nouvellement indépendants comme le Cameroun. La synthèse des efforts de restructuration militaire, des aspirations à la souveraineté et des abus en matière de droits de l'homme fournit un aperçu complet des complexités inhérentes à la décolonisation.
saved_summaries/fr/level_2_chunk_0_20250202_120459.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ Dans le milieu des années 1950 au Cameroun, les tensions anti-coloniales se sont intensifiées alors que les autorités françaises cherchaient à réprimer l'Union des Populations du Cameroun (UPC). Roland Pré, Haut-Commissaire français, a joué un rôle crucial dans la mise en œuvre de stratégies visant à contrer l'influence de l'UPC au milieu des demandes croissantes d'indépendance. Cette période était marquée par des confrontations stratégiques et des mesures répressives contre l'UPC.
2
+
3
+ Les événements clés incluaient une surveillance accrue et une répression agressive dans des régions comme la Sanaga-Maritime, où des leaders tels qu'Achille Mbembe et Ernest Ouandié tentaient de mobiliser la résistance par le biais d'un entraînement politique et militaire. Les tactiques françaises impliquaient le déploiement de gardes armés de Douala et Ngambè pour perturber les manifestations et arrêter les manifestants, y compris des actions conduisant à l'emprisonnement d'environ 47 partisans de l'UPC.
4
+
5
+ Ces incidents mettent en évidence la nature violente du conflit et la détermination de la France à maintenir le contrôle colonial face aux pressions internationales pour la décolonisation. Les événements ont souligné la lutte plus large pour l'indépendance du Cameroun, illustrant l'approche multifacette de Pré qui combinait des réformes administratives et des mesures militaires contre le mouvement anti-colonial.
6
+
7
+ Ce résumé est en accord avec les discussions précédentes en soulignant les efforts stratégiques de Pré pour diluer l'influence de l'UPC en favorisant des factions pro-françaises et en mettant en œuvre des politiques décentralisatrices. Ces actions faisaient partie d'une stratégie coloniale française plus large pendant cette période tumultueuse, reflétant les complexités de la résistance au règne colonial dans l'Afrique du milieu du XXe siècle.
saved_summaries/fr/level_2_chunk_0_20250202_123011.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ En décembre 1960, alors que la France passait le contrôle militaire au Cameroun pour le 1er janvier 1961, des défis importants ont émergé, notamment mis en lumière par une "Instruction personnelle et secrète" émise le 25 novembre par le Premier ministre français Michel Debré. Cette directive visait à maintenir l'influence française sur les forces camerounaises nouvellement formées pendant la décolonisation, mais contournait les canaux de commandement militaire traditionnels, créant des frictions au sein de la hiérarchie militaire française.
2
+
3
+ La confusion provenait principalement d'une responsabilité floue entre le Commandement des Forces Interarmées Françaises au Cameroun (CIFFC), dirigé par le Général Sizaire, et d'autres entités militaires françaises. Ce désaccord a été exacerbé lorsque le Général Sizaire n'a appris l'instruction que par une lettre datée du 2 janvier 1961 envoyée par le ministre Pierre Messmer, qui critiquait sa nature secrète.
4
+
5
+ Pour répondre à ces défis, il y avait des appels à une délimitation plus claire des structures de commandement afin d'éviter davantage de conflits. En réponse, Pierre Messmer a proposé de restructurer la présence militaire française en deux commandements distincts : une Force Militaire Mixte (FMM) sous l'autorité de l'ambassadeur et un commandement séparé pour les Forces Françaises au Cameroun (FFC), supervisé par Zone Militaire n°2 (Zom n°2). Ces mesures visaient à rationaliser les opérations et à consolider les intérêts stratégiques de la France alors que le Cameroun se dirigeait vers l'indépendance militaire.
6
+
7
+ Dans l'ensemble, cette période met en lumière les complexités et tensions inhérentes à la décolonisation, notamment en ce qui concerne le maintien d'une influence tout en passant le contrôle sur les forces militaires.
saved_summaries/fr/level_2_chunk_1_20250202_120509.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ Dans la moitié des années 1950, le Cameroun a connu des tensions anti-coloniales accrues alors que les autorités françaises intensifiaient leurs efforts pour réprimer l'Union des Populations du Cameroun (UPC), un mouvement nationaliste clé. Sous Roland Pré, Haut-Commissaire français, des mesures stratégiques ont été mises en œuvre pour contrer l'influence de l'UPC face à la croissance des demandes d'indépendance. Cette période était caractérisée par une surveillance accrue et une répression agressive, particulièrement dans des régions comme Sanaga-Maritime.
2
+
3
+ Des leaders tels qu'Achille Mbembe et Ernest Ouandié ont cherché à galvaniser la résistance à travers des formations politiques et militaires, incitant les autorités françaises à déployer des gardes armés depuis Douala et Ngambè. Ces forces ont perturbé les manifestations et conduit à l'arrestation d'environ 47 partisans de l'UPC, soulignant la nature violente du conflit et la détermination de la France à maintenir le contrôle colonial.
4
+
5
+ Ces événements ont mis en évidence la lutte plus large du Cameroun pour l'indépendance, illustrant la stratégie multifacette de Pré qui combinait réformes administratives avec des actions militaires contre les mouvements anti-coloniaux. Cette approche faisait partie d'une stratégie coloniale française plus large durant cette période tumultueuse en Afrique du milieu du 20ème siècle, reflétant la complexité rencontrée par ceux qui résistaient à l'autorité coloniale.
6
+
7
+ Ce résumé s'aligne avec les discussions précédentes sur les efforts de Pré pour affaiblir l'influence de l'UPC grâce aux factions pro-françaises et aux politiques de décentralisation, soulignant la lutte persistante du Cameroun pour son indépendance face aux pressions internationales de décolonisation.
saved_summaries/fr/level_2_chunk_1_20250202_123019.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ Dans la fin des années 1960 et le début des années 1970, le Cameroun a navigué à travers une transition complexe vers l'autonomie militaire de la France, marquée par des efforts pour affirmer sa souveraineté tout en gérant les influences coloniales résiduelles. Le processus s'est achevé avec un contrôle complet sur ses forces armées d'ici 1969. Des tensions prévalaient entre les officiers français et camerounais, notamment alors que des commandants camerounais plus jeunes commençaient à exercer une indépendance accrue, souvent en ignorant leurs homologues expérimentés français.
2
+
3
+ Pendant cette période, le président Ahmadou Ahidjo a activement cherché un soutien militaire renforcé de la France pour assurer la stabilité régionale sans intervention directe. Cependant, les troubles intérieurs en France en 1968 ont retardé ces efforts, compliquant les relations bilatérales. Pour répondre aux défis d'une dépendance exclusive à la formation militaire française, le Cameroun a exploré des opportunités éducatives avec d'autres nations telles que l'URSS et la Grèce.
4
+
5
+ La participation française est restée significative dans certaines régions comme les Bamiléké, où un soutien indirect continuait à travers la logistique et des mesures préventives. Malgré les tensions persistantes sur le contrôle et les approches divergentes du commandement, ces accords soulignaient les dynamiques nuancées entre la recherche d'autonomie et le maintien de liens coloniaux établis dans le secteur militaire du Cameroun pendant la décolonisation.
6
+
7
+ Cette phase reflète des thèmes plus larges de transitions post-indépendance, mettant en avant à la fois les aspirations pour une souveraineté nationale et les complexités durables des relations coloniales antérieures dans la formation d'identités nationales nouvelles.
saved_summaries/fr/level_2_chunk_2_20250202_120519.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ Au milieu du 20ème siècle, la France a adapté ses stratégies militaires pour faire face aux insurrections lors de la décolonisation, en particulier à travers le développement de la "guerre révolutionnaire" ou guerre révolutionnaire. Cette approche est apparue en réponse aux limitations des tactiques conventionnelles contre des mouvements tels que ceux en Algérie et au Vietnam. Le colonel Charles Lacheroy a joué un rôle clé dans l'élaboration de cette stratégie, qui mettait l'accent sur un processus multi-étapes commençant par des opérations psychologiques conçues pour déstabiliser les ordres sociaux existants et éroder l'autorité de l'État.
2
+
3
+ Le cadre de Lacheroy soulignait l'intégration d'opérations psychologiques dans la planification militaire, visant à influencer la perception publique et la loyauté pour gagner le soutien ou réprimer les insurrections. Ses aperçus étaient informés par des observations issues de conflits au Vietnam et en Algérie, où les insurgés utilisaient efficacement des tactiques non militaires contre les puissances coloniales. Pendant la Guerre d'Indépendance algérienne, ces stratégies ont été combinées avec des opérations combattantes traditionnelles pour à la fois engager les insurgés et gagner le "cœur et l'esprit" de la population civile.
4
+
5
+ Le texte souligne un changement pivot dans l'histoire militaire alors que la France cherchait à aborder les complexités modernes des insurrections grâce à une combinaison de techniques de guerre psychologique et conventionnelle. Cette adaptation était cruciale pour maintenir le contrôle sur ses colonies durant une époque marquée par l'augmentation des demandes d'indépendance.
6
+
7
+ Ce résumé s'aligne avec les discussions précédentes sur les stratégies coloniales françaises, en se concentrant sur le contexte plus large des luttes anti-coloniales au Cameroun dans les années 1950, comme cela a été décrit précédemment. L'accent est ici mis sur l'évolution de la doctrine militaire française pour contrer les mouvements nationalistes tels que l'UPC (Union des Populations du Cameroun) face aux pressions internationales croissantes en faveur de la décolonisation.
saved_summaries/fr/level_2_chunk_2_20250202_123028.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ Le texte fournit une analyse approfondie des méthodes d'interrogatoire coercitif employées par les forces soutenues par la France, notamment le Bataillon Mixte Malgache (BMM), pendant la transition du Cameroun de l'administration coloniale à l'indépendance dans les années 1950 et au début des années 1960. Ces méthodes incluaient des tactiques brutales telles que les aveux forcés sous la contrainte, notamment la méthode "kalimba" qui impliquait des chocs électriques destinés à extraire des informations indépendamment du bien-être des suspects.
2
+
3
+ Malgré leur gravité, les rapports officiels minimisaient fréquemment ou omettaient ces pratiques coercitives, présentant la coopération des suspects comme volontaire après avoir été persuadés par des agents du BMM. Des incidents spécifiques, notamment des interrogatoires à Fort Kéniéba impliquant des tactiques de chocs électriques, mettent en évidence le traitement sévère subi par les détenus pendant cette période.
4
+
5
+ Le texte souligne les critiques savantes et les témoignages personnels qui révèlent une violence étendue contre des figures politiques camerounaises, reflétant une continuité des stratégies de répression de l'ère coloniale malgré les efforts pour développer une formation policière locale. Ces abus ont contribué à des schémas plus larges d'oppression au Cameroun post-colonial, mettant en avant la nécessité de reconnaissance historique et de justice pour ces violations des droits humains.
6
+
7
+ Ce récit s'intègre dans un récit plus vaste de transition de l'administration coloniale tout en faisant face aux influences durables et pratiques héritées de cette période, qui ont affecté la formation de l'identité nationale et le gouvernement des nouveaux États indépendants.
saved_summaries/fr/level_2_chunk_3_20250202_120528.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ En décembre 1946, lors des sessions du Comité spécial quatrième de l'Organisation des Nations unies à New York, des négociations intenses ont porté sur les accords de tutelle proposés par la France pour le Cameroun. Sur une période de dix jours, les délégués ont examiné huit projets d'accord et considéré 229 propositions d'amendement, reflétant les tensions mondiales entre les puissances coloniales émergentes et les nouvelles normes d'autogouvernement.
2
+
3
+ Les délégués ont critiqué les projets français pour ne pas avoir suffisamment priorisé les intérêts et l'autonomie des habitants du Cameroun, soulevant des préoccupations concernant un langage flou qui pourrait contredire l'objectif de l'ONU d'établir une véritable gouvernance locale. Les représentants de nations comme l'Inde, Haïti et l'Égypte ont mis en évidence les divergences entre ces projets coloniaux et les principes de libre détermination tels qu'ils sont définis dans la Charte des Nations unies. Ils ont plaidé pour des amendements garantissant que toute future administration serait responsable de l'ONU plutôt que des puissances coloniales telles que la France.
4
+
5
+ Les propositions visant à renforcer l'autonomie locale et le contrôle sous le droit international ont gagné du terrain, reflétant un changement plus large vers la décolonisation après la Seconde Guerre mondiale. Ces discussions marquaient une étape importante pour redéfinir l'administration coloniale par des cadres juridiques reconnus reconnaissant les droits et l'autonomie autochtones, posant les bases du chemin ultérieur vers l'indépendance du Cameroun.
6
+
7
+ Ce résumé continue à partir de discussions précédentes sur les stratégies coloniales françaises en soulignant des efforts diplomatiques décisifs à l'ONU qui ont redessiné les approches internationales pour la décolonisation, en mettant en avant comment les normes émergentes favorisaient de plus en plus l'autogouvernement.
saved_summaries/fr/level_2_chunk_3_20250202_123035.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ Le texte continue d'explorer les graves violations des droits de l'homme pendant la transition du Cameroun de la domination coloniale à l'indépendance, en se concentrant sur les méthodes d'interrogatoire coercitives employées par les forces soutenues par la France, y compris la collaboration britannique. Des techniques comme la méthode « kalimba » impliquaient des chocs électriques destinés à extraire des informations sans tenir compte du bien-être des détenus. Les rapports officiels minimisaient souvent ces pratiques brutales, présentant les aveux suspects comme volontaires.
2
+
3
+ Des incidents spécifiques et des témoignages révèlent la dure réalité des tactiques d'interrogatoire, telles que celles utilisées à Fort Kéniéba, illustrant un schéma de violence contre les figures politiques camerounaises qui reflète les stratégies de répression coloniale. Ces abus sont contextualisés dans le cadre des efforts pour établir des forces de police locales au Cameroun post-colonial, mettant en lumière les défis à relever pour maintenir l'ordre tout en passant des pratiques coloniales.
4
+
5
+ Le texte insiste sur la nécessité de reconnaître ces injustices historiques pour comprendre pleinement cette période de l'histoire camerounaise, soulignant les schémas plus larges d'oppression et leur impact sur l'identité nationale et le gouvernement. Cette narration s'intègre dans un contexte plus large de lutte avec les héritages coloniaux dans les États nouvellement indépendants.
saved_summaries/question_eng.json ADDED
The diff for this file is too large to render. See raw diff
 
saved_summaries/question_fr.json ADDED
The diff for this file is too large to render. See raw diff
 
src/__init__.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ import logging
2
+
3
+ logging.basicConfig(
4
+ level=logging.WARNING,
5
+ format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
6
+ )
src/database.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import random
3
+ from glob import glob
4
+
5
+ from .vector_store.document_loader import load_dataset # noqa
6
+
7
+
8
+ def load_questions(language="fr"):
9
+ raw: dict[str, list[dict[str, str]]] = json.load(
10
+ open(f"saved_summaries/question_{language}.json")
11
+ )
12
+ questions = [example["query"] for _, fqa in raw.items() for example in fqa]
13
+ return questions
14
+
15
+
16
+ def load_final_summaries(language="fr"):
17
+ files = glob(f"saved_summaries/{language}/*.txt")
18
+ data = [open(file).read() for file in files]
19
+ random.shuffle(data)
20
+ return data
src/rag_pipeline/__init__.py ADDED
File without changes
src/rag_pipeline/prompts.py ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain.prompts.chat import (
2
+ ChatPromptTemplate,
3
+ HumanMessagePromptTemplate,
4
+ MessagesPlaceholder,
5
+ SystemMessagePromptTemplate,
6
+ )
7
+
8
+ # ---------------------------------------------------------------------------
9
+ # System Prompt for the RAG Expert on France's Role in Cameroon
10
+ # ---------------------------------------------------------------------------
11
+ system_prompt = """
12
+ You are **Dikoka**, an AI assistant and expert on France’s involvement in Cameroon during the suppression of independence and opposition movements (1945-1971), based on the findings of the Franco-Cameroonian Commission.
13
+
14
+ **Instructions:**
15
+ - **Answer strictly using the provided context.**
16
+ - **Summarize key points when requested.**
17
+ - **Maintain accuracy and neutrality; avoid speculation or external knowledge.**
18
+
19
+ **Response Guidelines:**
20
+ 1. **Context-Only Answers:** Rely solely on the provided context.
21
+ 2. **Insufficient Information:** If details are lacking, reply:
22
+ > "I do not have enough information to answer this question based on the provided context."
23
+ 3. **Language Requests:** If a query is in an African language or asks for a translation, reply:
24
+ > "I can only provide information in the language of the original context. Could you please rephrase your question in that language?"
25
+ 4. **Irrelevant Topics:** For questions not related to:
26
+ - The Franco-Cameroonian Commission’s findings
27
+ - France’s role in Cameroon
28
+ - The historical period (1945-1971)
29
+
30
+ reply:
31
+ > "I do not have information on that topic based on the provided context. Could you please ask a question related to France’s role in Cameroon between 1945 and 1971?"
32
+ 5. **Summaries:** Provide concise, structured summaries (using bullet points or paragraphs) based solely on the context.
33
+ 6. **Formatting:** Organize responses using bullet points, numbered lists, and headings/subheadings when appropriate.
34
+
35
+ Context:
36
+ {context}
37
+ """
38
+
39
+ # Define the messages for the main chat prompt
40
+ chat_messages = [
41
+ MessagesPlaceholder(variable_name="chat_history"),
42
+ SystemMessagePromptTemplate.from_template(system_prompt),
43
+ HumanMessagePromptTemplate.from_template(
44
+ "Answer in the same language as the input:\n{input}"
45
+ ),
46
+ ]
47
+
48
+ # Create the chat prompt template
49
+ CHAT_PROMPT = ChatPromptTemplate.from_messages(chat_messages)
50
+
51
+ # ---------------------------------------------------------------------------
52
+ # Prompt for Generating a Standalone Query from Conversation History
53
+ # ---------------------------------------------------------------------------
54
+ standalone_query_instructions = """
55
+ Your task is to generate a standalone query that is fully understandable without any prior conversation context. Follow these steps:
56
+
57
+ 1. Analyze the conversation history and the latest query.
58
+ 2. Rephrase the query to include any necessary context from the history (don't answer the query).
59
+ 3. If the original query is already standalone, return it as is.
60
+ 4. Maintain the original intent in rephrase and language of the query.
61
+ 5. Output only the standalone query **without any explanations or extra text**. Only query rephrased are needed.
62
+ """
63
+
64
+ # Create the contextual query prompt template
65
+ CONTEXTUEL_QUERY_PROMPT = ChatPromptTemplate.from_messages(
66
+ [
67
+ SystemMessagePromptTemplate.from_template(standalone_query_instructions),
68
+ MessagesPlaceholder(variable_name="chat_history"),
69
+ HumanMessagePromptTemplate.from_template("{input}"),
70
+ ]
71
+ )
src/rag_pipeline/rag_system.py ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ from typing import List, Optional
3
+
4
+ from langchain.chains.combine_documents import create_stuff_documents_chain
5
+ from langchain.chains.conversational_retrieval.base import (
6
+ BaseConversationalRetrievalChain,
7
+ )
8
+ from langchain.chains.history_aware_retriever import (
9
+ create_history_aware_retriever,
10
+ )
11
+ from langchain.chains.retrieval import create_retrieval_chain
12
+
13
+ from ..utilities.llm_models import get_llm_model_chat
14
+ from ..vector_store.vector_store import VectorStoreManager
15
+ from .prompts import CHAT_PROMPT, CONTEXTUEL_QUERY_PROMPT
16
+
17
+
18
+ class RAGSystem:
19
+ """
20
+ Retrieval-Augmented Generation (RAG) system for document retrieval and question answering.
21
+ """
22
+
23
+ def __init__(
24
+ self,
25
+ persist_directory_dir="data/chroma_db",
26
+ batch_size: int = 64,
27
+ top_k_documents=5,
28
+ ):
29
+ """
30
+ Initializes the RAGSystem with the given parameters.
31
+
32
+ Args:
33
+ persist_directory_dir (str): Directory to persist the vector store.
34
+ batch_size (int): Number of documents to process in each batch.
35
+ top_k_documents (int): Number of top documents to retrieve.
36
+ """
37
+ self.top_k_documents = top_k_documents
38
+ self.llm = self._get_llm()
39
+ self.chain: Optional[BaseConversationalRetrievalChain] = None
40
+ self.vector_store_management = VectorStoreManager(
41
+ persist_directory_dir, batch_size
42
+ )
43
+
44
+ def _get_llm(self):
45
+ """
46
+ Retrieves the language model for the RAG system.
47
+
48
+ Returns:
49
+ The language model.
50
+ """
51
+ return get_llm_model_chat(temperature=0.1, max_tokens=1000)
52
+
53
+ def load_documents(self) -> List:
54
+ """
55
+ Loads and splits documents from the specified directory.
56
+
57
+ Returns:
58
+ List: List of loaded documents.
59
+ """
60
+ return self.vector_store_management.load_and_process_documents()
61
+
62
+ def initialize_vector_store(self, documents: List = None):
63
+ """
64
+ Initializes or loads the vector store.
65
+
66
+ Args:
67
+ documents (List, optional): List of documents to initialize the vector store. Defaults to None.
68
+ """
69
+ self.vector_store_management.initialize_vector_store(documents)
70
+
71
+ def setup_rag_chain(self):
72
+ """
73
+ Sets up the RAG chain for document retrieval and question answering.
74
+ """
75
+ if self.chain is not None:
76
+ return
77
+ retriever = self.vector_store_management.create_retriever(
78
+ self.llm, self.top_k_documents, bm25_portion=0.03
79
+ )
80
+
81
+ # Contextualize question
82
+ history_aware_retriever = create_history_aware_retriever(
83
+ self.llm, retriever, CONTEXTUEL_QUERY_PROMPT
84
+ )
85
+ question_answer_chain = create_stuff_documents_chain(self.llm, CHAT_PROMPT)
86
+ self.chain = create_retrieval_chain(
87
+ history_aware_retriever, question_answer_chain
88
+ )
89
+ logging.info("RAG chain setup complete" + str(self.chain))
90
+ return self.chain
91
+
92
+ def query(self, question: str, history: list = []):
93
+ """
94
+ Queries the RAG system with a question and chat history.
95
+
96
+ Args:
97
+ question (str): The question to query.
98
+ history (list, optional): The chat history. Defaults to [].
99
+
100
+ Yields:
101
+ str: The answer from the RAG system.
102
+ """
103
+ if not self.vector_store_management.vs_initialized:
104
+ self.initialize_vector_store()
105
+
106
+ self.setup_rag_chain()
107
+
108
+ for token in self.chain.stream({"input": question, "chat_history": history}):
109
+ if "answer" in token:
110
+ yield token["answer"]
src/utilities/__init__.py ADDED
File without changes
src/utilities/embedding.py ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import os
3
+ from typing import Any, List
4
+
5
+ import torch
6
+ from langchain_core.embeddings import Embeddings
7
+ from langchain_huggingface import (
8
+ HuggingFaceEmbeddings,
9
+ HuggingFaceEndpointEmbeddings,
10
+ )
11
+ from pydantic import BaseModel, Field
12
+
13
+
14
+ class CustomEmbedding(BaseModel, Embeddings):
15
+ """
16
+ Custom embedding class that supports both hosted and CPU embeddings.
17
+ """
18
+
19
+ hosted_embedding: HuggingFaceEndpointEmbeddings = Field(
20
+ default_factory=lambda: None
21
+ )
22
+ cpu_embedding: HuggingFaceEmbeddings = Field(default_factory=lambda: None)
23
+ matryoshka_dim: int = Field(default=256)
24
+
25
+ def get_instruction(self) -> str:
26
+ """
27
+ Generates the instruction for the embedding model based on environment variables.
28
+
29
+ Returns:
30
+ str: The instruction string.
31
+ """
32
+ if "nomic" in os.getenv("HF_MODEL"):
33
+ return (
34
+ "search_query: "
35
+ if (os.getenv("IS_APP", "0") == "1")
36
+ else "search_document: "
37
+ )
38
+ return (
39
+ "Represent this sentence for searching relevant passages:"
40
+ if (os.getenv("IS_APP", "0") == "1")
41
+ else ""
42
+ )
43
+
44
+ def get_hf_embedd(self) -> HuggingFaceEmbeddings:
45
+ """
46
+ Initializes the HuggingFaceEmbeddings with the appropriate settings.
47
+
48
+ Returns:
49
+ HuggingFaceEmbeddings: The initialized HuggingFaceEmbeddings object.
50
+ """
51
+ return HuggingFaceEmbeddings(
52
+ model_name=os.getenv("HF_MODEL"), # You can replace with any HF model
53
+ model_kwargs={
54
+ "device": "cpu" if not torch.cuda.is_available() else "cuda",
55
+ "trust_remote_code": True,
56
+ },
57
+ encode_kwargs={
58
+ "normalize_embeddings": True,
59
+ "prompt": self.get_instruction(),
60
+ },
61
+ )
62
+
63
+ def __init__(self, matryoshka_dim=256, **kwargs: Any):
64
+ """
65
+ Initializes the CustomEmbedding with the given parameters.
66
+
67
+ Args:
68
+ matryoshka_dim (int): Dimension of the embeddings.
69
+ **kwargs: Additional keyword arguments.
70
+ """
71
+ super().__init__(**kwargs)
72
+ query_instruction = self.get_instruction()
73
+ self.matryoshka_dim = matryoshka_dim
74
+ if torch.cuda.is_available():
75
+ logging.info("CUDA is available")
76
+ self.hosted_embedding = self.get_hf_embedd()
77
+ self.cpu_embedding = self.hosted_embedding
78
+ else:
79
+ logging.info("CUDA is not available")
80
+ self.hosted_embedding = HuggingFaceEndpointEmbeddings(
81
+ model=os.getenv("HF_MODEL"),
82
+ model_kwargs={
83
+ "encode_kwargs": {
84
+ "normalize_embeddings": True,
85
+ "prompt": query_instruction,
86
+ }
87
+ },
88
+ huggingfacehub_api_token=os.getenv("HUGGINGFACEHUB_API_TOKEN"),
89
+ )
90
+ self.cpu_embedding = self.get_hf_embedd()
91
+
92
+ def embed_documents(self, texts: List[str]) -> List[List[float]]:
93
+ """
94
+ Embeds a list of documents using the appropriate embedding model.
95
+
96
+ Args:
97
+ texts (List[str]): List of document texts to embed.
98
+
99
+ Returns:
100
+ List[List[float]]: List of embedded document vectors.
101
+ """
102
+ try:
103
+ embed = self.hosted_embedding.embed_documents(texts)
104
+ except Exception as e:
105
+ logging.warning(f"Issue with batch hosted embedding, moving to CPU: {e}")
106
+ embed = self.cpu_embedding.embed_documents(texts)
107
+ return (
108
+ [e[: self.matryoshka_dim] for e in embed] if self.matryoshka_dim else embed
109
+ )
110
+
111
+ def embed_query(self, text: str) -> List[float]:
112
+ """
113
+ Embeds a single query using the appropriate embedding model.
114
+
115
+ Args:
116
+ text (str): The query text to embed.
117
+
118
+ Returns:
119
+ List[float]: The embedded query vector.
120
+ """
121
+ try:
122
+ embed = self.hosted_embedding.embed_query(text)
123
+ except Exception as e:
124
+ logging.warning(f"Issue with hosted embedding, moving to CPU: {e}")
125
+ embed = self.cpu_embedding.embed_query(text)
126
+ logging.warning(text)
127
+ return embed[: self.matryoshka_dim] if self.matryoshka_dim else embed
src/utilities/llm_models.py ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from enum import Enum
3
+
4
+ from langchain_groq import ChatGroq
5
+ from langchain_ollama import ChatOllama, OllamaEmbeddings
6
+
7
+ from .embedding import CustomEmbedding
8
+
9
+
10
+ class LLMModel(Enum):
11
+ OLLAMA = "ChatOllama"
12
+ GROQ = "ChatGroq"
13
+
14
+
15
+ def get_llm_model_chat(temperature=0.01, max_tokens: int = None):
16
+ if str(os.getenv("USE_OLLAMA_CHAT")) == "1":
17
+ return ChatOllama(
18
+ model=os.getenv("OLLAMA_MODEL"),
19
+ temperature=temperature,
20
+ num_predict=max_tokens,
21
+ )
22
+ return ChatGroq(
23
+ model=os.getenv("GROQ_MODEL_NAME"),
24
+ temperature=temperature,
25
+ max_tokens=max_tokens,
26
+ )
27
+
28
+
29
+ def get_llm_model_embedding():
30
+ if str(os.getenv("USE_HF_EMBEDDING")) == "1":
31
+ return CustomEmbedding()
32
+ return OllamaEmbeddings(
33
+ model=os.getenv("OLLAM_EMB"),
34
+ base_url=(
35
+ os.getenv("OLLAMA_HOST") if os.getenv("OLLAMA_HOST") is not None else None
36
+ ),
37
+ client_kwargs=(
38
+ {
39
+ "headers": {
40
+ "Authorization": "Bearer " + (os.getenv("OLLAMA_TOKEN") or "")
41
+ }
42
+ }
43
+ if os.getenv("OLLAMA_HOST") is not None
44
+ else None
45
+ ),
46
+ )
src/vector_store/__init__.py ADDED
File without changes
src/vector_store/document_loader.py ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+ from glob import glob
4
+ from typing import Dict, List
5
+
6
+ import tiktoken
7
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
8
+ from langchain_core.documents import Document
9
+
10
+
11
+ def load_qa_dataset(file_path: str) -> List[List[str]]:
12
+ """
13
+ Load question-answer dataset from a JSON file.
14
+
15
+ Args:
16
+ file_path (str): Path to the JSON file containing the QA dataset.
17
+
18
+ Returns:
19
+ List[List[str]]: List of questions and their corresponding file names.
20
+ """
21
+ raw: Dict[str, List[Dict[str, str]]] = json.load(open(file_path))
22
+ questions = [
23
+ [example["response"], os.path.basename(path)]
24
+ for path, fqa in raw.items()
25
+ for example in fqa
26
+ ]
27
+ return questions
28
+
29
+
30
+ def load_summaries(
31
+ folder_path: str, chunk_size=512, chunk_overlap=100
32
+ ) -> List[List[str]]:
33
+ """
34
+ Load summaries from text files in a folder and split them into chunks.
35
+
36
+ Args:
37
+ folder_path (str): Path to the folder containing text files.
38
+ chunk_size (int, optional): Size of each chunk. Defaults to 512.
39
+ chunk_overlap (int, optional): Overlap between chunks. Defaults to 100.
40
+
41
+ Returns:
42
+ List[List[str]]: List of text chunks and their corresponding folder names.
43
+ """
44
+ encoding = tiktoken.get_encoding("cl100k_base")
45
+ text_splitter = RecursiveCharacterTextSplitter(
46
+ chunk_size=chunk_size,
47
+ chunk_overlap=chunk_overlap,
48
+ length_function=lambda x: len(encoding.encode(x)),
49
+ )
50
+
51
+ files = sorted(glob(os.path.join(folder_path, "**/*.txt"), recursive=True))
52
+ grouped_files: Dict[str, List[str]] = {}
53
+ for file in files:
54
+ folder = os.path.dirname(file)
55
+ grouped_files.setdefault(folder, []).append(file)
56
+
57
+ summaries = []
58
+ for folder, file_list in grouped_files.items():
59
+ content = "\n\n".join(open(file).read() for file in file_list)
60
+ summaries.extend((chunk, folder) for chunk in text_splitter.split_text(content))
61
+
62
+ return summaries
63
+
64
+
65
+ def load_pages_from_folder(
66
+ folder_path: str, chunk_size=512, chunk_overlap=100
67
+ ) -> List[List[str]]:
68
+ """
69
+ Load pages from text files in a folder and split them into chunks.
70
+
71
+ Args:
72
+ folder_path (str): Path to the folder containing text files.
73
+ chunk_size (int, optional): Size of each chunk. Defaults to 512.
74
+ chunk_overlap (int, optional): Overlap between chunks. Defaults to 100.
75
+
76
+ Returns:
77
+ List[List[str]]: List of text chunks and their corresponding folder names.
78
+ """
79
+ files = sorted(glob(os.path.join(folder_path, "*.txt")))
80
+ name = os.path.basename(folder_path)
81
+ pages = [open(path).read().strip() for path in files]
82
+ content = "\n\n".join(pages)
83
+ encoding = tiktoken.get_encoding("cl100k_base")
84
+ text_splitter = RecursiveCharacterTextSplitter(
85
+ chunk_size=chunk_size,
86
+ chunk_overlap=chunk_overlap,
87
+ length_function=lambda x: len(encoding.encode(x)),
88
+ )
89
+ summaries = text_splitter.split_text(content)
90
+ return [(i, name) for i in summaries]
91
+
92
+
93
+ def load_pages_from_folders(
94
+ folders_path: List[str], chunk_size=512, chunk_overlap=100
95
+ ) -> List[List[str]]:
96
+ """
97
+ Load pages from multiple folders and split them into chunks.
98
+
99
+ Args:
100
+ folders_path (List[str]): List of folder paths containing text files.
101
+ chunk_size (int, optional): Size of each chunk. Defaults to 512.
102
+ chunk_overlap (int, optional): Overlap between chunks. Defaults to 100.
103
+
104
+ Returns:
105
+ List[List[str]]: List of text chunks and their corresponding folder names.
106
+ """
107
+ data = sum(
108
+ [
109
+ load_pages_from_folder(folder, chunk_size, chunk_overlap)
110
+ for folder in folders_path
111
+ ],
112
+ start=[],
113
+ )
114
+ return data
115
+
116
+
117
+ def load_dataset(language="fr") -> List[Document]:
118
+ """
119
+ Load the entire dataset including questions, summaries, and pages.
120
+
121
+ Args:
122
+ language (str, optional): Language of the dataset. Defaults to "fr".
123
+
124
+ Returns:
125
+ List[Document]: List of Document objects containing the dataset.
126
+ """
127
+ question_path = f"saved_summaries/question_{language}.json"
128
+ questions = load_qa_dataset(question_path)
129
+
130
+ summary_path = "data/summaries/summaries_" + language
131
+ summaries = load_summaries(
132
+ summary_path,
133
+ chunk_size=512,
134
+ chunk_overlap=100,
135
+ )
136
+
137
+ pages = load_pages_from_folders(
138
+ ["data/pages/297054", "data/pages/297054_Volume_2"],
139
+ chunk_size=512,
140
+ chunk_overlap=100,
141
+ )
142
+
143
+ documents = questions + summaries + pages
144
+ documents = [
145
+ Document(page_content=doc, metadata={"source": source})
146
+ for (doc, source) in documents
147
+ ]
148
+ return documents
149
+
150
+
151
+ class DocumentLoader:
152
+ """
153
+ Handles loading and splitting documents from directories.
154
+ """
155
+
156
+ def load_documents(self) -> List[Document]:
157
+ """
158
+ Determines and loads documents based on file type.
159
+
160
+ Returns:
161
+ List[Document]: List of Document objects containing the dataset.
162
+ """
163
+ return load_dataset()
src/vector_store/prompts.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.prompts.prompt import PromptTemplate
2
+
3
+ DEFAULT_QUERY_PROMPT = PromptTemplate(
4
+ input_variables=["question"],
5
+ template="""You are an AI language model assistant tasked with generating alternative versions of a given user question. Your goal is to create 3 different perspectives on the original question to help retrieve relevant documents from a vector database. This approach aims to overcome some limitations of distance-based similarity search.
6
+
7
+ When generating alternative questions, follow these guidelines:
8
+ 1. Maintain the core intent of the original question
9
+ 2. Use different phrasing, synonyms, or sentence structures
10
+ 3. Consider potential related aspects or implications of the question
11
+ 4. Avoid introducing new topics or drastically changing the subject matter
12
+
13
+ Here is the original question:
14
+
15
+ {question}
16
+
17
+
18
+ Generate 3 alternative versions of this question. Provide your output as a numbered list, with each alternative question on a new line. Do not include any additional explanation or commentary.
19
+
20
+ Remember, the purpose of these alternative questions is to broaden the search scope while staying relevant to the user's original intent. This will help in retrieving a diverse set of potentially relevant documents from the vector database.
21
+
22
+ Do not include any additional explanation or commentary, just give 3 alternative questions.
23
+ """,
24
+ )
src/vector_store/vector_store.py ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from typing import Dict, List
3
+
4
+ from langchain.retrievers import MultiQueryRetriever
5
+ from langchain_chroma import Chroma
6
+ from langchain_core.documents import Document
7
+ from tqdm import tqdm
8
+
9
+ from ..utilities.llm_models import get_llm_model_embedding
10
+ from .document_loader import DocumentLoader
11
+ from .prompts import DEFAULT_QUERY_PROMPT
12
+
13
+
14
+ def get_collection_name() -> str:
15
+ """
16
+ Derives the collection name from an environment variable.
17
+
18
+ Returns:
19
+ str: Processed collection name.
20
+ """
21
+ return os.getenv("HF_MODEL", "default_model").split(":")[0].split("/")[-1]
22
+
23
+
24
+ class VectorStoreManager:
25
+ """
26
+ Manages vector store initialization, updates, and retrieval.
27
+ """
28
+
29
+ def __init__(self, persist_directory: str, batch_size: int = 64):
30
+ """
31
+ Initializes the VectorStoreManager with the given parameters.
32
+
33
+ Args:
34
+ persist_directory (str): Directory to persist the vector store.
35
+ batch_size (int): Number of documents to process in each batch.
36
+ """
37
+ self.persist_directory = persist_directory
38
+ self.batch_size = batch_size
39
+ self.embeddings = get_llm_model_embedding()
40
+ self.collection_name = get_collection_name()
41
+ self.vector_stores: Dict[str, Chroma] = {"chroma": None}
42
+ self.vs_initialized = False
43
+
44
+ def _batch_process_documents(self, documents: List[Document]):
45
+ """
46
+ Processes documents in batches for vector store initialization.
47
+
48
+ Args:
49
+ documents (List[Document]): List of documents to process.
50
+ """
51
+ for i in tqdm(
52
+ range(0, len(documents), self.batch_size), desc="Processing documents"
53
+ ):
54
+ batch = documents[i : i + self.batch_size]
55
+ if not self.vs_initialized:
56
+ self.vector_stores["chroma"] = Chroma.from_documents(
57
+ collection_name=self.collection_name,
58
+ documents=batch,
59
+ embedding=self.embeddings,
60
+ persist_directory=self.persist_directory,
61
+ )
62
+ self.vs_initialized = True
63
+ else:
64
+ self.vector_stores["chroma"].add_documents(batch)
65
+
66
+ def initialize_vector_store(self, documents: List[Document] = None):
67
+ """
68
+ Initializes or loads the vector store.
69
+
70
+ Args:
71
+ documents (List[Document], optional): List of documents to initialize the vector store with.
72
+ """
73
+ if documents:
74
+ self._batch_process_documents(documents)
75
+ else:
76
+ self.vector_stores["chroma"] = Chroma(
77
+ collection_name=self.collection_name,
78
+ persist_directory=self.persist_directory,
79
+ embedding_function=self.embeddings,
80
+ )
81
+ self.vs_initialized = True
82
+
83
+ def create_retriever(
84
+ self, llm, n_documents: int, bm25_portion: float = 0.8
85
+ ) -> MultiQueryRetriever:
86
+ """
87
+ Creates a retriever using Chroma.
88
+
89
+ Args:
90
+ llm: Language model to use for the retriever.
91
+ n_documents (int): Number of documents to retrieve.
92
+ bm25_portion (float): Portion of BM25 to use in the retriever.
93
+
94
+ Returns:
95
+ MultiQueryRetriever: Configured retriever.
96
+ """
97
+ self.vector_store = MultiQueryRetriever.from_llm(
98
+ retriever=self.vector_stores["chroma"].as_retriever(
99
+ search_kwargs={"k": n_documents}
100
+ ),
101
+ llm=llm,
102
+ include_original=True,
103
+ prompt=DEFAULT_QUERY_PROMPT
104
+ )
105
+ return self.vector_store
106
+
107
+ def load_and_process_documents(self) -> List[Document]:
108
+ """
109
+ Loads and processes documents from the specified directory.
110
+
111
+ Returns:
112
+ List[Document]: List of processed documents.
113
+ """
114
+ loader = DocumentLoader()
115
+ return loader.load_documents()