chuckfinca commited on
Commit
1550049
·
1 Parent(s): c32c832

feat(notebook): Add PoC notebook for RAG demonstration

Browse files

This commit introduces the primary technical deliverable: a functional, interactive Proof-of-Concept (PoC) in a Google Colab notebook.

The notebook () demonstrates the functionality of the Freshman On-Track Intervention Recommender. It guides the user through the entire process:
- Setting up the local environment.
- Loading the final, semantically chunked knowledge base.
- Initializing the embedding model and FAISS vector database.
- Accepting a user's free-text query about a student's challenges.
- Performing a semantic search and displaying the top 3 recommendations.

Key Changes:
- **Added PoC Notebook**: Created to serve as the interactive demonstration of the RAG system.
- **Created Display Utilities**: Introduced a new module with a helper function. This formats the raw search results into a clean, human-readable output, making the recommendations clear and actionable within the notebook.
- **Updated Dependencies**: Added and to the dependencies in to ensure the project's development environment fully supports working with the notebook.

notebooks/fot_recommender_poc.ipynb ADDED
@@ -0,0 +1,373 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "944d2724-5cbb-4f2d-80f1-4deec31e4058",
6
+ "metadata": {},
7
+ "source": [
8
+ "# Freshman On-Track (FOT) Intervention Recommender\n",
9
+ "### A Standalone Proof-of-Concept\n",
10
+ "\n",
11
+ "This notebook demonstrates a working PoC for an AI-powered intervention recommender.\n",
12
+ "\n",
13
+ "**This notebook is designed to run in Google Colab.** It contains all the code needed to set up its environment, download the project from GitHub, and run the demonstration."
14
+ ]
15
+ },
16
+ {
17
+ "cell_type": "markdown",
18
+ "id": "e4be1b92-95cc-421f-9820-9ccfc261aaeb",
19
+ "metadata": {},
20
+ "source": [
21
+ "## 1. Universal Setup\n",
22
+ "\n",
23
+ "This cell is the \"magic\" that prepares the entire environment. It intelligently detects where it's running and performs the correct setup automatically.\n",
24
+ "\n",
25
+ "Here's what happens when you run the next cell:\n",
26
+ "1. **Define Project Source**: We specify the official GitHub repository for this project so it's clear where the code comes from.\n",
27
+ "2. **Detect Environment**: The notebook checks if it's running inside the local project folder or as a standalone file.\n",
28
+ "3. **Prepare Environment**: A helper script is called to do the heavy lifting:\n",
29
+ " - If **local**, it uses your existing project files.\n",
30
+ " - If **standalone**, it clones the repository and installs all dependencies for you.\n",
31
+ "\n",
32
+ "After running this one cell, the environment will be ready for the demonstration."
33
+ ]
34
+ },
35
+ {
36
+ "cell_type": "code",
37
+ "execution_count": 1,
38
+ "id": "1f286cf0-3355-48ff-ade7-43a035db38ea",
39
+ "metadata": {},
40
+ "outputs": [
41
+ {
42
+ "name": "stdout",
43
+ "output_type": "stream",
44
+ "text": [
45
+ "🚀 Setting up LOCAL development environment...\n",
46
+ " - Using local project root: /Users/charlesfeinn/Developer/job_applications/fot-intervention-recommender\n",
47
+ "\n",
48
+ "🎉 Local environment is ready!\n"
49
+ ]
50
+ }
51
+ ],
52
+ "source": [
53
+ "import sys\n",
54
+ "from pathlib import Path\n",
55
+ "\n",
56
+ "# --- Define Project Source ---\n",
57
+ "REPO_URL = \"https://github.com/chuckfinca/fot-intervention-recommender.git\"\n",
58
+ "PROJECT_DIR_NAME = \"fot-intervention-recommender\"\n",
59
+ "\n",
60
+ "# print(\"🚀 Setting up the environment...\")\n",
61
+ "\n",
62
+ "# # --- Clone the Repository & Install Dependencies ---\n",
63
+ "# !git clone -q {REPO_URL}\n",
64
+ "# %pip install -q -r {PROJECT_DIR_NAME}/requirements.txt\n",
65
+ "\n",
66
+ "# # --- Configure Python Path ---\n",
67
+ "# project_path = Path.cwd() / PROJECT_DIR_NAME\n",
68
+ "# src_path = project_path / \"src\"\n",
69
+ "# sys.path.insert(0, str(src_path))\n",
70
+ "\n",
71
+ "# print(\"\\n🎉 Environment is ready!\")\n",
72
+ "\n",
73
+ "\n",
74
+ "print(\"🚀 Setting up LOCAL development environment...\")\n",
75
+ "\n",
76
+ "# We assume the notebook is in 'notebooks/'. The project root is one level up.\n",
77
+ "project_path = Path.cwd().parent \n",
78
+ "\n",
79
+ "# Configure Python Path to use the local 'src' directory\n",
80
+ "src_path = project_path / \"src\"\n",
81
+ "if str(src_path) not in sys.path:\n",
82
+ " sys.path.insert(0, str(src_path))\n",
83
+ "\n",
84
+ "print(f\" - Using local project root: {project_path}\")\n",
85
+ "print(\"\\n🎉 Local environment is ready!\")"
86
+ ]
87
+ },
88
+ {
89
+ "cell_type": "markdown",
90
+ "id": "c9b1ad1b-1c20-4eca-b98f-179ad80dc942",
91
+ "metadata": {},
92
+ "source": [
93
+ "## 2. Load the Knowledge Base\n",
94
+ "\n",
95
+ "With the environment bootstrapped, we can now import our project's modules and load the data. The `project_path` variable ensures we find the file correctly."
96
+ ]
97
+ },
98
+ {
99
+ "cell_type": "code",
100
+ "execution_count": 2,
101
+ "id": "4143ee4b-c9f3-4d18-9d5b-0ee247937961",
102
+ "metadata": {},
103
+ "outputs": [
104
+ {
105
+ "name": "stderr",
106
+ "output_type": "stream",
107
+ "text": [
108
+ "/Users/charlesfeinn/Developer/job_applications/fot-intervention-recommender/.venv/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
109
+ " from .autonotebook import tqdm as notebook_tqdm\n"
110
+ ]
111
+ },
112
+ {
113
+ "name": "stdout",
114
+ "output_type": "stream",
115
+ "text": [
116
+ "Successfully loaded 27 intervention chunks.\n"
117
+ ]
118
+ },
119
+ {
120
+ "data": {
121
+ "text/plain": [
122
+ "{'title': 'Strategy: Leadership Roles',\n",
123
+ " 'source_document': 'NCS_OTToolkit_2ndEd_October_2017_updated.pdf',\n",
124
+ " 'fot_pages': 'Pages: 44',\n",
125
+ " 'content_for_embedding': 'Title: Strategy: Leadership Roles. Content: Principal Role:\\n• Implementation: Reviews and interrogates interim freshman success-related data in light of Success Team goals, and strategizes with team leadership around next steps',\n",
126
+ " 'original_content': 'Principal Role:\\n• Implementation: Reviews and interrogates interim freshman success-related data in light of Success Team goals, and strategizes with team leadership around next steps'}"
127
+ ]
128
+ },
129
+ "execution_count": 2,
130
+ "metadata": {},
131
+ "output_type": "execute_result"
132
+ }
133
+ ],
134
+ "source": [
135
+ "# Import the functions from our custom Python package (now in the path)\n",
136
+ "from fot_recommender.rag_pipeline import (\n",
137
+ " load_knowledge_base,\n",
138
+ " initialize_embedding_model,\n",
139
+ " create_embeddings,\n",
140
+ " create_vector_db,\n",
141
+ " search_interventions,\n",
142
+ ")\n",
143
+ "\n",
144
+ "# Build the path to the knowledge base using the universal project_path variable\n",
145
+ "kb_path = project_path / \"data\" / \"processed\" / \"knowledge_base_final_chunks.json\"\n",
146
+ "\n",
147
+ "# Load the knowledge base\n",
148
+ "knowledge_base_chunks = load_knowledge_base(str(kb_path))\n",
149
+ "\n",
150
+ "print(f\"Successfully loaded {len(knowledge_base_chunks)} intervention chunks.\")\n",
151
+ "knowledge_base_chunks[0]"
152
+ ]
153
+ },
154
+ {
155
+ "cell_type": "code",
156
+ "execution_count": 4,
157
+ "id": "0d3e673f-17db-4308-991a-5f5b12ffb104",
158
+ "metadata": {},
159
+ "outputs": [
160
+ {
161
+ "name": "stdout",
162
+ "output_type": "stream",
163
+ "text": [
164
+ "Initializing embedding model: all-MiniLM-L6-v2...\n",
165
+ "Model initialized successfully.\n",
166
+ "Creating embeddings for 27 chunks...\n"
167
+ ]
168
+ },
169
+ {
170
+ "name": "stderr",
171
+ "output_type": "stream",
172
+ "text": [
173
+ "Batches: 0%| | 0/1 [00:00<?, ?it/s]/Users/charlesfeinn/Developer/job_applications/fot-intervention-recommender/.venv/lib/python3.12/site-packages/torch/nn/modules/module.py:1520: FutureWarning: `encoder_attention_mask` is deprecated and will be removed in version 4.55.0 for `BertSdpaSelfAttention.forward`.\n",
174
+ " return forward_call(*args, **kwargs)\n",
175
+ "Batches: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:02<00:00, 2.03s/it]"
176
+ ]
177
+ },
178
+ {
179
+ "name": "stdout",
180
+ "output_type": "stream",
181
+ "text": [
182
+ "Embeddings created successfully.\n",
183
+ "Creating FAISS index with dimension 384...\n",
184
+ "FAISS index created with 27 vectors.\n"
185
+ ]
186
+ },
187
+ {
188
+ "name": "stderr",
189
+ "output_type": "stream",
190
+ "text": [
191
+ "\n"
192
+ ]
193
+ }
194
+ ],
195
+ "source": [
196
+ "# --- Build the RAG Pipeline Components ---\n",
197
+ "#\n",
198
+ "# Now, we will initialize the core components of our RAG pipeline.\n",
199
+ "# 1. Embedding Model: We'll load the model that converts text into vectors.\n",
200
+ "# 2. Vector Embeddings: We'll encode all our knowledge base chunks.\n",
201
+ "# 3. Vector Database: We'll create a FAISS index for fast searching.\n",
202
+ "#\n",
203
+ "# These components will be stored in variables for the rest of the notebook to use.\n",
204
+ "\n",
205
+ "# 1. Initialize the embedding model\n",
206
+ "embedding_model = initialize_embedding_model()\n",
207
+ "\n",
208
+ "# 2. Create vector embeddings for the knowledge base\n",
209
+ "embeddings = create_embeddings(knowledge_base_chunks, embedding_model)\n",
210
+ "\n",
211
+ "# 3. Set up the FAISS vector database\n",
212
+ "vector_db = create_vector_db(embeddings)"
213
+ ]
214
+ },
215
+ {
216
+ "cell_type": "markdown",
217
+ "id": "c906f11b-9363-4181-91f4-9cb899630caa",
218
+ "metadata": {},
219
+ "source": [
220
+ "## 5. Try It Yourself: Enter Your Own Query\n",
221
+ "\n",
222
+ "Now it's your turn. The system is ready to accept a new query.\n",
223
+ "\n",
224
+ "Describe the challenges of a hypothetical student in the text box below. For example, you could try:\n",
225
+ "- \"A student is missing a lot of school and their grades are suffering.\"\n",
226
+ "- \"This freshman has good attendance but is failing math and science and seems disengaged.\"\n",
227
+ "- \"A student has multiple behavior incidents and is struggling to connect with teachers.\"\n",
228
+ "\n",
229
+ "The RAG system will perform a new semantic search and return the top 3 interventions from the knowledge base that best match your description."
230
+ ]
231
+ },
232
+ {
233
+ "cell_type": "code",
234
+ "execution_count": 5,
235
+ "id": "997c358c-3c9c-486e-88f8-1c032a2ed146",
236
+ "metadata": {},
237
+ "outputs": [
238
+ {
239
+ "name": "stdin",
240
+ "output_type": "stream",
241
+ "text": [
242
+ "Enter a description of a student's challenges: asdf\n"
243
+ ]
244
+ },
245
+ {
246
+ "name": "stdout",
247
+ "output_type": "stream",
248
+ "text": [
249
+ "\n",
250
+ "🔍 Searching for interventions based on your query...\n",
251
+ "\n",
252
+ "Searching for top 3 interventions for query: 'asdf...'\n",
253
+ "Found 0 relevant interventions.\n",
254
+ "\n",
255
+ "No relevant interventions were found for this query.\n"
256
+ ]
257
+ }
258
+ ],
259
+ "source": [
260
+ "from fot_recommender.utils import display_recommendations\n",
261
+ "\n",
262
+ "# Prompt the user to enter their own query\n",
263
+ "user_query = input(\"Enter a description of a student's challenges: \")\n",
264
+ "\n",
265
+ "if user_query:\n",
266
+ " print(\"\\n🔍 Searching for interventions based on your query...\")\n",
267
+ " \n",
268
+ " # Perform a new search using the user's input\n",
269
+ " custom_recommendations = search_interventions(\n",
270
+ " query=user_query,\n",
271
+ " model=embedding_model,\n",
272
+ " index=vector_db,\n",
273
+ " knowledge_base=knowledge_base_chunks,\n",
274
+ " k=3,\n",
275
+ " )\n",
276
+ " \n",
277
+ " # Display the new results using our helper function\n",
278
+ " display_recommendations(custom_recommendations)\n",
279
+ " \n",
280
+ "else:\n",
281
+ " print(\"\\nNo query entered. Skipping custom search.\")"
282
+ ]
283
+ },
284
+ {
285
+ "cell_type": "markdown",
286
+ "id": "142c44e7-b75b-46c7-9267-996e44054529",
287
+ "metadata": {},
288
+ "source": []
289
+ },
290
+ {
291
+ "cell_type": "code",
292
+ "execution_count": null,
293
+ "id": "f7977b72-30a8-4146-b420-d0adb824ab99",
294
+ "metadata": {},
295
+ "outputs": [],
296
+ "source": []
297
+ },
298
+ {
299
+ "cell_type": "markdown",
300
+ "id": "7b6c8adb-df2f-4b7b-b09a-88058d0cd785",
301
+ "metadata": {},
302
+ "source": []
303
+ },
304
+ {
305
+ "cell_type": "code",
306
+ "execution_count": null,
307
+ "id": "665cb647-97da-441f-81b0-ae7b908fdd2f",
308
+ "metadata": {},
309
+ "outputs": [],
310
+ "source": []
311
+ },
312
+ {
313
+ "cell_type": "code",
314
+ "execution_count": null,
315
+ "id": "92729636-bd91-4b0c-ac35-5ed82797a1f2",
316
+ "metadata": {},
317
+ "outputs": [],
318
+ "source": [
319
+ "import shutil\n",
320
+ "from pathlib import Path\n",
321
+ "\n",
322
+ "# The path to the project directory we created at the start\n",
323
+ "project_path_to_clean = Path.cwd() / \"fot-recommender-poc-workspace\"\n",
324
+ "\n",
325
+ "if project_path_to_clean.exists():\n",
326
+ " print(f\"The project directory '{project_path_to_clean}' was found.\")\n",
327
+ " \n",
328
+ " # Ask for user confirmation before deleting anything\n",
329
+ " response = input(\"Would you like to delete the git repository folder that was downloaded during the running of this notebook? (y/n): \")\n",
330
+ " \n",
331
+ " if response.lower().strip() == 'y':\n",
332
+ " try:\n",
333
+ " shutil.rmtree(project_path_to_clean)\n",
334
+ " print(f\"✅ Successfully deleted '{project_path_to_clean}'.\")\n",
335
+ " except OSError as e:\n",
336
+ " print(f\"Error: {e.strerror}. Could not delete the directory.\")\n",
337
+ " else:\n",
338
+ " print(\"Cleanup skipped.\")\n",
339
+ "else:\n",
340
+ " print(\"Project directory not found. Nothing to clean up.\")"
341
+ ]
342
+ },
343
+ {
344
+ "cell_type": "code",
345
+ "execution_count": null,
346
+ "id": "085de4e9-e7d4-4c87-892b-711765a7d8a1",
347
+ "metadata": {},
348
+ "outputs": [],
349
+ "source": []
350
+ }
351
+ ],
352
+ "metadata": {
353
+ "kernelspec": {
354
+ "display_name": "Python 3 (ipykernel)",
355
+ "language": "python",
356
+ "name": "python3"
357
+ },
358
+ "language_info": {
359
+ "codemirror_mode": {
360
+ "name": "ipython",
361
+ "version": 3
362
+ },
363
+ "file_extension": ".py",
364
+ "mimetype": "text/x-python",
365
+ "name": "python",
366
+ "nbconvert_exporter": "python",
367
+ "pygments_lexer": "ipython3",
368
+ "version": "3.12.8"
369
+ }
370
+ },
371
+ "nbformat": 4,
372
+ "nbformat_minor": 5
373
+ }
pyproject.toml CHANGED
@@ -34,6 +34,8 @@ dev = [
34
  "mypy>=1.16.1",
35
  "pytest>=8.4.1",
36
  "ruff>=0.12.2",
 
 
37
  ]
