├── src
└── ollama_rag
│ ├── __init__.py
│ └── helpers.py
├── documents
├── README.md
└── Searle (1980) - The Chinese Room.pdf
├── .vscode
├── extensions.json
└── launch.json
├── .gitignore
├── ollama-rag.code-workspace
├── pyproject.toml
├── README.md
├── requirements.lock
└── requirements-dev.lock
/src/ollama_rag/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/documents/README.md:
--------------------------------------------------------------------------------
1 | Place your document(s) here.
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "ms-python.python"
4 | ]
5 | }
--------------------------------------------------------------------------------
/documents/Searle (1980) - The Chinese Room.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chapagain/ai-discipline-ollama-rag/main/documents/Searle (1980) - The Chinese Room.pdf
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # python generated files
2 | __pycache__/
3 | *.py[oc]
4 | build/
5 | dist/
6 | wheels/
7 | *.egg-info
8 |
9 | # venv
10 | .venv
11 |
12 | .document_store_cache
--------------------------------------------------------------------------------
/ollama-rag.code-workspace:
--------------------------------------------------------------------------------
1 | {
2 | "folders": [
3 | {
4 | "path": "."
5 | }
6 | ],
7 | "settings": {},
8 | "launch": {
9 | "version": "0.2.0",
10 | "configurations": []
11 | }
12 | }
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "Python Debugger: Launch App",
9 | "type": "debugpy",
10 | "request": "launch",
11 | "module": "ollama_rag"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "ollama-rag"
3 | version = "0.1.0"
4 | description = "Add your description here"
5 | authors = [
6 | { name = "Kyle Alan Hale", email = "khale@rightpoint.com" }
7 | ]
8 | dependencies = [
9 | "gradio>=4.22.0",
10 | "ollama>=0.1.7",
11 | "haystack-ai>=2.0.0",
12 | "ollama-haystack>=0.0.5",
13 | "pypdf>=4.1.0",
14 | ]
15 | readme = "README.md"
16 | requires-python = ">= 3.11"
17 |
18 | [build-system]
19 | requires = ["hatchling"]
20 | build-backend = "hatchling.build"
21 |
22 | [tool.rye]
23 | managed = true
24 | dev-dependencies = []
25 |
26 | [tool.hatch.metadata]
27 | allow-direct-references = true
28 |
29 | [tool.hatch.build.targets.wheel]
30 | packages = ["src/ollama_rag"]
31 |
--------------------------------------------------------------------------------
/src/ollama_rag/helpers.py:
--------------------------------------------------------------------------------
1 | from haystack import Document
2 | from haystack.document_stores.in_memory import InMemoryDocumentStore
3 | from haystack.document_stores.types import DuplicatePolicy
4 | from typing import Dict, List, Literal
5 | from pathlib import Path
6 | import json
7 |
8 |
9 | class CachedInMemoryDocumentStore(InMemoryDocumentStore):
10 | def __init__(self, bm25_tokenization_regex: str = r"(?u)\b\w\w+\b", bm25_algorithm: Literal['BM25Okapi'] | Literal['BM25L'] | Literal['BM25Plus'] = "BM25L", bm25_parameters: Dict | None = None, embedding_similarity_function: Literal['dot_product'] | Literal['cosine'] = "dot_product"):
11 | super().__init__(bm25_tokenization_regex, bm25_algorithm, bm25_parameters, embedding_similarity_function)
12 |
13 | self.cache_path = Path(__file__).parent.parent.parent / '.document_store_cache'
14 | self.cached = False
15 | self._load_cache()
16 |
17 | def write_documents(self, documents: List[Document], policy: DuplicatePolicy = DuplicatePolicy.NONE) -> int:
18 | documents = super().write_documents(documents, policy)
19 | self._write_cache()
20 | return documents
21 |
22 | def _load_cache(self):
23 | if self.cache_path.exists():
24 | with open(self.cache_path, 'r') as cache:
25 | documents = [Document.from_dict(document) for document in json.load(cache)]
26 | self.write_documents(documents)
27 | self.cached = True
28 |
29 | def _write_cache(self):
30 | with open(self.cache_path, 'w') as cache:
31 | documents = [document.to_dict() for document in self.storage.values()]
32 | json.dump(documents, cache)
33 | self.cached = True
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AI Discipline Code-Along: Ollama RAG
2 | 27 Mar 2024
3 |
4 | This code-along will focus on a simple RAG implementation that runs locally on your machine using [Ollama](https://ollama.com/). In addition to installing the dependencies below, choose a document with text content that you want to chat with the model about, and store it as a PDF in the `documents` directory. Haystack has support for other document converters as well, although you may need to install additional dependencies. This code-along will assume you're using a PDF.
5 |
6 | ## Dependencies
7 |
8 | * Python 3.11+ (Rye will automatically use 3.11 by default; see below)
9 | * VS Code () with the Python extension (search in Extensions in the side bar)
10 | * Rye (), to manage the project’s Python third-party dependencies and Python interpreter version. For Windows users, you’ll likely want to use the 64-bit installer.
11 | * Ollama ()
12 |
13 | ## Setup
14 | First, clone this repo, and open the `ollama-rag.code-workspace` file in VS Code.
15 |
16 | From the terminal in VS Code, install the Python dependencies using Rye:
17 |
18 | ```shell
19 | $ rye sync
20 | ```
21 |
22 | This will install the following Python dependencies in a virtual environment: `gradio ollama haystack-ai ollama-haystack pypdf`. If VS Code prompts you to select the new environment for the workspace, say yes.
23 |
24 | Next, use Ollama to pull down the models you want to use. Do these two, at least:
25 |
26 | ```shell
27 | $ ollama pull llama2
28 | $ ollama pull nomic-embed-text
29 | ```
30 |
31 | Test it out by chatting with it on the command line:
32 |
33 | ```shell
34 | $ ollama run llama2
35 | ```
36 |
37 | If you’d like, check out the supported models at and pull any that you’d like to try. Unless you have a powerful GPU, it’s recommended that you use models in the 7b-parameter and under category. If your machine only supports running on CPU and you want to speed that up, there are smaller models such as `gemma:2b` that you can try, although the performance will not be as good. In general, the more parameters the model has, the better its accuracy, the more resources it requires, and the more slowly it runs. I’ll be doing the code-along with the `llama2:7b` model, but feel free to experiment and use what you like best!
38 |
--------------------------------------------------------------------------------
/requirements.lock:
--------------------------------------------------------------------------------
1 | # generated by rye
2 | # use `rye lock` or `rye sync` to update this lockfile
3 | #
4 | # last locked with the following flags:
5 | # pre: false
6 | # features: []
7 | # all-features: false
8 | # with-sources: false
9 |
10 | -e file:.
11 | aiofiles==23.2.1
12 | # via gradio
13 | altair==5.2.0
14 | # via gradio
15 | annotated-types==0.6.0
16 | # via pydantic
17 | anyio==4.3.0
18 | # via httpx
19 | # via openai
20 | # via starlette
21 | attrs==23.2.0
22 | # via jsonschema
23 | # via referencing
24 | backoff==2.2.1
25 | # via posthog
26 | boilerpy3==1.0.7
27 | # via haystack-ai
28 | certifi==2024.2.2
29 | # via httpcore
30 | # via httpx
31 | # via requests
32 | charset-normalizer==3.3.2
33 | # via requests
34 | click==8.1.7
35 | # via typer
36 | # via uvicorn
37 | colorama==0.4.6
38 | # via typer
39 | contourpy==1.2.0
40 | # via matplotlib
41 | cycler==0.12.1
42 | # via matplotlib
43 | distro==1.9.0
44 | # via openai
45 | fastapi==0.110.0
46 | # via gradio
47 | ffmpy==0.3.2
48 | # via gradio
49 | filelock==3.13.1
50 | # via huggingface-hub
51 | fonttools==4.50.0
52 | # via matplotlib
53 | fsspec==2024.3.1
54 | # via gradio-client
55 | # via huggingface-hub
56 | gradio==4.22.0
57 | # via ollama-rag
58 | gradio-client==0.13.0
59 | # via gradio
60 | h11==0.14.0
61 | # via httpcore
62 | # via uvicorn
63 | haystack-ai==2.0.0
64 | # via ollama-haystack
65 | # via ollama-rag
66 | haystack-bm25==1.0.2
67 | # via haystack-ai
68 | httpcore==1.0.4
69 | # via httpx
70 | httpx==0.25.2
71 | # via gradio
72 | # via gradio-client
73 | # via ollama
74 | # via openai
75 | huggingface-hub==0.21.4
76 | # via gradio
77 | # via gradio-client
78 | idna==3.6
79 | # via anyio
80 | # via httpx
81 | # via requests
82 | importlib-resources==6.4.0
83 | # via gradio
84 | jinja2==3.1.3
85 | # via altair
86 | # via gradio
87 | # via haystack-ai
88 | jsonschema==4.21.1
89 | # via altair
90 | jsonschema-specifications==2023.12.1
91 | # via jsonschema
92 | kiwisolver==1.4.5
93 | # via matplotlib
94 | lazy-imports==0.3.1
95 | # via haystack-ai
96 | markdown-it-py==3.0.0
97 | # via rich
98 | markupsafe==2.1.5
99 | # via gradio
100 | # via jinja2
101 | matplotlib==3.8.3
102 | # via gradio
103 | mdurl==0.1.2
104 | # via markdown-it-py
105 | monotonic==1.6
106 | # via posthog
107 | more-itertools==10.2.0
108 | # via haystack-ai
109 | networkx==3.2.1
110 | # via haystack-ai
111 | numpy==1.26.4
112 | # via altair
113 | # via contourpy
114 | # via gradio
115 | # via haystack-ai
116 | # via haystack-bm25
117 | # via matplotlib
118 | # via pandas
119 | ollama==0.1.7
120 | # via ollama-rag
121 | ollama-haystack==0.0.5
122 | # via ollama-rag
123 | openai==1.14.2
124 | # via haystack-ai
125 | orjson==3.9.15
126 | # via gradio
127 | packaging==24.0
128 | # via altair
129 | # via gradio
130 | # via gradio-client
131 | # via huggingface-hub
132 | # via matplotlib
133 | pandas==2.2.1
134 | # via altair
135 | # via gradio
136 | # via haystack-ai
137 | pillow==10.2.0
138 | # via gradio
139 | # via matplotlib
140 | posthog==3.5.0
141 | # via haystack-ai
142 | pydantic==2.6.4
143 | # via fastapi
144 | # via gradio
145 | # via openai
146 | pydantic-core==2.16.3
147 | # via pydantic
148 | pydub==0.25.1
149 | # via gradio
150 | pygments==2.17.2
151 | # via rich
152 | pyparsing==3.1.2
153 | # via matplotlib
154 | pypdf==4.1.0
155 | # via ollama-rag
156 | python-dateutil==2.9.0.post0
157 | # via haystack-ai
158 | # via matplotlib
159 | # via pandas
160 | # via posthog
161 | python-multipart==0.0.9
162 | # via gradio
163 | pytz==2024.1
164 | # via pandas
165 | pyyaml==6.0.1
166 | # via gradio
167 | # via haystack-ai
168 | # via huggingface-hub
169 | referencing==0.34.0
170 | # via jsonschema
171 | # via jsonschema-specifications
172 | requests==2.31.0
173 | # via haystack-ai
174 | # via huggingface-hub
175 | # via ollama-haystack
176 | # via posthog
177 | rich==13.7.1
178 | # via typer
179 | rpds-py==0.18.0
180 | # via jsonschema
181 | # via referencing
182 | ruff==0.3.4
183 | # via gradio
184 | semantic-version==2.10.0
185 | # via gradio
186 | shellingham==1.5.4
187 | # via typer
188 | six==1.16.0
189 | # via posthog
190 | # via python-dateutil
191 | sniffio==1.3.1
192 | # via anyio
193 | # via httpx
194 | # via openai
195 | starlette==0.36.3
196 | # via fastapi
197 | tenacity==8.2.3
198 | # via haystack-ai
199 | tomlkit==0.12.0
200 | # via gradio
201 | toolz==0.12.1
202 | # via altair
203 | tqdm==4.66.2
204 | # via haystack-ai
205 | # via huggingface-hub
206 | # via openai
207 | typer==0.10.0
208 | # via gradio
209 | typing-extensions==4.10.0
210 | # via fastapi
211 | # via gradio
212 | # via gradio-client
213 | # via haystack-ai
214 | # via huggingface-hub
215 | # via openai
216 | # via pydantic
217 | # via pydantic-core
218 | # via typer
219 | tzdata==2024.1
220 | # via pandas
221 | urllib3==2.2.1
222 | # via requests
223 | uvicorn==0.29.0
224 | # via gradio
225 | websockets==11.0.3
226 | # via gradio-client
227 |
--------------------------------------------------------------------------------
/requirements-dev.lock:
--------------------------------------------------------------------------------
1 | # generated by rye
2 | # use `rye lock` or `rye sync` to update this lockfile
3 | #
4 | # last locked with the following flags:
5 | # pre: false
6 | # features: []
7 | # all-features: false
8 | # with-sources: false
9 |
10 | -e file:.
11 | aiofiles==23.2.1
12 | # via gradio
13 | altair==5.2.0
14 | # via gradio
15 | annotated-types==0.6.0
16 | # via pydantic
17 | anyio==4.3.0
18 | # via httpx
19 | # via openai
20 | # via starlette
21 | attrs==23.2.0
22 | # via jsonschema
23 | # via referencing
24 | backoff==2.2.1
25 | # via posthog
26 | boilerpy3==1.0.7
27 | # via haystack-ai
28 | certifi==2024.2.2
29 | # via httpcore
30 | # via httpx
31 | # via requests
32 | charset-normalizer==3.3.2
33 | # via requests
34 | click==8.1.7
35 | # via typer
36 | # via uvicorn
37 | colorama==0.4.6
38 | # via typer
39 | contourpy==1.2.0
40 | # via matplotlib
41 | cycler==0.12.1
42 | # via matplotlib
43 | distro==1.9.0
44 | # via openai
45 | fastapi==0.110.0
46 | # via gradio
47 | ffmpy==0.3.2
48 | # via gradio
49 | filelock==3.13.1
50 | # via huggingface-hub
51 | fonttools==4.50.0
52 | # via matplotlib
53 | fsspec==2024.3.1
54 | # via gradio-client
55 | # via huggingface-hub
56 | gradio==4.22.0
57 | # via ollama-rag
58 | gradio-client==0.13.0
59 | # via gradio
60 | h11==0.14.0
61 | # via httpcore
62 | # via uvicorn
63 | haystack-ai==2.0.0
64 | # via ollama-haystack
65 | # via ollama-rag
66 | haystack-bm25==1.0.2
67 | # via haystack-ai
68 | httpcore==1.0.4
69 | # via httpx
70 | httpx==0.25.2
71 | # via gradio
72 | # via gradio-client
73 | # via ollama
74 | # via openai
75 | huggingface-hub==0.21.4
76 | # via gradio
77 | # via gradio-client
78 | idna==3.6
79 | # via anyio
80 | # via httpx
81 | # via requests
82 | importlib-resources==6.4.0
83 | # via gradio
84 | jinja2==3.1.3
85 | # via altair
86 | # via gradio
87 | # via haystack-ai
88 | jsonschema==4.21.1
89 | # via altair
90 | jsonschema-specifications==2023.12.1
91 | # via jsonschema
92 | kiwisolver==1.4.5
93 | # via matplotlib
94 | lazy-imports==0.3.1
95 | # via haystack-ai
96 | markdown-it-py==3.0.0
97 | # via rich
98 | markupsafe==2.1.5
99 | # via gradio
100 | # via jinja2
101 | matplotlib==3.8.3
102 | # via gradio
103 | mdurl==0.1.2
104 | # via markdown-it-py
105 | monotonic==1.6
106 | # via posthog
107 | more-itertools==10.2.0
108 | # via haystack-ai
109 | networkx==3.2.1
110 | # via haystack-ai
111 | numpy==1.26.4
112 | # via altair
113 | # via contourpy
114 | # via gradio
115 | # via haystack-ai
116 | # via haystack-bm25
117 | # via matplotlib
118 | # via pandas
119 | ollama==0.1.7
120 | # via ollama-rag
121 | ollama-haystack==0.0.5
122 | # via ollama-rag
123 | openai==1.14.2
124 | # via haystack-ai
125 | orjson==3.9.15
126 | # via gradio
127 | packaging==24.0
128 | # via altair
129 | # via gradio
130 | # via gradio-client
131 | # via huggingface-hub
132 | # via matplotlib
133 | pandas==2.2.1
134 | # via altair
135 | # via gradio
136 | # via haystack-ai
137 | pillow==10.2.0
138 | # via gradio
139 | # via matplotlib
140 | posthog==3.5.0
141 | # via haystack-ai
142 | pydantic==2.6.4
143 | # via fastapi
144 | # via gradio
145 | # via openai
146 | pydantic-core==2.16.3
147 | # via pydantic
148 | pydub==0.25.1
149 | # via gradio
150 | pygments==2.17.2
151 | # via rich
152 | pyparsing==3.1.2
153 | # via matplotlib
154 | pypdf==4.1.0
155 | # via ollama-rag
156 | python-dateutil==2.9.0.post0
157 | # via haystack-ai
158 | # via matplotlib
159 | # via pandas
160 | # via posthog
161 | python-multipart==0.0.9
162 | # via gradio
163 | pytz==2024.1
164 | # via pandas
165 | pyyaml==6.0.1
166 | # via gradio
167 | # via haystack-ai
168 | # via huggingface-hub
169 | referencing==0.34.0
170 | # via jsonschema
171 | # via jsonschema-specifications
172 | requests==2.31.0
173 | # via haystack-ai
174 | # via huggingface-hub
175 | # via ollama-haystack
176 | # via posthog
177 | rich==13.7.1
178 | # via typer
179 | rpds-py==0.18.0
180 | # via jsonschema
181 | # via referencing
182 | ruff==0.3.4
183 | # via gradio
184 | semantic-version==2.10.0
185 | # via gradio
186 | shellingham==1.5.4
187 | # via typer
188 | six==1.16.0
189 | # via posthog
190 | # via python-dateutil
191 | sniffio==1.3.1
192 | # via anyio
193 | # via httpx
194 | # via openai
195 | starlette==0.36.3
196 | # via fastapi
197 | tenacity==8.2.3
198 | # via haystack-ai
199 | tomlkit==0.12.0
200 | # via gradio
201 | toolz==0.12.1
202 | # via altair
203 | tqdm==4.66.2
204 | # via haystack-ai
205 | # via huggingface-hub
206 | # via openai
207 | typer==0.10.0
208 | # via gradio
209 | typing-extensions==4.10.0
210 | # via fastapi
211 | # via gradio
212 | # via gradio-client
213 | # via haystack-ai
214 | # via huggingface-hub
215 | # via openai
216 | # via pydantic
217 | # via pydantic-core
218 | # via typer
219 | tzdata==2024.1
220 | # via pandas
221 | urllib3==2.2.1
222 | # via requests
223 | uvicorn==0.29.0
224 | # via gradio
225 | websockets==11.0.3
226 | # via gradio-client
227 |
--------------------------------------------------------------------------------