38
 
39
  [tool.setuptools.packages.find]
 
34
  "mypy>=1.16.1",
35
  "pytest>=8.4.1",
36
  "ruff>=0.12.2",
37
+ "jupyterlab>=4.0",
38
+ "notebook>=7.0"
39
  ]
40
 
41
  [tool.setuptools.packages.find]
requirements.txt ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ annotated-types==0.7.0
2
+ anyio==4.10.0
3
+ appnope==0.1.4
4
+ argon2-cffi==25.1.0
5
+ argon2-cffi-bindings==25.1.0
6
+ arrow==1.3.0
7
+ asttokens==3.0.0
8
+ async-lru==2.0.5
9
+ attrs==25.3.0
10
+ babel==2.17.0
11
+ beautifulsoup4==4.13.4
12
+ black==25.1.0
13
+ bleach==6.2.0
14
+ certifi==2025.8.3
15
+ cffi==1.17.1
16
+ charset-normalizer==3.4.2
17
+ click==8.2.1
18
+ comm==0.2.3
19
+ debugpy==1.8.15
20
+ decorator==5.2.1
21
+ defusedxml==0.7.1
22
+ executing==2.2.0
23
+ faiss-cpu==1.11.0.post1
24
+ fastjsonschema==2.21.1
25
+ filelock==3.18.0
26
+ -e file:///Users/charlesfeinn/Developer/job_applications/fot-intervention-recommender
27
+ fqdn==1.5.1
28
+ fsspec==2025.7.0
29
+ greenlet==3.2.3
30
+ h11==0.16.0
31
+ hf-xet==1.1.5
32
+ httpcore==1.0.9
33
+ httpx==0.28.1
34
+ huggingface-hub==0.34.3
35
+ idna==3.10
36
+ iniconfig==2.1.0
37
+ ipykernel==6.30.1
38
+ ipython==9.4.0
39
+ ipython-pygments-lexers==1.1.1
40
+ isoduration==20.11.0
41
+ jedi==0.19.2
42
+ jinja2==3.1.6
43
+ joblib==1.5.1
44
+ json5==0.12.0
45
+ jsonpatch==1.33
46
+ jsonpointer==3.0.0
47
+ jsonschema==4.25.0
48
+ jsonschema-specifications==2025.4.1
49
+ jupyter-client==8.6.3
50
+ jupyter-core==5.8.1
51
+ jupyter-events==0.12.0
52
+ jupyter-lsp==2.2.6
53
+ jupyter-server==2.16.0
54
+ jupyter-server-terminals==0.5.3
55
+ jupyterlab==4.4.5
56
+ jupyterlab-pygments==0.3.0
57
+ jupyterlab-server==2.27.3
58
+ langchain==0.3.27
59
+ langchain-core==0.3.72
60
+ langchain-text-splitters==0.3.9
61
+ langsmith==0.4.10
62
+ lark==1.2.2
63
+ markupsafe==3.0.2
64
+ matplotlib-inline==0.1.7
65
+ mistune==3.1.3
66
+ mpmath==1.3.0
67
+ mypy==1.17.1
68
+ mypy-extensions==1.1.0
69
+ nbclient==0.10.2
70
+ nbconvert==7.16.6
71
+ nbformat==5.10.4
72
+ nest-asyncio==1.6.0
73
+ networkx==3.5
74
+ notebook==7.4.5
75
+ notebook-shim==0.2.4
76
+ numpy==1.26.4
77
+ orjson==3.11.1
78
+ overrides==7.7.0
79
+ packaging==25.0
80
+ pandocfilters==1.5.1
81
+ parso==0.8.4
82
+ pathspec==0.12.1
83
+ pexpect==4.9.0
84
+ pillow==11.3.0
85
+ platformdirs==4.3.8
86
+ pluggy==1.6.0
87
+ prometheus-client==0.22.1
88
+ prompt-toolkit==3.0.51
89
+ psutil==7.0.0
90
+ ptyprocess==0.7.0
91
+ pure-eval==0.2.3
92
+ pycparser==2.22
93
+ pydantic==2.11.7
94
+ pydantic-core==2.33.2
95
+ pygments==2.19.2
96
+ pytest==8.4.1
97
+ python-dateutil==2.9.0.post0
98
+ python-json-logger==3.3.0
99
+ pyyaml==6.0.2
100
+ pyzmq==27.0.1
101
+ referencing==0.36.2
102
+ regex==2025.7.34
103
+ requests==2.32.4
104
+ requests-toolbelt==1.0.0
105
+ rfc3339-validator==0.1.4
106
+ rfc3986-validator==0.1.1
107
+ rfc3987-syntax==1.1.0
108
+ rpds-py==0.26.0
109
+ ruff==0.12.7
110
+ safetensors==0.5.3
111
+ scikit-learn==1.7.1
112
+ scipy==1.16.1
113
+ send2trash==1.8.3
114
+ sentence-transformers==5.0.0
115
+ setuptools==80.9.0
116
+ six==1.17.0
117
+ sniffio==1.3.1
118
+ soupsieve==2.7
119
+ sqlalchemy==2.0.42
120
+ stack-data==0.6.3
121
+ sympy==1.14.0
122
+ tenacity==9.1.2
123
+ terminado==0.18.1
124
+ threadpoolctl==3.6.0
125
+ tinycss2==1.4.0
126
+ tokenizers==0.21.4
127
+ torch==2.2.2
128
+ tornado==6.5.1
129
+ tqdm==4.67.1
130
+ traitlets==5.14.3
131
+ transformers==4.54.1
132
+ types-python-dateutil==2.9.0.20250708
133
+ typing-extensions==4.14.1
134
+ typing-inspection==0.4.1
135
+ uri-template==1.3.0
136
+ urllib3==2.5.0
137
+ wcwidth==0.2.13
138
+ webcolors==24.11.1
139
+ webencodings==0.5.1
140
+ websocket-client==1.8.0
141
+ zstandard==0.23.0
src/fot_recommender/utils.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import List, Dict, Any, Tuple
2
+
3
+ def display_recommendations(results: List[Tuple[Dict[str, Any], float]]):
4
+ """
5
+ A helper function to neatly print the results of a semantic search.
6
+ This function is designed to be called from a notebook or a command-line script.
7
+
8
+ Args:
9
+ results: A list of tuples, where each tuple contains a result chunk (dict)
10
+ and its similarity score (float).
11
+ """
12
+ if not results:
13
+ print("\nNo relevant interventions were found for this query.")
14
+ return
15
+
16
+ print("\n--- Top Recommended Interventions ---")
17
+ for i, (chunk, score) in enumerate(results):
18
+ print(f"\n--- Recommendation {i + 1} (Similarity Score: {score:.4f}) ---")
19
+ print(f" Title: {chunk['title']}")
20
+ print(f" Source: {chunk['source_document']} ({chunk['fot_pages']})")
21
+
22
+ # Indent the content for better readability
23
+ content = chunk['original_content']
24
+ indented_content = "\n ".join(content.splitlines())
25
+ print(f" \n Content Snippet:\n \"{indented_content[:500]}...\"")
26
+ print("-" * 50)
uv.lock CHANGED
The diff for this file is too large to render. See raw diff