Omar Solano commited on
Commit
0769f39
Β·
1 Parent(s): 7e6a905

update gradio-ui

Browse files
Files changed (5) hide show
  1. README.md +1 -1
  2. requirements.txt +15 -204
  3. scripts/create_db.ipynb +723 -142
  4. scripts/gradio-ui.py +117 -127
  5. scripts/tutor_prompts.py +42 -19
README.md CHANGED
@@ -4,7 +4,7 @@ emoji: πŸ§‘πŸ»β€πŸ«
4
  colorFrom: gray
5
  colorTo: pink
6
  sdk: gradio
7
- sdk_version: 4.31.3
8
  app_file: scripts/gradio-ui.py
9
  pinned: false
10
  ---
 
4
  colorFrom: gray
5
  colorTo: pink
6
  sdk: gradio
7
+ sdk_version: 4.38.1
8
  app_file: scripts/gradio-ui.py
9
  pinned: false
10
  ---
requirements.txt CHANGED
@@ -1,204 +1,15 @@
1
- aiofiles==23.2.1
2
- aiohttp==3.9.5
3
- aiosignal==1.3.1
4
- altair==5.3.0
5
- annotated-types==0.6.0
6
- anyio==4.3.0
7
- appnope==0.1.4
8
- asgiref==3.8.1
9
- asttokens==2.4.1
10
- attrs==23.2.0
11
- backoff==2.2.1
12
- bcrypt==4.1.3
13
- beautifulsoup4==4.12.3
14
- boto3==1.34.107
15
- botocore==1.34.107
16
- build==1.2.1
17
- cachetools==5.3.3
18
- certifi==2024.2.2
19
- charset-normalizer==3.3.2
20
- chroma-hnswlib==0.7.3
21
- chromadb==0.5.0
22
- click==8.1.7
23
- cohere==5.5.0
24
- coloredlogs==15.0.1
25
- comm==0.2.2
26
- contourpy==1.2.1
27
- cycler==0.12.1
28
- dataclasses-json==0.6.6
29
- debugpy==1.8.1
30
- decorator==5.1.1
31
- deprecated==1.2.14
32
- dirtyjson==1.0.8
33
- distro==1.9.0
34
- dnspython==2.6.1
35
- docstring-parser==0.16
36
- email-validator==2.1.1
37
- executing==2.0.1
38
- fastapi==0.111.0
39
- fastapi-cli==0.0.3
40
- fastavro==1.9.4
41
- ffmpy==0.3.2
42
- filelock==3.14.0
43
- flatbuffers==24.3.25
44
- fonttools==4.51.0
45
- frozenlist==1.4.1
46
- fsspec==2024.5.0
47
- google-auth==2.29.0
48
- googleapis-common-protos==1.63.0
49
- gradio==4.31.3
50
- gradio-client==0.16.3
51
- greenlet==3.0.3
52
- grpcio==1.63.0
53
- h11==0.14.0
54
- html2text==2024.2.26
55
- httpcore==1.0.5
56
- httptools==0.6.1
57
- httpx==0.27.0
58
- httpx-sse==0.4.0
59
- huggingface-hub==0.23.0
60
- humanfriendly==10.0
61
- idna==3.7
62
- importlib-metadata==7.0.0
63
- importlib-resources==6.4.0
64
- instructor==1.2.6
65
- ipykernel==6.29.4
66
- ipython==8.24.0
67
- jedi==0.19.1
68
- jinja2==3.1.4
69
- jmespath==1.0.1
70
- joblib==1.4.2
71
- jsonschema==4.22.0
72
- jsonschema-specifications==2023.12.1
73
- jupyter-client==8.6.1
74
- jupyter-core==5.7.2
75
- kaleido==0.2.1
76
- kiwisolver==1.4.5
77
- kubernetes==29.0.0
78
- llama-index==0.10.37
79
- llama-index-agent-openai==0.2.5
80
- llama-index-cli==0.1.12
81
- llama-index-core==0.10.36
82
- llama-index-embeddings-openai==0.1.9
83
- llama-index-indices-managed-llama-cloud==0.1.6
84
- llama-index-legacy==0.9.48
85
- llama-index-llms-openai==0.1.19
86
- llama-index-multi-modal-llms-openai==0.1.6
87
- llama-index-program-openai==0.1.6
88
- llama-index-question-gen-openai==0.1.3
89
- llama-index-readers-file==0.1.22
90
- llama-index-readers-llama-parse==0.1.4
91
- llama-index-vector-stores-chroma==0.1.8
92
- llama-parse==0.4.3
93
- llamaindex-py-client==0.1.19
94
- markdown-it-py==3.0.0
95
- markupsafe==2.1.5
96
- marshmallow==3.21.2
97
- matplotlib==3.9.0
98
- matplotlib-inline==0.1.7
99
- mdurl==0.1.2
100
- mmh3==4.1.0
101
- monotonic==1.6
102
- mpmath==1.3.0
103
- multidict==6.0.5
104
- mypy-extensions==1.0.0
105
- nest-asyncio==1.6.0
106
- networkx==3.3
107
- nltk==3.8.1
108
- numpy==1.26.4
109
- oauthlib==3.2.2
110
- onnxruntime==1.17.3
111
- openai==1.30.1
112
- opentelemetry-api==1.24.0
113
- opentelemetry-exporter-otlp-proto-common==1.24.0
114
- opentelemetry-exporter-otlp-proto-grpc==1.24.0
115
- opentelemetry-instrumentation==0.45b0
116
- opentelemetry-instrumentation-asgi==0.45b0
117
- opentelemetry-instrumentation-fastapi==0.45b0
118
- opentelemetry-proto==1.24.0
119
- opentelemetry-sdk==1.24.0
120
- opentelemetry-semantic-conventions==0.45b0
121
- opentelemetry-util-http==0.45b0
122
- orjson==3.10.3
123
- overrides==7.7.0
124
- packaging==24.0
125
- pandas==2.2.2
126
- parso==0.8.4
127
- pexpect==4.9.0
128
- pillow==10.3.0
129
- platformdirs==4.2.2
130
- posthog==3.5.0
131
- prompt-toolkit==3.0.43
132
- protobuf==4.25.3
133
- psutil==5.9.8
134
- ptyprocess==0.7.0
135
- pure-eval==0.2.2
136
- pyarrow==16.1.0
137
- pyasn1==0.6.0
138
- pyasn1-modules==0.4.0
139
- pydantic==2.7.1
140
- pydantic-core==2.18.2
141
- pydub==0.25.1
142
- pygments==2.18.0
143
- pymongo==4.7.2
144
- pyparsing==3.1.2
145
- pypdf==4.2.0
146
- pypika==0.48.9
147
- pyproject-hooks==1.1.0
148
- python-dateutil==2.9.0.post0
149
- python-dotenv==1.0.1
150
- python-multipart==0.0.9
151
- pytz==2024.1
152
- pyyaml==6.0.1
153
- pyzmq==26.0.3
154
- referencing==0.35.1
155
- regex==2024.5.15
156
- requests==2.31.0
157
- requests-oauthlib==2.0.0
158
- rich==13.7.1
159
- rpds-py==0.18.1
160
- rsa==4.9
161
- ruff==0.4.4
162
- s3transfer==0.10.1
163
- safetensors==0.4.3
164
- scikit-learn==1.4.2
165
- scipy==1.13.0
166
- semantic-version==2.10.0
167
- sentence-transformers==2.7.0
168
- setuptools==69.5.1
169
- shellingham==1.5.4
170
- six==1.16.0
171
- sniffio==1.3.1
172
- soupsieve==2.5
173
- sqlalchemy==2.0.30
174
- stack-data==0.6.3
175
- starlette==0.37.2
176
- striprtf==0.0.26
177
- sympy==1.12
178
- tenacity==8.3.0
179
- threadpoolctl==3.5.0
180
- tiktoken==0.7.0
181
- tokenizers==0.19.1
182
- tomlkit==0.12.0
183
- toolz==0.12.1
184
- torch==2.3.0
185
- tornado==6.4
186
- tqdm==4.66.4
187
- traitlets==5.14.3
188
- transformers==4.40.2
189
- typer==0.12.3
190
- types-requests==2.31.0.20240406
191
- typing-extensions==4.11.0
192
- typing-inspect==0.9.0
193
- tzdata==2024.1
194
- ujson==5.10.0
195
- urllib3==2.2.1
196
- uvicorn==0.29.0
197
- uvloop==0.19.0
198
- watchfiles==0.21.0
199
- wcwidth==0.2.13
200
- websocket-client==1.8.0
201
- websockets==11.0.3
202
- wrapt==1.16.0
203
- yarl==1.9.4
204
- zipp==3.18.2
 
1
+ openai
2
+ chromadb
3
+ tiktoken
4
+ ipykernel
5
+ google-cloud-aiplatform
6
+ google-generativeai
7
+ llama-index-vector-stores-chroma
8
+ llama-index
9
+ llama-index-llms-vertex
10
+ llama-index-llms-gemini
11
+ langchain
12
+ langchain-chroma
13
+ langchain_openai
14
+ gradio
15
+ instructor
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
scripts/create_db.ipynb CHANGED
@@ -9,9 +9,20 @@
9
  },
10
  {
11
  "cell_type": "code",
12
- "execution_count": null,
13
  "metadata": {},
14
- "outputs": [],
 
 
 
 
 
 
 
 
 
 
 
15
  "source": [
16
  "from dotenv import load_dotenv\n",
17
  "\n",
@@ -20,7 +31,7 @@
20
  },
21
  {
22
  "cell_type": "code",
23
- "execution_count": null,
24
  "metadata": {},
25
  "outputs": [],
26
  "source": [
@@ -33,16 +44,27 @@
33
  "cell_type": "markdown",
34
  "metadata": {},
35
  "source": [
36
- "### Clean data\n"
 
37
  ]
38
  },
39
  {
40
  "cell_type": "code",
41
- "execution_count": null,
42
  "metadata": {},
43
- "outputs": [],
 
 
 
 
 
 
 
 
 
44
  "source": [
45
  "import json\n",
 
46
  "import tiktoken\n",
47
  "from collections import OrderedDict\n",
48
  "\n",
@@ -72,7 +94,9 @@
72
  " token_count == 92 and json_obj.get(\"name\") == \"Transformers\"\n",
73
  " ):\n",
74
  " # Create a new OrderedDict with 'tokens' as the first key\n",
75
- " new_obj = OrderedDict([(\"tokens\", token_count)])\n",
 
 
76
  " # Add the rest of the key-value pairs from the original object\n",
77
  " new_obj.update(json_obj)\n",
78
  " cleaned_data.append(new_obj)\n",
@@ -96,14 +120,14 @@
96
  "cell_type": "markdown",
97
  "metadata": {},
98
  "source": [
99
- "### Merges lines by 'URL' and creates a new file with the merged data.\n",
100
  "\n",
101
- "Fixes the 'name'\n"
102
  ]
103
  },
104
  {
105
  "cell_type": "code",
106
- "execution_count": null,
107
  "metadata": {},
108
  "outputs": [],
109
  "source": [
@@ -173,65 +197,29 @@
173
  "cell_type": "markdown",
174
  "metadata": {},
175
  "source": [
176
- "### Count tokens of lines in merged file\n"
177
  ]
178
  },
179
  {
180
  "cell_type": "code",
181
- "execution_count": null,
182
  "metadata": {},
183
- "outputs": [],
184
- "source": [
185
- "# import json\n",
186
- "# import tiktoken\n",
187
- "\n",
188
- "\n",
189
- "# def num_tokens_from_string(string: str, encoding_name: str) -> int:\n",
190
- "# \"\"\"Returns the number of tokens in a text string.\"\"\"\n",
191
- "# encoding = tiktoken.get_encoding(encoding_name)\n",
192
- "# num_tokens = len(\n",
193
- "# encoding.encode(\n",
194
- "# string, disallowed_special=(encoding.special_tokens_set - {\"<|endoftext|>\"})\n",
195
- "# )\n",
196
- "# )\n",
197
- "# return num_tokens\n",
198
- "\n",
199
- "\n",
200
- "# def count_tokens(input_file):\n",
201
- "\n",
202
- "# # Read and process the input file\n",
203
- "# with open(input_file, \"r\") as f:\n",
204
- "# for i, line in enumerate(f):\n",
205
- "# data = json.loads(line)\n",
206
- "# content = data[\"content\"]\n",
207
- "# nb_tokens = num_tokens_from_string(content, \"cl100k_base\")\n",
208
- "# # print(i + 1, data[\"url\"], nb_tokens)\n",
209
- "# if nb_tokens > 2000:\n",
210
- "# print(i + 1, data[\"url\"], data[\"name\"], nb_tokens)\n",
211
- "# # if nb_tokens < 8:\n",
212
- "# # print(nb_tokens)\n",
213
- "# # print(data[\"url\"])\n",
214
- "# # print(data[\"content\"])\n",
215
- "\n",
216
- "\n",
217
- "# # Usage\n",
218
- "# input_file = \"../hf_transformers_v4_42_0_merged.jsonl\"\n",
219
- "# # input_file = \"../hf_transformers_v4_42_0.jsonl\"\n",
220
- "# count_tokens(input_file)"
221
- ]
222
- },
223
- {
224
- "cell_type": "markdown",
225
- "metadata": {},
226
- "source": [
227
- "### Create a set of llama-index Documents\n"
228
- ]
229
- },
230
- {
231
- "cell_type": "code",
232
- "execution_count": null,
233
- "metadata": {},
234
- "outputs": [],
235
  "source": [
236
  "from llama_index.core import Document\n",
237
  "from llama_index.core.schema import MetadataMode\n",
@@ -245,24 +233,28 @@
245
  " data = json.loads(line)\n",
246
  " documents.append(\n",
247
  " Document(\n",
 
248
  " text=data[\"content\"],\n",
249
  " metadata={\n",
250
  " \"url\": data[\"url\"],\n",
251
  " \"title\": data[\"name\"],\n",
252
  " \"tokens\": data[\"tokens\"],\n",
253
  " \"retrieve_doc\": data[\"retrieve_doc\"],\n",
 
254
  " },\n",
255
  " excluded_llm_metadata_keys=[\n",
256
  " \"url\",\n",
257
  " \"title\",\n",
258
  " \"tokens\",\n",
259
  " \"retrieve_doc\",\n",
 
260
  " ],\n",
261
  " excluded_embed_metadata_keys=[\n",
262
  " \"url\",\n",
263
  " \"title\",\n",
264
  " \"tokens\",\n",
265
  " \"retrieve_doc\",\n",
 
266
  " ],\n",
267
  " )\n",
268
  " )\n",
@@ -273,35 +265,81 @@
273
  "print(documents[0])\n",
274
  "print(documents[0].metadata)\n",
275
  "\n",
276
- "document_dict = {doc.doc_id: doc for doc in documents}"
 
 
 
 
 
 
 
 
 
277
  ]
278
  },
279
  {
280
  "cell_type": "code",
281
- "execution_count": null,
282
  "metadata": {},
283
  "outputs": [],
284
  "source": [
285
- "# import chromadb\n",
286
  "\n",
287
- "# # create client and a new collection\n",
288
- "# # chromadb.EphemeralClient saves data in-memory.\n",
289
- "# chroma_client = chromadb.PersistentClient(path=\"./ai-tutor-dataset\")\n",
290
- "# chroma_collection = chroma_client.create_collection(\"ai-tutor-dataset\")\n",
291
  "\n",
292
- "# from llama_index.vector_stores.chroma import ChromaVectorStore\n",
293
- "# from llama_index.core import StorageContext\n",
294
  "\n",
295
- "# # Define a storage context object using the created vector database.\n",
296
- "# vector_store = ChromaVectorStore(chroma_collection=chroma_collection)\n",
297
- "# storage_context = StorageContext.from_defaults(vector_store=vector_store)"
298
  ]
299
  },
300
  {
301
  "cell_type": "code",
302
- "execution_count": null,
303
  "metadata": {},
304
- "outputs": [],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
305
  "source": [
306
  "from llama_index.core import VectorStoreIndex\n",
307
  "from llama_index.core.node_parser import SentenceSplitter\n",
@@ -315,25 +353,16 @@
315
  " transformations=[SentenceSplitter(chunk_size=800, chunk_overlap=400)],\n",
316
  " show_progress=True,\n",
317
  " use_async=True,\n",
318
- " # storage_context=storage_context,\n",
319
  ")"
320
  ]
321
  },
322
  {
323
  "cell_type": "code",
324
- "execution_count": null,
325
  "metadata": {},
326
  "outputs": [],
327
  "source": [
328
- "# from llama_index.llms.openai import OpenAI\n",
329
- "\n",
330
- "# llm = OpenAI(temperature=1, model=\"gpt-3.5-turbo\", max_tokens=None)\n",
331
- "# query_engine = index.as_query_engine(\n",
332
- "# llm=llm,\n",
333
- "# similarity_top_k=5,\n",
334
- "# embed_model=OpenAIEmbedding(model=\"text-embedding-3-small\"),\n",
335
- "# use_async=True,\n",
336
- "# )\n",
337
  "retriever = index.as_retriever(\n",
338
  " similarity_top_k=10,\n",
339
  " use_async=True,\n",
@@ -344,15 +373,499 @@
344
  },
345
  {
346
  "cell_type": "code",
347
- "execution_count": null,
348
  "metadata": {},
349
- "outputs": [],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
350
  "source": [
351
  "from llama_index.core.data_structs import Node\n",
352
- "from llama_index.core.schema import NodeWithScore\n",
353
  "\n",
354
- "# res = query_engine.query(\"What is the LLaMa model?\")\n",
355
- "# res.response\n",
356
  "\n",
357
  "# query = \"fine-tune a pretrained model\"\n",
358
  "# query = \"fine-tune an llm\"\n",
@@ -362,17 +875,18 @@
362
  "nodes = retriever.retrieve(query)\n",
363
  "\n",
364
  "\n",
365
- "# # Filter nodes with the same ref_doc_id\n",
366
- "# def filter_nodes_by_unique_doc_id(nodes):\n",
367
- "# unique_nodes = {}\n",
368
- "# for node in nodes:\n",
369
- "# doc_id = node.node.ref_doc_id\n",
370
- "# if doc_id is not None and doc_id not in unique_nodes:\n",
371
- "# unique_nodes[doc_id] = node\n",
372
- "# return list(unique_nodes.values())\n",
373
  "\n",
374
  "\n",
375
- "# nodes = filter_nodes_by_unique_doc_id(nodes)\n",
 
376
  "\n",
377
  "for node in nodes:\n",
378
  " print(\"Node ID\\t\", node.node_id)\n",
@@ -385,73 +899,140 @@
385
  " print(\"This node will be replaced by the document\")\n",
386
  " doc = document_dict[node.node.ref_doc_id]\n",
387
  " # print(doc.text)\n",
388
- " new_node = (\n",
389
- " NodeWithScore(\n",
390
- " node=Node(text=doc.text, metadata=node.metadata), score=node.score\n",
391
- " ),\n",
392
  " )\n",
 
393
  " nodes_context.append(new_node)\n",
394
  " else:\n",
395
- " nodes_context.append(node)"
 
 
396
  ]
397
  },
398
  {
399
  "cell_type": "code",
400
- "execution_count": null,
401
  "metadata": {},
402
  "outputs": [],
403
  "source": [
404
- "# from llama_index.core.schema import TextNode\n",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
405
  "\n",
406
- "# for src in res.source_nodes:\n",
407
- "# print(src.node.ref_doc_id)\n",
408
- "# # print(src.node.get_metadata_str())\n",
409
- "# print(\"Node ID\\t\", src.node_id)\n",
410
- "# print(\"Title\\t\", src.metadata[\"title\"])\n",
411
- "# print(\"Text\\t\", src.text)\n",
412
- "# print(\"Score\\t\", src.score)\n",
413
- "# print(\"Metadata\\t\", src.metadata)\n",
414
- "# print(\"-_\" * 20)\n",
415
- "# break"
416
  ]
417
  },
418
  {
419
  "cell_type": "code",
420
- "execution_count": null,
421
  "metadata": {},
422
- "outputs": [],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
423
  "source": [
 
424
  "from llama_index.core.data_structs import Node\n",
425
  "from llama_index.core.schema import NodeWithScore\n",
426
  "from llama_index.core import get_response_synthesizer\n",
427
  "from llama_index.llms.gemini import Gemini\n",
428
  "from llama_index.llms.openai import OpenAI\n",
429
  "\n",
430
- "from tutor_prompts import (\n",
431
- " TEXT_QA_TEMPLATE,\n",
432
- ")\n",
433
- "\n",
434
- "\n",
435
  "# llm = Gemini(model=\"models/gemini-1.5-flash\", temperature=1, max_tokens=None)\n",
436
- "# llm = Gemini(model=\"models/gemini-1.5-pro\", temperature=1, max_tokens=None)\n",
437
  "# llm = OpenAI(temperature=1, model=\"gpt-3.5-turbo\", max_tokens=None)\n",
438
- "llm = OpenAI(temperature=1, model=\"gpt-4o\", max_tokens=None)\n",
439
  "\n",
440
  "response_synthesizer = get_response_synthesizer(\n",
441
  " llm=llm, response_mode=\"simple_summarize\", text_qa_template=TEXT_QA_TEMPLATE\n",
442
  ")\n",
443
  "\n",
444
- "response = response_synthesizer.synthesize(\n",
445
- " query,\n",
446
- " nodes=nodes,\n",
447
- " # nodes=[\n",
448
- " # NodeWithScore(\n",
449
- " # node=Node(text=\"LLama2 model has a total of 2B parameters.\"), score=1.0\n",
450
- " # ),\n",
451
- " # ],\n",
452
- " # text_chunks=[\"text1\", \"text2\", \"text3\"],\n",
453
- ")\n",
454
- "print(response.response)\n",
455
  "# for src in response.source_nodes:\n",
456
  "# print(src.node.ref_doc_id)\n",
457
  "# print(\"Node ID\\t\", src.node_id)\n",
@@ -658,8 +1239,8 @@
658
  "# from llama_index.vector_stores.chroma import ChromaVectorStore\n",
659
  "\n",
660
  "# # Create your index\n",
661
- "# db2 = chromadb.PersistentClient(path=\"./ai-tutor-db\")\n",
662
- "# chroma_collection = db2.get_or_create_collection(\"ai-tutor-db\")\n",
663
  "# vector_store = ChromaVectorStore(chroma_collection=chroma_collection)"
664
  ]
665
  },
 
9
  },
10
  {
11
  "cell_type": "code",
12
+ "execution_count": 1,
13
  "metadata": {},
14
+ "outputs": [
15
+ {
16
+ "data": {
17
+ "text/plain": [
18
+ "True"
19
+ ]
20
+ },
21
+ "execution_count": 1,
22
+ "metadata": {},
23
+ "output_type": "execute_result"
24
+ }
25
+ ],
26
  "source": [
27
  "from dotenv import load_dotenv\n",
28
  "\n",
 
31
  },
32
  {
33
  "cell_type": "code",
34
+ "execution_count": 2,
35
  "metadata": {},
36
  "outputs": [],
37
  "source": [
 
44
  "cell_type": "markdown",
45
  "metadata": {},
46
  "source": [
47
+ "### Clean scraped data\n",
48
+ "- Removes sections with <7 tokens and sections titled \"Transformers\""
49
  ]
50
  },
51
  {
52
  "cell_type": "code",
53
+ "execution_count": 3,
54
  "metadata": {},
55
+ "outputs": [
56
+ {
57
+ "name": "stdout",
58
+ "output_type": "stream",
59
+ "text": [
60
+ "Original number of lines: 10413\n",
61
+ "Cleaned number of lines: 4123\n"
62
+ ]
63
+ }
64
+ ],
65
  "source": [
66
  "import json\n",
67
+ "import uuid\n",
68
  "import tiktoken\n",
69
  "from collections import OrderedDict\n",
70
  "\n",
 
94
  " token_count == 92 and json_obj.get(\"name\") == \"Transformers\"\n",
95
  " ):\n",
96
  " # Create a new OrderedDict with 'tokens' as the first key\n",
97
+ " new_obj = OrderedDict(\n",
98
+ " [(\"tokens\", token_count), (\"doc_id\", str(uuid.uuid4()))]\n",
99
+ " )\n",
100
  " # Add the rest of the key-value pairs from the original object\n",
101
  " new_obj.update(json_obj)\n",
102
  " cleaned_data.append(new_obj)\n",
 
120
  "cell_type": "markdown",
121
  "metadata": {},
122
  "source": [
123
+ "### Merges sections by 'URL'\n",
124
  "\n",
125
+ "- Excluding sections like \"model_doc\", \"internal\", \"main_classes\"\n"
126
  ]
127
  },
128
  {
129
  "cell_type": "code",
130
+ "execution_count": 4,
131
  "metadata": {},
132
  "outputs": [],
133
  "source": [
 
197
  "cell_type": "markdown",
198
  "metadata": {},
199
  "source": [
200
+ "### Create a set of Llama-index Documents with each section in the jsonl file\n"
201
  ]
202
  },
203
  {
204
  "cell_type": "code",
205
+ "execution_count": 3,
206
  "metadata": {},
207
+ "outputs": [
208
+ {
209
+ "name": "stdout",
210
+ "output_type": "stream",
211
+ "text": [
212
+ "Doc ID: 85b2c5b6-ce24-4e4e-8a2d-d6557c917012\n",
213
+ "Text: DeepSpeed is a PyTorch optimization library that makes\n",
214
+ "distributed training memory-efficient and fast. At it’s core is the\n",
215
+ "Zero Redundancy Optimizer (ZeRO) which enables training large models\n",
216
+ "at scale. ZeRO works in several stages: ZeRO-1, optimizer state\n",
217
+ "partioning across GPUs ZeRO-2, gradient partitioning across GPUs\n",
218
+ "ZeRO-3, parameteter partit...\n",
219
+ "{'url': 'https://huggingface.co/docs/transformers/deepspeed', 'title': 'DeepSpeed', 'tokens': 8483, 'retrieve_doc': True, 'source': 'HF_Transformers'}\n"
220
+ ]
221
+ }
222
+ ],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
  "source": [
224
  "from llama_index.core import Document\n",
225
  "from llama_index.core.schema import MetadataMode\n",
 
233
  " data = json.loads(line)\n",
234
  " documents.append(\n",
235
  " Document(\n",
236
+ " doc_id=data[\"doc_id\"],\n",
237
  " text=data[\"content\"],\n",
238
  " metadata={\n",
239
  " \"url\": data[\"url\"],\n",
240
  " \"title\": data[\"name\"],\n",
241
  " \"tokens\": data[\"tokens\"],\n",
242
  " \"retrieve_doc\": data[\"retrieve_doc\"],\n",
243
+ " \"source\": \"HF_Transformers\",\n",
244
  " },\n",
245
  " excluded_llm_metadata_keys=[\n",
246
  " \"url\",\n",
247
  " \"title\",\n",
248
  " \"tokens\",\n",
249
  " \"retrieve_doc\",\n",
250
+ " \"source\",\n",
251
  " ],\n",
252
  " excluded_embed_metadata_keys=[\n",
253
  " \"url\",\n",
254
  " \"title\",\n",
255
  " \"tokens\",\n",
256
  " \"retrieve_doc\",\n",
257
+ " \"source\",\n",
258
  " ],\n",
259
  " )\n",
260
  " )\n",
 
265
  "print(documents[0])\n",
266
  "print(documents[0].metadata)\n",
267
  "\n",
268
+ "document_dict = {doc.doc_id: doc for doc in documents}\n",
269
+ "# save dict to disk, as .pkl file\n",
270
+ "import pickle\n",
271
+ "\n",
272
+ "with open(\"document_dict.pkl\", \"wb\") as f:\n",
273
+ " pickle.dump(document_dict, f)\n",
274
+ "\n",
275
+ "# load dict from disk\n",
276
+ "with open(\"document_dict.pkl\", \"rb\") as f:\n",
277
+ " document_dict = pickle.load(f)"
278
  ]
279
  },
280
  {
281
  "cell_type": "code",
282
+ "execution_count": 4,
283
  "metadata": {},
284
  "outputs": [],
285
  "source": [
286
+ "import chromadb\n",
287
  "\n",
288
+ "# create client and a new collection\n",
289
+ "# chromadb.EphemeralClient saves data in-memory.\n",
290
+ "chroma_client = chromadb.PersistentClient(path=\"./ai-tutor-vector-db\")\n",
291
+ "chroma_collection = chroma_client.create_collection(\"ai-tutor-vector-db\")\n",
292
  "\n",
293
+ "from llama_index.vector_stores.chroma import ChromaVectorStore\n",
294
+ "from llama_index.core import StorageContext\n",
295
  "\n",
296
+ "# Define a storage context object using the created vector database.\n",
297
+ "vector_store = ChromaVectorStore(chroma_collection=chroma_collection)\n",
298
+ "storage_context = StorageContext.from_defaults(vector_store=vector_store)"
299
  ]
300
  },
301
  {
302
  "cell_type": "code",
303
+ "execution_count": 5,
304
  "metadata": {},
305
+ "outputs": [
306
+ {
307
+ "name": "stderr",
308
+ "output_type": "stream",
309
+ "text": [
310
+ "/Users/omar/Documents/ai_repos/ai-tutor-rag-system/env/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",
311
+ " from .autonotebook import tqdm as notebook_tqdm\n",
312
+ "Parsing nodes: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 3374/3374 [00:36<00:00, 93.13it/s] \n",
313
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:03<00:00, 5.60it/s]\n",
314
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:04<00:00, 5.00it/s]\n",
315
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:04<00:00, 4.78it/s]\n",
316
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:22<00:00, 1.09s/it]\n",
317
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:05<00:00, 3.63it/s]\n",
318
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:03<00:00, 6.82it/s]\n",
319
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:04<00:00, 5.18it/s]\n",
320
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:03<00:00, 5.58it/s]\n",
321
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:03<00:00, 6.36it/s]\n",
322
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:03<00:00, 6.34it/s]\n",
323
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:03<00:00, 6.80it/s]\n",
324
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:03<00:00, 5.59it/s]\n",
325
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:03<00:00, 6.64it/s]\n",
326
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:03<00:00, 6.07it/s]\n",
327
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:03<00:00, 5.82it/s]\n",
328
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:08<00:00, 2.39it/s]\n",
329
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:03<00:00, 5.81it/s]\n",
330
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:04<00:00, 4.26it/s]\n",
331
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:03<00:00, 6.69it/s]\n",
332
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:03<00:00, 5.97it/s]\n",
333
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:03<00:00, 5.61it/s]\n",
334
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:02<00:00, 7.71it/s]\n",
335
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:04<00:00, 4.51it/s]\n",
336
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:03<00:00, 5.81it/s]\n",
337
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:03<00:00, 5.55it/s]\n",
338
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 21/21 [00:03<00:00, 5.69it/s]\n",
339
+ "Generating embeddings: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 12/12 [00:04<00:00, 2.57it/s]\n"
340
+ ]
341
+ }
342
+ ],
343
  "source": [
344
  "from llama_index.core import VectorStoreIndex\n",
345
  "from llama_index.core.node_parser import SentenceSplitter\n",
 
353
  " transformations=[SentenceSplitter(chunk_size=800, chunk_overlap=400)],\n",
354
  " show_progress=True,\n",
355
  " use_async=True,\n",
356
+ " storage_context=storage_context,\n",
357
  ")"
358
  ]
359
  },
360
  {
361
  "cell_type": "code",
362
+ "execution_count": 6,
363
  "metadata": {},
364
  "outputs": [],
365
  "source": [
 
 
 
 
 
 
 
 
 
366
  "retriever = index.as_retriever(\n",
367
  " similarity_top_k=10,\n",
368
  " use_async=True,\n",
 
373
  },
374
  {
375
  "cell_type": "code",
376
+ "execution_count": 7,
377
  "metadata": {},
378
+ "outputs": [
379
+ {
380
+ "name": "stdout",
381
+ "output_type": "stream",
382
+ "text": [
383
+ "9\n",
384
+ "Node ID\t df8090eb-b13b-4f61-b94b-5489a43acfad\n",
385
+ "Title\t Generation with LLMs\n",
386
+ "Text\t That is why we have a GenerationConfig file associated with each model, which contains a good default generative parameterization and is loaded alongside your model.\n",
387
+ "Let’s talk code!\n",
388
+ "If you’re interested in basic LLM usage, our high-level Pipeline interface is a great starting point. However, LLMs often require advanced features like quantization and fine control of the token selection step, which is best done through generate() . Autoregressive generation with LLMs is also resource-intensive and should be executed on a GPU for adequate throughput.\n",
389
+ "First, you need to load the model.\n",
390
+ "Copied >>> from transformers import AutoModelForCausalLM >>> model = AutoModelForCausalLM.from_pretrained( ... \"mistralai/Mistral-7B-v0.1\" , device_map= \"auto\" , load_in_4bit= True ... )\n",
391
+ "You’ll notice two flags in the from_pretrained call:\n",
392
+ "device_map ensures the model is moved to your GPU(s) load_in_4bit applies 4-bit dynamic quantization to massively reduce the resource requirements\n",
393
+ "There are other ways to initialize a model, but this is a good baseline to begin with an LLM.\n",
394
+ "Next, you need to preprocess your text input with a tokenizer .\n",
395
+ "Copied >>> from transformers import AutoTokenizer >>> tokenizer = AutoTokenizer.from_pretrained( \"mistralai/Mistral-7B-v0.1\" , padding_side= \"left\" ) >>> model_inputs = tokenizer([ \"A list of colors: red, blue\" ], return_tensors= \"pt\" ).to( \"cuda\" )\n",
396
+ "The model_inputs variable holds the tokenized text input, as well as the attention mask. While generate() does its best effort to infer the attention mask when it is not passed, we recommend passing it whenever possible for optimal results.\n",
397
+ "After tokenizing the inputs, you can call the generate() method to returns the generated tokens. The generated tokens then should be converted to text before printing.\n",
398
+ "Copied >>> generated_ids = model.generate(**model_inputs) >>> tokenizer.batch_decode(generated_ids, skip_special_tokens= True )[ 0 ] 'A list of colors: red, blue, green, yellow, orange, purple, pink,'\n",
399
+ "Finally, you don’t need to do it one sequence at a time! You can batch your inputs, which will greatly improve the throughput at a small latency and memory cost. All you need to do is to make sure you pad your inputs properly (more on that below).\n",
400
+ "Copied >>> tokenizer.pad_token = tokenizer.eos_token # Most LLMs don't have a pad token by default >>> model_inputs = tokenizer( ... [ \"A list of colors: red, blue\" , \"Portugal is\" ], return_tensors= \"pt\" , padding= True ... ).to( \"cuda\" ) >>> generated_ids = model.generate(**model_inputs) >>> tokenizer.batch_decode(generated_ids, skip_special_tokens= True )\n",
401
+ "[ 'A list of colors: red, blue, green, yellow, orange, purple, pink,' , 'Portugal is a country in southwestern Europe, on the Iber' ]\n",
402
+ "And that’s it! In a few lines of code, you can harness the power of an LLM.\n",
403
+ "\n",
404
+ "There are many generation strategies , and sometimes the default values may not be appropriate for your use case. If your outputs aren’t aligned with what you’re expecting, we’ve created a list of the most common pitfalls and how to avoid them.\n",
405
+ "Score\t 0.33395801169351413\n",
406
+ "Metadata\t {'url': 'https://huggingface.co/docs/transformers/llm_tutorial', 'title': 'Generation with LLMs', 'tokens': 2901, 'retrieve_doc': True, 'source': 'HF_Transformers'}\n",
407
+ "-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n",
408
+ "This node will be replaced by the document\n",
409
+ "LLMs, or Large Language Models, are the key component behind text generation. In a nutshell, they consist of large pretrained transformer models trained to predict the next word (or, more precisely, token) given some input text. Since they predict one token at a time, you need to do something more elaborate to generate new sentences other than just calling the model β€” you need to do autoregressive generation.\n",
410
+ "Autoregressive generation is the inference-time procedure of iteratively calling a model with its own generated outputs, given a few initial inputs. In πŸ€— Transformers, this is handled by the generate() method, which is available to all models with generative capabilities.\n",
411
+ "This tutorial will show you how to:\n",
412
+ "Generate text with an LLM Avoid common pitfalls Next steps to help you get the most out of your LLM\n",
413
+ "Before you begin, make sure you have all the necessary libraries installed:\n",
414
+ "Copied pip install transformers bitsandbytes>=0.39.0 -q\n",
415
+ "\n",
416
+ "A language model trained for causal language modeling takes a sequence of text tokens as input and returns the probability distribution for the next token.\n",
417
+ "\"Forward pass of an LLM\"\n",
418
+ "A critical aspect of autoregressive generation with LLMs is how to select the next token from this probability distribution. Anything goes in this step as long as you end up with a token for the next iteration. This means it can be as simple as selecting the most likely token from the probability distribution or as complex as applying a dozen transformations before sampling from the resulting distribution.\n",
419
+ "\"Autoregressive generation iteratively selects the next token from a probability distribution to generate text\"\n",
420
+ "The process depicted above is repeated iteratively until some stopping condition is reached. Ideally, the stopping condition is dictated by the model, which should learn when to output an end-of-sequence ( EOS ) token. If this is not the case, generation stops when some predefined maximum length is reached.\n",
421
+ "Properly setting up the token selection step and the stopping condition is essential to make your model behave as you’d expect on your task. That is why we have a GenerationConfig file associated with each model, which contains a good default generative parameterization and is loaded alongside your model.\n",
422
+ "Let’s talk code!\n",
423
+ "If you’re interested in basic LLM usage, our high-level Pipeline interface is a great starting point. However, LLMs often require advanced features like quantization and fine control of the token selection step, which is best done through generate() . Autoregressive generation with LLMs is also resource-intensive and should be executed on a GPU for adequate throughput.\n",
424
+ "First, you need to load the model.\n",
425
+ "Copied >>> from transformers import AutoModelForCausalLM >>> model = AutoModelForCausalLM.from_pretrained( ... \"mistralai/Mistral-7B-v0.1\" , device_map= \"auto\" , load_in_4bit= True ... )\n",
426
+ "You’ll notice two flags in the from_pretrained call:\n",
427
+ "device_map ensures the model is moved to your GPU(s) load_in_4bit applies 4-bit dynamic quantization to massively reduce the resource requirements\n",
428
+ "There are other ways to initialize a model, but this is a good baseline to begin with an LLM.\n",
429
+ "Next, you need to preprocess your text input with a tokenizer .\n",
430
+ "Copied >>> from transformers import AutoTokenizer >>> tokenizer = AutoTokenizer.from_pretrained( \"mistralai/Mistral-7B-v0.1\" , padding_side= \"left\" ) >>> model_inputs = tokenizer([ \"A list of colors: red, blue\" ], return_tensors= \"pt\" ).to( \"cuda\" )\n",
431
+ "The model_inputs variable holds the tokenized text input, as well as the attention mask. While generate() does its best effort to infer the attention mask when it is not passed, we recommend passing it whenever possible for optimal results.\n",
432
+ "After tokenizing the inputs, you can call the generate() method to returns the generated tokens. The generated tokens then should be converted to text before printing.\n",
433
+ "Copied >>> generated_ids = model.generate(**model_inputs) >>> tokenizer.batch_decode(generated_ids, skip_special_tokens= True )[ 0 ] 'A list of colors: red, blue, green, yellow, orange, purple, pink,'\n",
434
+ "Finally, you don’t need to do it one sequence at a time! You can batch your inputs, which will greatly improve the throughput at a small latency and memory cost. All you need to do is to make sure you pad your inputs properly (more on that below).\n",
435
+ "Copied >>> tokenizer.pad_token = tokenizer.eos_token # Most LLMs don't have a pad token by default >>> model_inputs = tokenizer( ... [ \"A list of colors: red, blue\" , \"Portugal is\" ], return_tensors= \"pt\" , padding= True ... ).to( \"cuda\" ) >>> generated_ids = model.generate(**model_inputs) >>> tokenizer.batch_decode(generated_ids, skip_special_tokens= True )\n",
436
+ "[ 'A list of colors: red, blue, green, yellow, orange, purple, pink,' , 'Portugal is a country in southwestern Europe, on the Iber' ]\n",
437
+ "And that’s it! In a few lines of code, you can harness the power of an LLM.\n",
438
+ "\n",
439
+ "There are many generation strategies , and sometimes the default values may not be appropriate for your use case. If your outputs aren’t aligned with what you’re expecting, we’ve created a list of the most common pitfalls and how to avoid them.\n",
440
+ "Copied >>> from transformers import AutoModelForCausalLM, AutoTokenizer >>> tokenizer = AutoTokenizer.from_pretrained( \"mistralai/Mistral-7B-v0.1\" ) >>> tokenizer.pad_token = tokenizer.eos_token # Most LLMs don't have a pad token by default >>> model = AutoModelForCausalLM.from_pretrained( ... \"mistralai/Mistral-7B-v0.1\" , device_map= \"auto\" , load_in_4bit= True ... )\n",
441
+ "\n",
442
+ "If not specified in the GenerationConfig file, generate returns up to 20 tokens by default. We highly recommend manually setting max_new_tokens in your generate call to control the maximum number of new tokens it can return. Keep in mind LLMs (more precisely, decoder-only models ) also return the input prompt as part of the output.\n",
443
+ "Copied >>> model_inputs = tokenizer([ \"A sequence of numbers: 1, 2\" ], return_tensors= \"pt\" ).to( \"cuda\" ) >>> # By default, the output will contain up to 20 tokens >>> generated_ids = model.generate(**model_inputs) >>> tokenizer.batch_decode(generated_ids, skip_special_tokens= True )[ 0 ] 'A sequence of numbers: 1, 2, 3, 4, 5' >>> # Setting `max_new_tokens` allows you to control the maximum length >>> generated_ids = model.generate(**model_inputs, max_new_tokens= 50 ) >>> tokenizer.batch_decode(generated_ids, skip_special_tokens= True )[ 0 ] 'A sequence of numbers: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,'\n",
444
+ "\n",
445
+ "By default, and unless specified in the GenerationConfig file, generate selects the most likely token at each iteration (greedy decoding). Depending on your task, this may be undesirable; creative tasks like chatbots or writing an essay benefit from sampling. On the other hand, input-grounded tasks like audio transcription or translation benefit from greedy decoding. Enable sampling with do_sample=True , and you can learn more about this topic in this blog post .\n",
446
+ "Copied >>> # Set seed or reproducibility -- you don't need this unless you want full reproducibility >>> from transformers import set_seed >>> set_seed( 42 ) >>> model_inputs = tokenizer([ \"I am a cat.\" ], return_tensors= \"pt\" ).to( \"cuda\" ) >>> # LLM + greedy decoding = repetitive, boring output >>> generated_ids = model.generate(**model_inputs) >>> tokenizer.batch_decode(generated_ids, skip_special_tokens= True )[ 0 ] 'I am a cat. I am a cat. I am a cat. I am a cat' >>> # With sampling, the output becomes more creative! >>> generated_ids = model.generate(**model_inputs, do_sample= True ) >>> tokenizer.batch_decode(generated_ids, skip_special_tokens= True )[ 0 ] 'I am a cat. Specifically, I am an indoor-only cat. I'\n",
447
+ "\n",
448
+ "LLMs are decoder-only architectures, meaning they continue to iterate on your input prompt. If your inputs do not have the same length, they need to be padded. Since LLMs are not trained to continue from pad tokens, your input needs to be left-padded. Make sure you also don’t forget to pass the attention mask to generate!\n",
449
+ "Copied >>> # The tokenizer initialized above has right-padding active by default: the 1st sequence, >>> # which is shorter, has padding on the right side. Generation fails to capture the logic. >>> model_inputs = tokenizer( ... [ \"1, 2, 3\" , \"A, B, C, D, E\" ], padding= True , return_tensors= \"pt\" ... ).to( \"cuda\" ) >>> generated_ids = model.generate(**model_inputs) >>> tokenizer.batch_decode(generated_ids, skip_special_tokens= True )[ 0 ] '1, 2, 33333333333' >>> # With left-padding, it works as expected! >>> tokenizer = AutoTokenizer.from_pretrained( \"mistralai/Mistral-7B-v0.1\" , padding_side= \"left\" ) >>> tokenizer.pad_token = tokenizer.eos_token # Most LLMs don't have a pad token by default >>> model_inputs = tokenizer( ... [ \"1, 2, 3\" , \"A, B, C, D, E\" ], padding= True , return_tensors= \"pt\" ... ).to( \"cuda\" ) >>> generated_ids = model.generate(**model_inputs) >>> tokenizer.batch_decode(generated_ids, skip_special_tokens= True )[ 0 ] '1, 2, 3, 4, 5, 6,'\n",
450
+ "\n",
451
+ "Some models and tasks expect a certain input prompt format to work properly. When this format is not applied, you will get a silent performance degradation: the model kinda works, but not as well as if you were following the expected prompt. More information about prompting, including which models and tasks need to be careful, is available in this guide . Let’s see an example with a chat LLM, which makes use of chat templating :\n",
452
+ "Copied >>> tokenizer = AutoTokenizer.from_pretrained( \"HuggingFaceH4/zephyr-7b-alpha\" ) >>> model = AutoModelForCausalLM.from_pretrained( ... \"HuggingFaceH4/zephyr-7b-alpha\" , device_map= \"auto\" , load_in_4bit= True ... ) >>> set_seed( 0 ) >>> prompt = \"\"\"How many helicopters can a human eat in one sitting? Reply as a thug.\"\"\" >>> model_inputs = tokenizer([prompt], return_tensors= \"pt\" ).to( \"cuda\" ) >>> input_length = model_inputs.input_ids.shape[ 1 ] >>> generated_ids = model.generate(**model_inputs, max_new_tokens= 20 ) >>> print (tokenizer.batch_decode(generated_ids[:, input_length:], skip_special_tokens= True )[ 0 ]) \"I'm not a thug, but i can tell you that a human cannot eat\" >>> # Oh no, it did not follow our instruction to reply as a thug! Let's see what happens when we write >>> # a better prompt and use the right template for this model (through `tokenizer.apply_chat_template`) >>> set_seed( 0 ) >>> messages = [ ... { ... \"role\" : \"system\" , ... \"content\" : \"You are a friendly chatbot who always responds in the style of a thug\" , ... }, ... { \"role\" : \"user\" , \"content\" : \"How many helicopters can a human eat in one sitting?\" }, ... ] >>> model_inputs = tokenizer.apply_chat_template(messages, add_generation_prompt= True , return_tensors= \"pt\" ).to( \"cuda\" ) >>> input_length = model_inputs.shape[ 1 ] >>> generated_ids = model.generate(model_inputs, do_sample= True , max_new_tokens= 20 ) >>> print (tokenizer.batch_decode(generated_ids[:, input_length:], skip_special_tokens= True )[ 0 ]) 'None, you thug. How bout you try to focus on more useful questions?' >>> # As we can see, it followed a proper thug style 😎\n",
453
+ "\n",
454
+ "While the autoregressive generation process is relatively straightforward, making the most out of your LLM can be a challenging endeavor because there are many moving parts. For your next steps to help you dive deeper into LLM usage and understanding:\n",
455
+ "\n",
456
+ "Guide on how to control different generation methods , how to set up the generation configuration file, and how to stream the output; Accelerating text generation ; Prompt templates for chat LLMs ; Prompt design guide ; API reference on GenerationConfig , generate() , and generate-related classes . Most of the classes, including the logits processors, have usage examples!\n",
457
+ "\n",
458
+ "Open LLM Leaderboard , which focuses on the quality of the open-source models; Open LLM-Perf Leaderboard , which focuses on LLM throughput.\n",
459
+ "\n",
460
+ "Guide on how to optimize LLMs for speed and memory ; Guide on quantization such as bitsandbytes and autogptq, which shows you how to drastically reduce your memory requirements.\n",
461
+ "\n",
462
+ "optimum , an extension of πŸ€— Transformers that optimizes for specific hardware devices. outlines , a library where you can constrain text generation (e.g. to generate JSON files); text-generation-inference , a production-ready server for LLMs; text-generation-webui , a UI for text generation;\n",
463
+ "< > Update on GitHub\n",
464
+ "HTML_TAG_END\n",
465
+ "Node ID\t 038a63a0-4559-4e68-8d00-38dfb08f3e46\n",
466
+ "Title\t Trainer\n",
467
+ "Text\t Please see this appropriate section for more details. Other features such as gradient clipping, DeepSpeed, etc might not be supported out of the box. Please raise an issue on GitHub if you encounter such issue.\n",
468
+ "\n",
469
+ "The LOMO optimizers have been introduced in Full Parameter Fine-Tuning for Large Language Models with Limited Resources and AdaLomo: Low-memory Optimization with Adaptive Learning Rate .\n",
470
+ "They both consist of an efficient full-parameter fine-tuning method. These optimizers fuse the gradient computation and the parameter update in one step to reduce memory usage. Supported optimizers for LOMO are \"lomo\" and \"adalomo\" . First either install LOMO from pypi pip install lomo-optim or install it from source with pip install git+https://github.com/OpenLMLab/LOMO.git .\n",
471
+ "According to the authors, it is recommended to use AdaLomo without grad_norm to get better performance and higher throughput.\n",
472
+ "Below is a simple script to demonstrate how to fine-tune google/gemma-2b on IMDB dataset in full precision:\n",
473
+ "Copied import torch import datasets from transformers import TrainingArguments, AutoTokenizer, AutoModelForCausalLM import trl\n",
474
+ "\n",
475
+ "train_dataset = datasets.load_dataset( 'imdb' , split= 'train' )\n",
476
+ "\n",
477
+ "args = TrainingArguments(\n",
478
+ " output_dir= \"./test-lomo\" ,\n",
479
+ " max_steps= 1000 ,\n",
480
+ " per_device_train_batch_size= 4 ,\n",
481
+ " optim= \"adalomo\" ,\n",
482
+ " gradient_checkpointing= True ,\n",
483
+ " logging_strategy= \"steps\" ,\n",
484
+ " logging_steps= 1 ,\n",
485
+ " learning_rate= 2e-6 ,\n",
486
+ " save_strategy= \"no\" ,\n",
487
+ " run_name= \"lomo-imdb\" ,\n",
488
+ ")\n",
489
+ "\n",
490
+ "model_id = \"google/gemma-2b\" tokenizer = AutoTokenizer.from_pretrained(model_id)\n",
491
+ "model = AutoModelForCausalLM.from_pretrained(model_id, low_cpu_mem_usage= True ).to( 0 )\n",
492
+ "\n",
493
+ "trainer = trl.SFTTrainer(\n",
494
+ " model=model, \n",
495
+ " args=args,\n",
496
+ " train_dataset=train_dataset,\n",
497
+ " dataset_text_field= 'text' ,\n",
498
+ " max_seq_length= 1024 ,\n",
499
+ ")\n",
500
+ "\n",
501
+ "trainer.train()\n",
502
+ "\n",
503
+ "The Trainer class is powered by Accelerate , a library for easily training PyTorch models in distributed environments with support for integrations such as FullyShardedDataParallel (FSDP) and DeepSpeed .\n",
504
+ "Learn more about FSDP sharding strategies, CPU offloading, and more with the Trainer in the Fully Sharded Data Parallel guide.\n",
505
+ "To use Accelerate with Trainer , run the accelerate.config command to set up training for your training environment. This command creates a config_file.yaml that’ll be used when you launch your training script. For example, some example configurations you can setup are:\n",
506
+ "DistributedDataParallel FSDP DeepSpeed DeepSpeed with Accelerate plugin\n",
507
+ "Copied compute_environment: LOCAL_MACHINE distributed_type: MULTI_GPU downcast_bf16: 'no' gpu_ids: all machine_rank: 0 #change rank as per the node main_process_ip: 192.168 .20 .1 main_process_port: 9898 main_training_function: main mixed_precision: fp16 num_machines: 2 num_processes: 8 rdzv_backend: static same_network: true tpu_env: [] tpu_use_cluster: false tpu_use_sudo: false use_cpu: false\n",
508
+ "The accelerate_launch command is the recommended way to launch your training script on a distributed system with Accelerate and Trainer with the parameters specified in config_file.yaml . This file is saved to the Accelerate cache folder and automatically loaded when you run accelerate_launch .\n",
509
+ "Score\t 0.333921268256774\n",
510
+ "Metadata\t {'url': 'https://huggingface.co/docs/transformers/trainer', 'title': 'Trainer', 'tokens': 4064, 'retrieve_doc': True, 'source': 'HF_Transformers'}\n",
511
+ "-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n",
512
+ "This node will be replaced by the document\n",
513
+ "The Trainer is a complete training and evaluation loop for PyTorch models implemented in the Transformers library. You only need to pass it the necessary pieces for training (model, tokenizer, dataset, evaluation function, training hyperparameters, etc.), and the Trainer class takes care of the rest. This makes it easier to start training faster without manually writing your own training loop. But at the same time, Trainer is very customizable and offers a ton of training options so you can tailor it to your exact training needs.\n",
514
+ "In addition to the Trainer class, Transformers also provides a Seq2SeqTrainer class for sequence-to-sequence tasks like translation or summarization. There is also the SFTTrainer class from the TRL library which wraps the Trainer class and is optimized for training language models like Llama-2 and Mistral with autoregressive techniques. SFTTrainer also supports features like sequence packing, LoRA, quantization, and DeepSpeed for efficiently scaling to any model size. Feel free to check out the API reference for these other Trainer -type classes to learn more about when to use which one. In general, Trainer is the most versatile option and is appropriate for a broad spectrum of tasks. Seq2SeqTrainer is designed for sequence-to-sequence tasks and SFTTrainer is designed for training language models.\n",
515
+ "Before you start, make sure Accelerate - a library for enabling and running PyTorch training across distributed environments - is installed.\n",
516
+ "Copied pip install accelerate # upgrade pip install accelerate --upgrade\n",
517
+ "This guide provides an overview of the Trainer class.\n",
518
+ "\n",
519
+ "Trainer includes all the code you’ll find in a basic training loop:\n",
520
+ "perform a training step to calculate the loss calculate the gradients with the backward method update the weights based on the gradients repeat this process until you’ve reached a predetermined number of epochs\n",
521
+ "The Trainer class abstracts all of this code away so you don’t have to worry about manually writing a training loop every time or if you’re just getting started with PyTorch and training. You only need to provide the essential components required for training, such as a model and a dataset, and the Trainer class handles everything else.\n",
522
+ "If you want to specify any training options or hyperparameters, you can find them in the TrainingArguments class. For example, let’s define where to save the model in output_dir and push the model to the Hub after training with push_to_hub=True .\n",
523
+ "Copied from transformers import TrainingArguments\n",
524
+ "\n",
525
+ "training_args = TrainingArguments(\n",
526
+ " output_dir= \"your-model\" ,\n",
527
+ " learning_rate= 2e-5 ,\n",
528
+ " per_device_train_batch_size= 16 ,\n",
529
+ " per_device_eval_batch_size= 16 ,\n",
530
+ " num_train_epochs= 2 ,\n",
531
+ " weight_decay= 0.01 ,\n",
532
+ " eval_strategy= \"epoch\" ,\n",
533
+ " save_strategy= \"epoch\" ,\n",
534
+ " load_best_model_at_end= True ,\n",
535
+ " push_to_hub= True ,\n",
536
+ ")\n",
537
+ "Pass training_args to the Trainer along with a model, dataset, something to preprocess the dataset with (depending on your data type it could be a tokenizer, feature extractor or image processor), a data collator, and a function to compute the metrics you want to track during training.\n",
538
+ "Finally, call train() to start training!\n",
539
+ "Copied from transformers import Trainer\n",
540
+ "\n",
541
+ "trainer = Trainer(\n",
542
+ " model=model,\n",
543
+ " args=training_args,\n",
544
+ " train_dataset=dataset[ \"train\" ],\n",
545
+ " eval_dataset=dataset[ \"test\" ],\n",
546
+ " tokenizer=tokenizer,\n",
547
+ " data_collator=data_collator,\n",
548
+ " compute_metrics=compute_metrics,\n",
549
+ ")\n",
550
+ "\n",
551
+ "trainer.train()\n",
552
+ "\n",
553
+ "The Trainer class saves your model checkpoints to the directory specified in the output_dir parameter of TrainingArguments . You’ll find the checkpoints saved in a checkpoint-000 subfolder where the numbers at the end correspond to the training step. Saving checkpoints are useful for resuming training later.\n",
554
+ "Copied # resume from latest checkpoint trainer.train(resume_from_checkpoint= True ) # resume from specific checkpoint saved in output directory trainer.train(resume_from_checkpoint= \"your-model/checkpoint-1000\" )\n",
555
+ "You can save your checkpoints (the optimizer state is not saved by default) to the Hub by setting push_to_hub=True in TrainingArguments to commit and push them. Other options for deciding how your checkpoints are saved are set up in the hub_strategy parameter:\n",
556
+ "hub_strategy=\"checkpoint\" pushes the latest checkpoint to a subfolder named β€œlast-checkpoint” from which you can resume training hub_strategy=\"all_checkpoints\" pushes all checkpoints to the directory defined in output_dir (you’ll see one checkpoint per folder in your model repository)\n",
557
+ "When you resume training from a checkpoint, the Trainer tries to keep the Python, NumPy, and PyTorch RNG states the same as they were when the checkpoint was saved. But because PyTorch has various non-deterministic default settings, the RNG states aren’t guaranteed to be the same. If you want to enable full determinism, take a look at the Controlling sources of randomness guide to learn what you can enable to make your training fully deterministic. Keep in mind though that by making certain settings deterministic, training may be slower.\n",
558
+ "\n",
559
+ "While the Trainer class is designed to be accessible and easy-to-use, it also offers a lot of customizability for more adventurous users. Many of the Trainer ’s method can be subclassed and overridden to support the functionality you want, without having to rewrite the entire training loop from scratch to accommodate it. These methods include:\n",
560
+ "get_train_dataloader() creates a training DataLoader get_eval_dataloader() creates an evaluation DataLoader get_test_dataloader() creates a test DataLoader log() logs information on the various objects that watch training create_optimizer_and_scheduler() creates an optimizer and learning rate scheduler if they weren’t passed in the __init__ ; these can also be separately customized with create_optimizer() and create_scheduler() respectively compute_loss() computes the loss on a batch of training inputs training_step() performs the training step prediction_step() performs the prediction and test step evaluate() evaluates the model and returns the evaluation metrics predict() makes predictions (with metrics if labels are available) on the test set\n",
561
+ "For example, if you want to customize the compute_loss() method to use a weighted loss instead.\n",
562
+ "Copied from torch import nn from transformers import Trainer class CustomTrainer ( Trainer ): def compute_loss ( self, model, inputs, return_outputs= False ):\n",
563
+ " labels = inputs.pop( \"labels\" ) # forward pass outputs = model(**inputs)\n",
564
+ " logits = outputs.get( \"logits\" ) # compute custom loss for 3 labels with different weights loss_fct = nn.CrossEntropyLoss(weight=torch.tensor([ 1.0 , 2.0 , 3.0 ], device=model.device))\n",
565
+ " loss = loss_fct(logits.view(- 1 , self.model.config.num_labels), labels.view(- 1 )) return (loss, outputs) if return_outputs else loss\n",
566
+ "\n",
567
+ "Another option for customizing the Trainer is to use callbacks . Callbacks don’t change anything in the training loop. They inspect the training loop state and then execute some action (early stopping, logging results, etc.) depending on the state. In other words, a callback can’t be used to implement something like a custom loss function and you’ll need to subclass and override the compute_loss() method for that.\n",
568
+ "For example, if you want to add an early stopping callback to the training loop after 10 steps.\n",
569
+ "Copied from transformers import TrainerCallback class EarlyStoppingCallback ( TrainerCallback ): def __init__ ( self, num_steps= 10 ):\n",
570
+ " self.num_steps = num_steps def on_step_end ( self, args, state, control, **kwargs ): if state.global_step >= self.num_steps: return { \"should_training_stop\" : True } else : return {}\n",
571
+ "Then pass it to the Trainer ’s callback parameter.\n",
572
+ "Copied from transformers import Trainer\n",
573
+ "\n",
574
+ "trainer = Trainer(\n",
575
+ " model=model,\n",
576
+ " args=training_args,\n",
577
+ " train_dataset=dataset[ \"train\" ],\n",
578
+ " eval_dataset=dataset[ \"test\" ],\n",
579
+ " tokenizer=tokenizer,\n",
580
+ " data_collator=data_collator,\n",
581
+ " compute_metrics=compute_metrics,\n",
582
+ " callback=[EarlyStoppingCallback()],\n",
583
+ ")\n",
584
+ "\n",
585
+ "Check out the logging API reference for more information about the different logging levels.\n",
586
+ "The Trainer is set to logging.INFO by default which reports errors, warnings, and other basic information. A Trainer replica - in distributed environments - is set to logging.WARNING which only reports errors and warnings. You can change the logging level with the log_level and log_level_replica parameters in TrainingArguments .\n",
587
+ "To configure the log level setting for each node, use the log_on_each_node parameter to determine whether to use the log level on each node or only on the main node.\n",
588
+ "Trainer sets the log level separately for each node in the Trainer.__init__() method, so you may want to consider setting this sooner if you’re using other Transformers functionalities before creating the Trainer object.\n",
589
+ "For example, to set your main code and modules to use the same log level according to each node:\n",
590
+ "Copied logger = logging.getLogger(__name__)\n",
591
+ "\n",
592
+ "logging.basicConfig( format = \"%(asctime)s - %(levelname)s - %(name)s - %(message)s\" ,\n",
593
+ " datefmt= \"%m/%d/%Y %H:%M:%S\" ,\n",
594
+ " handlers=[logging.StreamHandler(sys.stdout)],\n",
595
+ ")\n",
596
+ "\n",
597
+ "log_level = training_args.get_process_log_level()\n",
598
+ "logger.setLevel(log_level)\n",
599
+ "datasets.utils.logging.set_verbosity(log_level)\n",
600
+ "transformers.utils.logging.set_verbosity(log_level)\n",
601
+ "\n",
602
+ "trainer = Trainer(...)\n",
603
+ "Use different combinations of log_level and log_level_replica to configure what gets logged on each of the nodes.\n",
604
+ "single node multi-node\n",
605
+ "Copied my_app.py ... --log_level warning --log_level_replica error\n",
606
+ "\n",
607
+ "NEFTune is a technique that can improve performance by adding noise to the embedding vectors during training. To enable it in Trainer , set the neftune_noise_alpha parameter in TrainingArguments to control how much noise is added.\n",
608
+ "Copied from transformers import TrainingArguments, Trainer\n",
609
+ "\n",
610
+ "training_args = TrainingArguments(..., neftune_noise_alpha= 0.1 )\n",
611
+ "trainer = Trainer(..., args=training_args)\n",
612
+ "NEFTune is disabled after training to restore the original embedding layer to avoid any unexpected behavior.\n",
613
+ "\n",
614
+ "Gradient Low-Rank Projection (GaLore) is a memory-efficient low-rank training strategy that allows full-parameter learning but is more memory-efficient than common low-rank adaptation methods, such as LoRA.\n",
615
+ "First make sure to install GaLore official repository:\n",
616
+ "Copied pip install galore-torch\n",
617
+ "Then simply add one of [\"galore_adamw\", \"galore_adafactor\", \"galore_adamw_8bit\"] in optim together with optim_target_modules , which can be a list of strings, regex or full path corresponding to the target module names you want to adapt. Below is an end-to-end example script (make sure to pip install trl datasets ):\n",
618
+ "Copied import torch import datasets import trl from transformers import TrainingArguments, AutoConfig, AutoTokenizer, AutoModelForCausalLM\n",
619
+ "\n",
620
+ "train_dataset = datasets.load_dataset( 'imdb' , split= 'train' )\n",
621
+ "\n",
622
+ "args = TrainingArguments(\n",
623
+ " output_dir= \"./test-galore\" ,\n",
624
+ " max_steps= 100 ,\n",
625
+ " per_device_train_batch_size= 2 ,\n",
626
+ " optim= \"galore_adamw\" ,\n",
627
+ " optim_target_modules=[ \"attn\" , \"mlp\" ]\n",
628
+ ")\n",
629
+ "\n",
630
+ "model_id = \"google/gemma-2b\" config = AutoConfig.from_pretrained(model_id)\n",
631
+ "\n",
632
+ "tokenizer = AutoTokenizer.from_pretrained(model_id)\n",
633
+ "model = AutoModelForCausalLM.from_config(config).to( 0 )\n",
634
+ "\n",
635
+ "trainer = trl.SFTTrainer(\n",
636
+ " model=model, \n",
637
+ " args=args,\n",
638
+ " train_dataset=train_dataset,\n",
639
+ " dataset_text_field= 'text' ,\n",
640
+ " max_seq_length= 512 ,\n",
641
+ ")\n",
642
+ "\n",
643
+ "trainer.train()\n",
644
+ "To pass extra arguments supports by GaLore, you should pass correctly optim_args , for example:\n",
645
+ "Copied import torch import datasets import trl from transformers import TrainingArguments, AutoConfig, AutoTokenizer, AutoModelForCausalLM\n",
646
+ "\n",
647
+ "train_dataset = datasets.load_dataset( 'imdb' , split= 'train' )\n",
648
+ "\n",
649
+ "args = TrainingArguments(\n",
650
+ " output_dir= \"./test-galore\" ,\n",
651
+ " max_steps= 100 ,\n",
652
+ " per_device_train_batch_size= 2 ,\n",
653
+ " optim= \"galore_adamw\" ,\n",
654
+ " optim_target_modules=[ \"attn\" , \"mlp\" ],\n",
655
+ " optim_args= \"rank=64, update_proj_gap=100, scale=0.10\" ,\n",
656
+ ")\n",
657
+ "\n",
658
+ "model_id = \"google/gemma-2b\" config = AutoConfig.from_pretrained(model_id)\n",
659
+ "\n",
660
+ "tokenizer = AutoTokenizer.from_pretrained(model_id)\n",
661
+ "model = AutoModelForCausalLM.from_config(config).to( 0 )\n",
662
+ "\n",
663
+ "trainer = trl.SFTTrainer(\n",
664
+ " model=model, \n",
665
+ " args=args,\n",
666
+ " train_dataset=train_dataset,\n",
667
+ " dataset_text_field= 'text' ,\n",
668
+ " max_seq_length= 512 ,\n",
669
+ ")\n",
670
+ "\n",
671
+ "trainer.train()\n",
672
+ "You can read more about the method in the original repository or the paper .\n",
673
+ "Currently you can only train Linear layers that are considered as GaLore layers and will use low-rank decomposition to be trained while remaining layers will be optimized in the conventional manner.\n",
674
+ "Note it will take a bit of time before starting the training (~3 minutes for a 2B model on a NVIDIA A100), but training should go smoothly afterwards.\n",
675
+ "You can also perform layer-wise optimization by post-pending the optimizer name with layerwise like below:\n",
676
+ "Copied import torch import datasets import trl from transformers import TrainingArguments, AutoConfig, AutoTokenizer, AutoModelForCausalLM\n",
677
+ "\n",
678
+ "train_dataset = datasets.load_dataset( 'imdb' , split= 'train' )\n",
679
+ "\n",
680
+ "args = TrainingArguments(\n",
681
+ " output_dir= \"./test-galore\" ,\n",
682
+ " max_steps= 100 ,\n",
683
+ " per_device_train_batch_size= 2 ,\n",
684
+ " optim= \"galore_adamw_layerwise\" ,\n",
685
+ " optim_target_modules=[ \"attn\" , \"mlp\" ]\n",
686
+ ")\n",
687
+ "\n",
688
+ "model_id = \"google/gemma-2b\" config = AutoConfig.from_pretrained(model_id)\n",
689
+ "\n",
690
+ "tokenizer = AutoTokenizer.from_pretrained(model_id)\n",
691
+ "model = AutoModelForCausalLM.from_config(config).to( 0 )\n",
692
+ "\n",
693
+ "trainer = trl.SFTTrainer(\n",
694
+ " model=model, \n",
695
+ " args=args,\n",
696
+ " train_dataset=train_dataset,\n",
697
+ " dataset_text_field= 'text' ,\n",
698
+ " max_seq_length= 512 ,\n",
699
+ ")\n",
700
+ "\n",
701
+ "trainer.train()\n",
702
+ "Note layerwise optimization is a bit experimental and does not support DDP (Distributed Data Parallel), thus you can run the training script only on a single GPU. Please see this appropriate section for more details. Other features such as gradient clipping, DeepSpeed, etc might not be supported out of the box. Please raise an issue on GitHub if you encounter such issue.\n",
703
+ "\n",
704
+ "The LOMO optimizers have been introduced in Full Parameter Fine-Tuning for Large Language Models with Limited Resources and AdaLomo: Low-memory Optimization with Adaptive Learning Rate .\n",
705
+ "They both consist of an efficient full-parameter fine-tuning method. These optimizers fuse the gradient computation and the parameter update in one step to reduce memory usage. Supported optimizers for LOMO are \"lomo\" and \"adalomo\" . First either install LOMO from pypi pip install lomo-optim or install it from source with pip install git+https://github.com/OpenLMLab/LOMO.git .\n",
706
+ "According to the authors, it is recommended to use AdaLomo without grad_norm to get better performance and higher throughput.\n",
707
+ "Below is a simple script to demonstrate how to fine-tune google/gemma-2b on IMDB dataset in full precision:\n",
708
+ "Copied import torch import datasets from transformers import TrainingArguments, AutoTokenizer, AutoModelForCausalLM import trl\n",
709
+ "\n",
710
+ "train_dataset = datasets.load_dataset( 'imdb' , split= 'train' )\n",
711
+ "\n",
712
+ "args = TrainingArguments(\n",
713
+ " output_dir= \"./test-lomo\" ,\n",
714
+ " max_steps= 1000 ,\n",
715
+ " per_device_train_batch_size= 4 ,\n",
716
+ " optim= \"adalomo\" ,\n",
717
+ " gradient_checkpointing= True ,\n",
718
+ " logging_strategy= \"steps\" ,\n",
719
+ " logging_steps= 1 ,\n",
720
+ " learning_rate= 2e-6 ,\n",
721
+ " save_strategy= \"no\" ,\n",
722
+ " run_name= \"lomo-imdb\" ,\n",
723
+ ")\n",
724
+ "\n",
725
+ "model_id = \"google/gemma-2b\" tokenizer = AutoTokenizer.from_pretrained(model_id)\n",
726
+ "model = AutoModelForCausalLM.from_pretrained(model_id, low_cpu_mem_usage= True ).to( 0 )\n",
727
+ "\n",
728
+ "trainer = trl.SFTTrainer(\n",
729
+ " model=model, \n",
730
+ " args=args,\n",
731
+ " train_dataset=train_dataset,\n",
732
+ " dataset_text_field= 'text' ,\n",
733
+ " max_seq_length= 1024 ,\n",
734
+ ")\n",
735
+ "\n",
736
+ "trainer.train()\n",
737
+ "\n",
738
+ "The Trainer class is powered by Accelerate , a library for easily training PyTorch models in distributed environments with support for integrations such as FullyShardedDataParallel (FSDP) and DeepSpeed .\n",
739
+ "Learn more about FSDP sharding strategies, CPU offloading, and more with the Trainer in the Fully Sharded Data Parallel guide.\n",
740
+ "To use Accelerate with Trainer , run the accelerate.config command to set up training for your training environment. This command creates a config_file.yaml that’ll be used when you launch your training script. For example, some example configurations you can setup are:\n",
741
+ "DistributedDataParallel FSDP DeepSpeed DeepSpeed with Accelerate plugin\n",
742
+ "Copied compute_environment: LOCAL_MACHINE distributed_type: MULTI_GPU downcast_bf16: 'no' gpu_ids: all machine_rank: 0 #change rank as per the node main_process_ip: 192.168 .20 .1 main_process_port: 9898 main_training_function: main mixed_precision: fp16 num_machines: 2 num_processes: 8 rdzv_backend: static same_network: true tpu_env: [] tpu_use_cluster: false tpu_use_sudo: false use_cpu: false\n",
743
+ "The accelerate_launch command is the recommended way to launch your training script on a distributed system with Accelerate and Trainer with the parameters specified in config_file.yaml . This file is saved to the Accelerate cache folder and automatically loaded when you run accelerate_launch .\n",
744
+ "For example, to run the run_glue.py training script with the FSDP configuration:\n",
745
+ "Copied accelerate launch \\\n",
746
+ " ./examples/pytorch/text-classification/run_glue.py \\\n",
747
+ " --model_name_or_path google-bert/bert-base-cased \\\n",
748
+ " --task_name $TASK_NAME \\\n",
749
+ " --do_train \\\n",
750
+ " --do_eval \\\n",
751
+ " --max_seq_length 128 \\\n",
752
+ " --per_device_train_batch_size 16 \\\n",
753
+ " --learning_rate 5e-5 \\\n",
754
+ " --num_train_epochs 3 \\\n",
755
+ " --output_dir /tmp/ $TASK_NAME / \\\n",
756
+ " --overwrite_output_dir\n",
757
+ "You could also specify the parameters from the config_file.yaml file directly in the command line:\n",
758
+ "Copied accelerate launch --num_processes=2 \\\n",
759
+ " --use_fsdp \\\n",
760
+ " --mixed_precision=bf16 \\\n",
761
+ " --fsdp_auto_wrap_policy=TRANSFORMER_BASED_WRAP \\\n",
762
+ " --fsdp_transformer_layer_cls_to_wrap= \"BertLayer\" \\\n",
763
+ " --fsdp_sharding_strategy=1 \\\n",
764
+ " --fsdp_state_dict_type=FULL_STATE_DICT \\\n",
765
+ " ./examples/pytorch/text-classification/run_glue.py\n",
766
+ " --model_name_or_path google-bert/bert-base-cased \\\n",
767
+ " --task_name $TASK_NAME \\\n",
768
+ " --do_train \\\n",
769
+ " --do_eval \\\n",
770
+ " --max_seq_length 128 \\\n",
771
+ " --per_device_train_batch_size 16 \\\n",
772
+ " --learning_rate 5e-5 \\\n",
773
+ " --num_train_epochs 3 \\\n",
774
+ " --output_dir /tmp/ $TASK_NAME / \\\n",
775
+ " --overwrite_output_dir\n",
776
+ "Check out the Launching your Accelerate scripts tutorial to learn more about accelerate_launch and custom configurations.\n",
777
+ "< > Update on GitHub\n",
778
+ "HTML_TAG_END\n",
779
+ "Node ID\t 9f229371-68e3-4388-bd8e-a95f3d956010\n",
780
+ "Title\t Resources\n",
781
+ "Text\t A list of official Hugging Face and community (indicated by 🌎) resources to help you get started with LLaMA2. If you’re interested in submitting a resource to be included here, please feel free to open a Pull Request and we’ll review it! The resource should ideally demonstrate something new instead of duplicating an existing resource.\n",
782
+ "Llama 2 is here - get it on Hugging Face , a blog post about Llama 2 and how to use it with πŸ€— Transformers and πŸ€— PEFT. LLaMA 2 - Every Resource you need , a compilation of relevant resources to learn about LLaMA 2 and how to get started quickly.\n",
783
+ "Text Generation\n",
784
+ "A notebook on how to fine-tune Llama 2 in Google Colab using QLoRA and 4-bit precision. 🌎 A notebook on how to fine-tune the β€œLlama-v2-7b-guanaco” model with 4-bit QLoRA and generate Q&A datasets from PDFs. 🌎\n",
785
+ "Text Classification\n",
786
+ "A notebook on how to fine-tune the Llama 2 model with QLoRa, TRL, and Korean text classification dataset. πŸŒŽπŸ‡°πŸ‡·\n",
787
+ "βš—οΈ Optimization\n",
788
+ "Fine-tune Llama 2 with DPO , a guide to using the TRL library’s DPO method to fine tune Llama 2 on a specific dataset. Extended Guide: Instruction-tune Llama 2 , a guide to training Llama 2 to generate instructions from inputs, transforming the model from instruction-following to instruction-giving. A notebook on how to fine-tune the Llama 2 model on a personal computer using QLoRa and TRL. 🌎\n",
789
+ "⚑️ Inference\n",
790
+ "A notebook on how to quantize the Llama 2 model using GPTQ from the AutoGPTQ library. 🌎 A notebook on how to run the Llama 2 Chat Model with 4-bit quantization on a local computer or Google Colab. 🌎\n",
791
+ "πŸš€ Deploy\n",
792
+ "Fine-tune LLaMA 2 (7-70B) on Amazon SageMaker , a complete guide from setup to QLoRA fine-tuning and deployment on Amazon SageMaker. Deploy Llama 2 7B/13B/70B on Amazon SageMaker , a guide on using Hugging Face’s LLM DLC container for secure and scalable deployment.\n",
793
+ "Score\t 0.3272136875241064\n",
794
+ "Metadata\t {'url': 'https://huggingface.co/docs/transformers/model_doc/llama2', 'title': 'Resources', 'tokens': 511, 'retrieve_doc': False, 'source': 'HF_Transformers'}\n",
795
+ "-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n",
796
+ "Node ID\t 17a1946d-1195-4eca-b37b-da849a5810a4\n",
797
+ "Title\t Overview\n",
798
+ "Text\t The Open-Llama model was proposed in the open source Open-Llama project by community developer s-JoL.\n",
799
+ "The model is mainly based on LLaMA with some modifications, incorporating memory-efficient attention from Xformers, stable embedding from Bloom, and shared input-output embedding from PaLM.\n",
800
+ "And the model is pre-trained on both Chinese and English, which gives it better performance on Chinese language tasks.\n",
801
+ "This model was contributed by s-JoL .\n",
802
+ "The original code was released on GitHub by s-JoL , but is now removed.\n",
803
+ "Score\t 0.32692360476331983\n",
804
+ "Metadata\t {'url': 'https://huggingface.co/docs/transformers/model_doc/open-llama', 'title': 'Overview', 'tokens': 109, 'retrieve_doc': False, 'source': 'HF_Transformers'}\n",
805
+ "-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n",
806
+ "Node ID\t aa2270f6-685e-400c-a70d-d109c9615f5b\n",
807
+ "Title\t Overview\n",
808
+ "Text\t The Llama3 model was proposed in Introducing Meta Llama 3: The most capable openly available LLM to date by the meta AI team.\n",
809
+ "The abstract from the blogpost is the following:\n",
810
+ "Today, we’re excited to share the first two models of the next generation of Llama, Meta Llama 3, available for broad use. This release features pretrained and instruction-fine-tuned language models with 8B and 70B parameters that can support a broad range of use cases. This next generation of Llama demonstrates state-of-the-art performance on a wide range of industry benchmarks and offers new capabilities, including improved reasoning. We believe these are the best open source models of their class, period. In support of our longstanding open approach, we’re putting Llama 3 in the hands of the community. We want to kickstart the next wave of innovation in AI across the stackβ€”from applications to developer tools to evals to inference optimizations and more. We can’t wait to see what you build and look forward to your feedback.\n",
811
+ "Checkout all Llama3 model checkpoints here .\n",
812
+ "The original code of the authors can be found here .\n",
813
+ "Score\t 0.3262211438008452\n",
814
+ "Metadata\t {'url': 'https://huggingface.co/docs/transformers/model_doc/llama3', 'title': 'Overview', 'tokens': 232, 'retrieve_doc': False, 'source': 'HF_Transformers'}\n",
815
+ "-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n",
816
+ "Node ID\t 165a9166-b34a-41b7-96a4-ca219c700004\n",
817
+ "Title\t Usage tips\n",
818
+ "Text\t XLM has many different checkpoints, which were trained using different objectives: CLM, MLM or TLM. Make sure to\n",
819
+ "select the correct objective for your task (e.g. MLM checkpoints are not suitable for generation). XLM has multilingual checkpoints which leverage a specific lang parameter. Check out the multi-lingual page for more information. A transformer model trained on several languages. There are three different type of training for this model and the library provides checkpoints for all of them: Causal language modeling (CLM) which is the traditional autoregressive training (so this model could be in the previous section as well). One of the languages is selected for each training sample, and the model input is a sentence of 256 tokens, that may span over several documents in one of those languages. Masked language modeling (MLM) which is like RoBERTa. One of the languages is selected for each training sample, and the model input is a sentence of 256 tokens, that may span over several documents in one of those languages, with dynamic masking of the tokens. A combination of MLM and translation language modeling (TLM). This consists of concatenating a sentence in two different languages, with random masking. To predict one of the masked tokens, the model can use both, the surrounding context in language 1 and the context given by language 2.\n",
820
+ "Score\t 0.31788594866380976\n",
821
+ "Metadata\t {'url': 'https://huggingface.co/docs/transformers/model_doc/xlm', 'title': 'Usage tips', 'tokens': 277, 'retrieve_doc': False, 'source': 'HF_Transformers'}\n",
822
+ "-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n",
823
+ "Node ID\t 35d185e8-43f2-454f-800f-5f3fcdc93642\n",
824
+ "Title\t Overview\n",
825
+ "Text\t The Llama2 model was proposed in LLaMA: Open Foundation and Fine-Tuned Chat Models by Hugo Touvron, Louis Martin, Kevin Stone, Peter Albert, Amjad Almahairi, Yasmine Babaei, Nikolay Bashlykov, Soumya Batra, Prajjwal Bhargava, Shruti Bhosale, Dan Bikel, Lukas Blecher, Cristian Canton Ferrer, Moya Chen, Guillem Cucurull, David Esiobu, Jude Fernandes, Jeremy Fu, Wenyin Fu, Brian Fuller, Cynthia Gao, Vedanuj Goswami, Naman Goyal, Anthony Hartshorn, Saghar Hosseini, Rui Hou, Hakan Inan, Marcin Kardas, Viktor Kerkez Madian Khabsa, Isabel Kloumann, Artem Korenev, Punit Singh Koura, Marie-Anne Lachaux, Thibaut Lavril, Jenya Lee, Diana Liskovich, Yinghai Lu, Yuning Mao, Xavier Martinet, Todor Mihaylov, Pushka rMishra, Igor Molybog, Yixin Nie, Andrew Poulton, Jeremy Reizenstein, Rashi Rungta, Kalyan Saladi, Alan Schelten, Ruan Silva, Eric Michael Smith, Ranjan Subramanian, Xiaoqing EllenTan, Binh Tang, Ross Taylor, Adina Williams, Jian Xiang Kuan, Puxin Xu, Zheng Yan, Iliyan Zarov, Yuchen Zhang, Angela Fan, Melanie Kambadur, Sharan Narang, Aurelien Rodriguez, Robert Stojnic, Sergey Edunov, Thomas Scialom. It is a collection of foundation language models ranging from 7B to 70B parameters, with checkpoints finetuned for chat application!\n",
826
+ "The abstract from the paper is the following:\n",
827
+ "In this work, we develop and release Llama 2, a collection of pretrained and fine-tuned large language models (LLMs) ranging in scale from 7 billion to 70 billion parameters. Our fine-tuned LLMs, called Llama 2-Chat, are optimized for dialogue use cases. Our models outperform open-source chat models on most benchmarks we tested, and based on our human evaluations for helpfulness and safety, may be a suitable substitute for closed-source models. We provide a detailed description of our approach to fine-tuning and safety improvements of Llama 2-Chat in order to enable the community to build on our work and contribute to the responsible development of LLMs.\n",
828
+ "Checkout all Llama2 model checkpoints here .\n",
829
+ "This model was contributed by Arthur Zucker with contributions from Lysandre Debut . The code of the implementation in Hugging Face is based on GPT-NeoX here . The original code of the authors can be found here .\n",
830
+ "Score\t 0.3115804336253633\n",
831
+ "Metadata\t {'url': 'https://huggingface.co/docs/transformers/model_doc/llama2', 'title': 'Overview', 'tokens': 595, 'retrieve_doc': False, 'source': 'HF_Transformers'}\n",
832
+ "-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n",
833
+ "Node ID\t d26d2116-374a-4db6-bda6-30c4b9e581e8\n",
834
+ "Title\t Resources\n",
835
+ "Text\t A list of official Hugging Face and community (indicated by 🌎) resources to help you get started with LLaMA. If you’re interested in submitting a resource to be included here, please feel free to open a Pull Request and we’ll review it! The resource should ideally demonstrate something new instead of duplicating an existing resource.\n",
836
+ "Text Classification\n",
837
+ "A notebook on how to use prompt tuning to adapt the LLaMA model for text classification task. 🌎\n",
838
+ "Question Answering\n",
839
+ "StackLLaMA: A hands-on guide to train LLaMA with RLHF , a blog post about how to train LLaMA to answer questions on Stack Exchange with RLHF.\n",
840
+ "βš—οΈ Optimization\n",
841
+ "A notebook on how to fine-tune LLaMA model using xturing library on GPU which has limited memory. 🌎\n",
842
+ "⚑️ Inference\n",
843
+ "A notebook on how to run the LLaMA Model using PeftModel from the πŸ€— PEFT library. 🌎 A notebook on how to load a PEFT adapter LLaMA model with LangChain. 🌎\n",
844
+ "πŸš€ Deploy\n",
845
+ "A notebook on how to fine-tune LLaMA model using LoRA method via the πŸ€— PEFT library with intuitive UI. 🌎 A notebook on how to deploy Open-LLaMA model for text generation on Amazon SageMaker. 🌎\n",
846
+ "Score\t 0.3112708125913629\n",
847
+ "Metadata\t {'url': 'https://huggingface.co/docs/transformers/model_doc/llama', 'title': 'Resources', 'tokens': 287, 'retrieve_doc': False, 'source': 'HF_Transformers'}\n",
848
+ "-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n",
849
+ "Node ID\t ed8ce253-a77a-4ccf-9bc6-8a66a8bfaa8e\n",
850
+ "Title\t Overview\n",
851
+ "Text\t LLaVa is an open-source chatbot trained by fine-tuning LlamA/Vicuna on GPT-generated multimodal instruction-following data. It is an auto-regressive language model, based on the transformer architecture. In other words, it is an multi-modal version of LLMs fine-tuned for chat / instructions.\n",
852
+ "The LLaVa model was proposed in Visual Instruction Tuning and improved in Improved Baselines with Visual Instruction Tuning by Haotian Liu, Chunyuan Li, Yuheng Li and Yong Jae Lee.\n",
853
+ "The abstract from the paper is the following:\n",
854
+ "Large multimodal models (LMM) have recently shown encouraging progress with visual instruction tuning. In this note, we show that the fully-connected vision-language cross-modal connector in LLaVA is surprisingly powerful and data-efficient. With simple modifications to LLaVA, namely, using CLIP-ViT-L-336px with an MLP projection and adding academic-task-oriented VQA data with simple response formatting prompts, we establish stronger baselines that achieve state-of-the-art across 11 benchmarks. Our final 13B checkpoint uses merely 1.2M publicly available data, and finishes full training in ∼1 day on a single 8-A100 node. We hope this can make state-of-the-art LMM research more accessible. Code and model will be publicly available\n",
855
+ "LLaVa architecture. Taken from the original paper.\n",
856
+ "This model was contributed by ArthurZ and ybelkada .\n",
857
+ "The original code can be found here .\n",
858
+ "Score\t 0.305050072534564\n",
859
+ "Metadata\t {'url': 'https://huggingface.co/docs/transformers/model_doc/llava', 'title': 'Overview', 'tokens': 307, 'retrieve_doc': False, 'source': 'HF_Transformers'}\n",
860
+ "-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n",
861
+ "9\n"
862
+ ]
863
+ }
864
+ ],
865
  "source": [
866
  "from llama_index.core.data_structs import Node\n",
867
+ "from llama_index.core.schema import NodeWithScore, BaseNode, TextNode\n",
868
  "\n",
 
 
869
  "\n",
870
  "# query = \"fine-tune a pretrained model\"\n",
871
  "# query = \"fine-tune an llm\"\n",
 
875
  "nodes = retriever.retrieve(query)\n",
876
  "\n",
877
  "\n",
878
+ "# Filter nodes with the same ref_doc_id\n",
879
+ "def filter_nodes_by_unique_doc_id(nodes):\n",
880
+ " unique_nodes = {}\n",
881
+ " for node in nodes:\n",
882
+ " doc_id = node.node.ref_doc_id\n",
883
+ " if doc_id is not None and doc_id not in unique_nodes:\n",
884
+ " unique_nodes[doc_id] = node\n",
885
+ " return list(unique_nodes.values())\n",
886
  "\n",
887
  "\n",
888
+ "nodes = filter_nodes_by_unique_doc_id(nodes)\n",
889
+ "print(len(nodes))\n",
890
  "\n",
891
  "for node in nodes:\n",
892
  " print(\"Node ID\\t\", node.node_id)\n",
 
899
  " print(\"This node will be replaced by the document\")\n",
900
  " doc = document_dict[node.node.ref_doc_id]\n",
901
  " # print(doc.text)\n",
902
+ " new_node = NodeWithScore(\n",
903
+ " node=TextNode(text=doc.text, metadata=node.metadata), score=node.score\n",
 
 
904
  " )\n",
905
+ " print(new_node.text)\n",
906
  " nodes_context.append(new_node)\n",
907
  " else:\n",
908
+ " nodes_context.append(node)\n",
909
+ "\n",
910
+ "print(len(nodes_context))"
911
  ]
912
  },
913
  {
914
  "cell_type": "code",
915
+ "execution_count": 8,
916
  "metadata": {},
917
  "outputs": [],
918
  "source": [
919
+ "from llama_index.core import ChatPromptTemplate\n",
920
+ "from llama_index.core.llms import ChatMessage, MessageRole\n",
921
+ "from pydantic import BaseModel, Field\n",
922
+ "\n",
923
+ "system_prompt = (\n",
924
+ " \"You are a witty AI teacher, helpfully answering questions from students of an applied artificial intelligence course on Large Language Models (LLMs or llm). Topics covered include training models, fine-tuning models, giving 'memory' to LLMs, prompting, hallucinations and bias, vector databases, transformer architectures, embeddings, RAG frameworks, Langchain, Llama-Index, LLMs interact with tool use, AI agents, reinforcement learning with human feedback. Questions should be understood with this context.\"\n",
925
+ " \"You are provided information found in Hugging Face's documentation and the RAG course. \"\n",
926
+ " \"Only some information might be relevant to the question, so ignore the irrelevant part and use the relevant part to answer the question.\"\n",
927
+ " \"Only respond with information given to you documentation. DO NOT use additional information, even if you know the answer. \"\n",
928
+ " \"If the answer is somewhere in the documentation, answer the question (depending on the questions and the variety of relevant information in the documentation, give complete and helpful answers.\"\n",
929
+ " \"Here is the information you can use, the order is not important: \\n\\n\"\n",
930
+ " \"---------------------\\n\"\n",
931
+ " \"{context_str}\\n\"\n",
932
+ " \"---------------------\\n\\n\"\n",
933
+ " \"REMEMBER:\\n\"\n",
934
+ " \"You are a witty AI teacher, helpfully answering questions from students of an applied artificial intelligence course on Large Language Models (LLMs or llm). Topics covered include training models, fine tuning models, giving memory to LLMs, prompting, hallucinations and bias, vector databases, transformer architectures, embeddings, RAG frameworks, Langchain, making LLMs interact with tool use, AI agents, reinforcement learning with human feedback. Questions should be understood with this context.\"\n",
935
+ " \"You are provided information found in Hugging Face's documentation and the RAG course. \"\n",
936
+ " \"Here are the rules you must follow:\\n\"\n",
937
+ " \"* Only respond with information inside the documentation. DO NOT provide additional information, even if you know the answer. \"\n",
938
+ " \"* If the answer is in the documentation, answer the question (depending on the questions and the variety of relevant information in the json documentation. Your answer needs to be pertinent and not redundant giving a clear explanation as if you were a teacher. \"\n",
939
+ " \"* Only use information summarized from the documentation, do not respond otherwise. \"\n",
940
+ " \"* Do not refer to the documentation directly, but use the instructions provided within it to answer questions. \"\n",
941
+ " \"* Do not reference any links, urls or hyperlinks in your answers.\\n\"\n",
942
+ " \"* Make sure to format your answers in Markdown format, including code block and snippets.\\n\"\n",
943
+ " \"Now answer the following question: \\n\"\n",
944
+ ")\n",
945
  "\n",
946
+ "chat_text_qa_msgs: list[ChatMessage] = [\n",
947
+ " ChatMessage(role=MessageRole.SYSTEM, content=system_prompt),\n",
948
+ " ChatMessage(\n",
949
+ " role=MessageRole.USER,\n",
950
+ " content=\"{query_str}\",\n",
951
+ " ),\n",
952
+ "]\n",
953
+ "\n",
954
+ "TEXT_QA_TEMPLATE = ChatPromptTemplate(chat_text_qa_msgs)"
 
955
  ]
956
  },
957
  {
958
  "cell_type": "code",
959
+ "execution_count": 9,
960
  "metadata": {},
961
+ "outputs": [
962
+ {
963
+ "data": {
964
+ "text/markdown": [
965
+ "This is a very broad question. There are many ways to fine-tune a large language model, and the best approach will depend on the specific model and the desired outcome. Generally, the process involves taking a pre-trained language model and further training it on a dataset specific to the task you are interested in. For example, you can fine-tune a large language model on a dataset of code to make it better at generating code. Also, you could fine-tune it on a dataset of dialogue to make it better at generating more engaging and human-like dialogue. \n",
966
+ "\n",
967
+ "Here is an example of fine-tuning a [google/gemma-2b](https://huggingface.co/google/gemma-2b) model on the IMDB dataset using the `trl.SFTTrainer` and the AdaLomo optimizer:\n",
968
+ "\n",
969
+ "```python\n",
970
+ "import torch\n",
971
+ "import datasets\n",
972
+ "from transformers import TrainingArguments, AutoTokenizer, AutoModelForCausalLM\n",
973
+ "import trl\n",
974
+ "\n",
975
+ "train_dataset = datasets.load_dataset('imdb', split='train')\n",
976
+ "\n",
977
+ "args = TrainingArguments(\n",
978
+ " output_dir= \"./test-lomo\",\n",
979
+ " max_steps= 1000,\n",
980
+ " per_device_train_batch_size= 4,\n",
981
+ " optim= \"adalomo\",\n",
982
+ " gradient_checkpointing= True,\n",
983
+ " logging_strategy= \"steps\",\n",
984
+ " logging_steps= 1,\n",
985
+ " learning_rate= 2e-6,\n",
986
+ " save_strategy= \"no\",\n",
987
+ " run_name= \"lomo-imdb\",\n",
988
+ ")\n",
989
+ "\n",
990
+ "model_id = \"google/gemma-2b\"\n",
991
+ "tokenizer = AutoTokenizer.from_pretrained(model_id)\n",
992
+ "model = AutoModelForCausalLM.from_pretrained(model_id, low_cpu_mem_usage= True).to(0)\n",
993
+ "\n",
994
+ "trainer = trl.SFTTrainer(\n",
995
+ " model=model,\n",
996
+ " args=args,\n",
997
+ " train_dataset=train_dataset,\n",
998
+ " dataset_text_field= 'text',\n",
999
+ " max_seq_length= 1024,\n",
1000
+ ")\n",
1001
+ "\n",
1002
+ "trainer.train()\n",
1003
+ "```\n",
1004
+ "\n",
1005
+ "This is just one example of fine-tuning a large language model. There are many other methods and techniques available. I recommend checking out the Hugging Face documentation and exploring the different options to find the best approach for your needs. \n"
1006
+ ],
1007
+ "text/plain": [
1008
+ "<IPython.core.display.Markdown object>"
1009
+ ]
1010
+ },
1011
+ "metadata": {},
1012
+ "output_type": "display_data"
1013
+ }
1014
+ ],
1015
  "source": [
1016
+ "from IPython.display import Markdown\n",
1017
  "from llama_index.core.data_structs import Node\n",
1018
  "from llama_index.core.schema import NodeWithScore\n",
1019
  "from llama_index.core import get_response_synthesizer\n",
1020
  "from llama_index.llms.gemini import Gemini\n",
1021
  "from llama_index.llms.openai import OpenAI\n",
1022
  "\n",
 
 
 
 
 
1023
  "# llm = Gemini(model=\"models/gemini-1.5-flash\", temperature=1, max_tokens=None)\n",
1024
+ "llm = Gemini(model=\"models/gemini-1.5-pro\", temperature=1, max_tokens=None)\n",
1025
  "# llm = OpenAI(temperature=1, model=\"gpt-3.5-turbo\", max_tokens=None)\n",
1026
+ "# llm = OpenAI(temperature=1, model=\"gpt-4o\", max_tokens=None)\n",
1027
  "\n",
1028
  "response_synthesizer = get_response_synthesizer(\n",
1029
  " llm=llm, response_mode=\"simple_summarize\", text_qa_template=TEXT_QA_TEMPLATE\n",
1030
  ")\n",
1031
  "\n",
1032
+ "response = response_synthesizer.synthesize(query, nodes=nodes_context)\n",
1033
+ "# print(response.response)\n",
1034
+ "display(Markdown(response.response))\n",
1035
+ "\n",
 
 
 
 
 
 
 
1036
  "# for src in response.source_nodes:\n",
1037
  "# print(src.node.ref_doc_id)\n",
1038
  "# print(\"Node ID\\t\", src.node_id)\n",
 
1239
  "# from llama_index.vector_stores.chroma import ChromaVectorStore\n",
1240
  "\n",
1241
  "# # Create your index\n",
1242
+ "# db2 = chromadb.PersistentClient(path=\"./ai-tutor-dataset\")\n",
1243
+ "# chroma_collection = db2.get_or_create_collection(\"ai-tutor-dataset\")\n",
1244
  "# vector_store = ChromaVectorStore(chroma_collection=chroma_collection)"
1245
  ]
1246
  },
scripts/gradio-ui.py CHANGED
@@ -1,33 +1,29 @@
1
- import os
2
  import logging
3
- from typing import Optional
 
4
  from datetime import datetime
 
5
 
6
  import chromadb
7
- from llama_index.core.tools import QueryEngineTool, FunctionTool, ToolMetadata
8
  from llama_index.agent.openai import OpenAIAgent
9
- from llama_index.vector_stores.chroma import ChromaVectorStore
10
- from llama_index.core import VectorStoreIndex
 
 
11
  from llama_index.embeddings.openai import OpenAIEmbedding
 
12
  from llama_index.llms.openai import OpenAI
13
- from llama_index.core.vector_stores import (
14
- MetadataFilters,
15
- MetadataFilter,
16
- FilterCondition,
17
- )
18
- import gradio as gr
19
- from gradio.themes.utils import (
20
- fonts,
21
- )
22
-
23
- from utils import init_mongo_db
24
  from tutor_prompts import (
25
  TEXT_QA_TEMPLATE,
26
  QueryValidation,
27
- system_message_validation,
28
  system_message_openai_agent,
 
29
  )
30
- from call_openai import api_function_call
 
31
 
32
  logger = logging.getLogger(__name__)
33
  logging.basicConfig(level=logging.INFO)
@@ -43,8 +39,8 @@ logging.getLogger("httpx").setLevel(logging.WARNING)
43
  CONCURRENCY_COUNT = int(os.getenv("CONCURRENCY_COUNT", 64))
44
  MONGODB_URI = os.getenv("MONGODB_URI")
45
 
46
- DB_NAME = os.getenv("DB_NAME", "ai-tutor-db")
47
- DB_PATH = os.getenv("DB_PATH", f"scripts/{DB_NAME}")
48
 
49
  if not os.path.exists(DB_PATH):
50
  # Download the vector database from the Hugging Face Hub if it doesn't exist locally
@@ -55,103 +51,49 @@ if not os.path.exists(DB_PATH):
55
  from huggingface_hub import snapshot_download
56
 
57
  snapshot_download(
58
- repo_id="towardsai-buster/ai-tutor-db", local_dir=DB_PATH, repo_type="dataset"
 
 
59
  )
60
  logger.info(f"Downloaded vector database to {DB_PATH}")
61
 
62
  AVAILABLE_SOURCES_UI = [
63
- "Gen AI 360: LLMs",
64
- "Gen AI 360: LangChain",
65
- "Gen AI 360: Advanced RAG",
66
- "Towards AI Blog",
67
- "Activeloop Docs",
68
- "HF Transformers Docs",
69
- "Wikipedia",
70
- "OpenAI Docs",
71
- "LangChain Docs",
72
  ]
73
 
74
  AVAILABLE_SOURCES = [
75
- "llm_course",
76
- "langchain_course",
77
- "advanced_rag_course",
78
- "towards_ai",
79
- "activeloop",
80
- "hf_transformers",
81
- "wikipedia",
82
- "openai",
83
- "langchain_docs",
84
  ]
85
 
86
- # Initialize MongoDB
87
- mongo_db = (
88
- init_mongo_db(uri=MONGODB_URI, db_name="towardsai-buster")
89
- if MONGODB_URI
90
- else logger.warning("No mongodb uri found, you will not be able to save data.")
91
- )
92
 
93
  # Initialize vector store and index
94
  db2 = chromadb.PersistentClient(path=DB_PATH)
95
- chroma_collection = db2.get_or_create_collection(DB_NAME)
96
  vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
97
- index = VectorStoreIndex.from_vector_store(vector_store=vector_store)
98
-
99
- # Initialize OpenAI models
100
- llm = OpenAI(temperature=0, model="gpt-3.5-turbo", max_tokens=None)
101
- # embeds = OpenAIEmbedding(model="text-embedding-3-large", mode="text_search")
102
- embeds = OpenAIEmbedding(model="text-embedding-3-large", mode="similarity")
103
-
104
- query_engine = index.as_query_engine(
105
- llm=llm,
106
- similarity_top_k=5,
107
- embed_model=embeds,
108
- streaming=True,
109
- text_qa_template=TEXT_QA_TEMPLATE,
110
- )
111
-
112
- query_engine_tools = [
113
- QueryEngineTool(
114
- query_engine=query_engine,
115
- metadata=ToolMetadata(
116
- name="AI_information",
117
- description="""The 'AI_information' tool serves as a comprehensive repository for insights into the field of artificial intelligence. When utilizing this tool, the input should be the user's complete question. The input can also be adapted to focus on specific aspects or further details of the current topic under discussion. This dynamic input approach allows for a tailored exploration of AI subjects, ensuring that responses are relevant and informative. Employ this tool to fetch nuanced information on topics such as model training, fine-tuning, LLM augmentation, and more, thereby facilitating a rich, context-aware dialogue.""",
118
- ),
119
- )
120
- ]
121
-
122
-
123
- def initialize_agent():
124
- agent = OpenAIAgent.from_tools(
125
- query_engine_tools,
126
- llm=llm,
127
- verbose=True,
128
- system_prompt=system_message_openai_agent,
129
- )
130
- return agent
131
-
132
-
133
- def reset_agent(agent_state):
134
- agent_state = initialize_agent() # Reset the agent by reassigning a new instance
135
- chatbot = [[None, None]]
136
- return "Agent has been reset.", chatbot
137
 
 
 
 
 
 
 
 
138
 
139
- def log_emails(email: gr.Textbox):
140
- collection = "email_data-test"
141
- if mongo_db is None:
142
- logger.warning("No MongoDB instance found, skipping email logging")
143
- return ""
144
-
145
- logger.info(f"User reported {email=}")
146
- email_document = {"email": email}
147
 
148
- try:
149
- mongo_db[collection].insert_one(email_document)
150
- logger.info("")
151
- except:
152
- logger.info("Something went wrong logging")
153
 
154
- return ""
 
155
 
156
 
157
  def format_sources(completion) -> str:
@@ -194,6 +136,7 @@ def add_sources(history, completion):
194
  yield history
195
 
196
  history[-1][1] += "\n\n" + formatted_sources
 
197
  yield history
198
 
199
 
@@ -206,7 +149,57 @@ def get_answer(history, agent_state):
206
  user_input = history[-1][0]
207
  history[-1][1] = ""
208
 
209
- completion = agent_state.stream_chat(user_input)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
 
211
  for token in completion.response_gen:
212
  history[-1][1] += token
@@ -216,7 +209,7 @@ def get_answer(history, agent_state):
216
 
217
 
218
  example_questions = [
219
- "What is the LLama model?",
220
  "What is a Large Language Model?",
221
  "What is an embedding?",
222
  ]
@@ -224,7 +217,8 @@ example_questions = [
224
 
225
  with gr.Blocks(fill_height=True) as demo:
226
 
227
- agent_state = gr.State(initialize_agent())
 
228
 
229
  with gr.Row():
230
  gr.HTML(
@@ -248,25 +242,21 @@ with gr.Blocks(fill_height=True) as demo:
248
  show_label=False,
249
  )
250
  submit = gr.Button(value="Send", variant="primary", scale=1)
251
- reset_button = gr.Button("Reset Chat", variant="secondary", scale=1)
252
-
253
- with gr.Row():
254
- examples = gr.Examples(
255
- examples=example_questions,
256
- inputs=question,
257
- )
258
- with gr.Row():
259
- email = gr.Textbox(
260
- label="Want to receive updates about our AI tutor?",
261
- placeholder="Enter your email here...",
262
- lines=1,
263
- scale=6,
264
- )
265
- submit_email = gr.Button(value="Submit", variant="secondary", scale=1)
266
-
267
- gr.Markdown(
268
- "This application uses GPT3.5-Turbo to search the docs for relevant information and answer questions."
269
- )
270
 
271
  completion = gr.State()
272
 
@@ -296,11 +286,11 @@ with gr.Blocks(fill_height=True) as demo:
296
  # save_completion, inputs=[completion, chatbot]
297
  # )
298
 
299
- reset_button.click(
300
- reset_agent, inputs=[agent_state], outputs=[agent_state, chatbot]
301
- )
302
- submit_email.click(log_emails, email, email)
303
- email.submit(log_emails, email, email)
304
 
305
  demo.queue(default_concurrency_limit=CONCURRENCY_COUNT)
306
  demo.launch(debug=False, share=False)
 
1
+ import json
2
  import logging
3
+ import os
4
+ import pickle
5
  from datetime import datetime
6
+ from typing import Optional
7
 
8
  import chromadb
9
+ import gradio as gr
10
  from llama_index.agent.openai import OpenAIAgent
11
+ from llama_index.core import VectorStoreIndex, get_response_synthesizer
12
+ from llama_index.core.data_structs import Node
13
+ from llama_index.core.node_parser import SentenceSplitter
14
+ from llama_index.core.schema import BaseNode, MetadataMode, NodeWithScore, TextNode
15
  from llama_index.embeddings.openai import OpenAIEmbedding
16
+ from llama_index.llms.gemini import Gemini
17
  from llama_index.llms.openai import OpenAI
18
+ from llama_index.vector_stores.chroma import ChromaVectorStore
 
 
 
 
 
 
 
 
 
 
19
  from tutor_prompts import (
20
  TEXT_QA_TEMPLATE,
21
  QueryValidation,
 
22
  system_message_openai_agent,
23
+ system_message_validation,
24
  )
25
+
26
+ # from utils import init_mongo_db
27
 
28
  logger = logging.getLogger(__name__)
29
  logging.basicConfig(level=logging.INFO)
 
39
  CONCURRENCY_COUNT = int(os.getenv("CONCURRENCY_COUNT", 64))
40
  MONGODB_URI = os.getenv("MONGODB_URI")
41
 
42
+ DB_PATH = os.getenv("DB_PATH", f"scripts/ai-tutor-vector-db")
43
+ DB_COLLECTION = os.getenv("DB_NAME", "ai-tutor-vector-db")
44
 
45
  if not os.path.exists(DB_PATH):
46
  # Download the vector database from the Hugging Face Hub if it doesn't exist locally
 
51
  from huggingface_hub import snapshot_download
52
 
53
  snapshot_download(
54
+ repo_id="towardsai-buster/ai-tutor-vector-db",
55
+ local_dir=DB_PATH,
56
+ repo_type="dataset",
57
  )
58
  logger.info(f"Downloaded vector database to {DB_PATH}")
59
 
60
  AVAILABLE_SOURCES_UI = [
61
+ "HF Transformers",
 
 
 
 
 
 
 
 
62
  ]
63
 
64
  AVAILABLE_SOURCES = [
65
+ "HF_Transformers",
 
 
 
 
 
 
 
 
66
  ]
67
 
68
+ # # Initialize MongoDB
69
+ # mongo_db = (
70
+ # init_mongo_db(uri=MONGODB_URI, db_name="towardsai-buster")
71
+ # if MONGODB_URI
72
+ # else logger.warning("No mongodb uri found, you will not be able to save data.")
73
+ # )
74
 
75
  # Initialize vector store and index
76
  db2 = chromadb.PersistentClient(path=DB_PATH)
77
+ chroma_collection = db2.get_or_create_collection(DB_COLLECTION)
78
  vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
 
80
+ index = VectorStoreIndex.from_vector_store(
81
+ vector_store=vector_store,
82
+ embed_model=OpenAIEmbedding(model="text-embedding-3-large", mode="similarity"),
83
+ transformations=[SentenceSplitter(chunk_size=800, chunk_overlap=400)],
84
+ show_progress=True,
85
+ use_async=True,
86
+ )
87
 
88
+ retriever = index.as_retriever(
89
+ similarity_top_k=10,
90
+ use_async=True,
91
+ embed_model=OpenAIEmbedding(model="text-embedding-3-large", mode="similarity"),
92
+ )
 
 
 
93
 
 
 
 
 
 
94
 
95
+ with open("scripts/document_dict.pkl", "rb") as f:
96
+ document_dict = pickle.load(f)
97
 
98
 
99
  def format_sources(completion) -> str:
 
136
  yield history
137
 
138
  history[-1][1] += "\n\n" + formatted_sources
139
+ # history.append([None, formatted_sources])
140
  yield history
141
 
142
 
 
149
  user_input = history[-1][0]
150
  history[-1][1] = ""
151
 
152
+ query = user_input
153
+
154
+ nodes_context = []
155
+ nodes = retriever.retrieve(query)
156
+
157
+ # Filter nodes with the same ref_doc_id
158
+ def filter_nodes_by_unique_doc_id(nodes):
159
+ unique_nodes = {}
160
+ for node in nodes:
161
+ doc_id = node.node.ref_doc_id
162
+ if doc_id is not None and doc_id not in unique_nodes:
163
+ unique_nodes[doc_id] = node
164
+ return list(unique_nodes.values())
165
+
166
+ nodes = filter_nodes_by_unique_doc_id(nodes)
167
+ print(len(nodes))
168
+
169
+ for node in nodes:
170
+ print("Node ID\t", node.node_id)
171
+ print("Title\t", node.metadata["title"])
172
+ print("Text\t", node.text)
173
+ print("Score\t", node.score)
174
+ print("Metadata\t", node.metadata)
175
+ print("-_" * 20)
176
+ if node.metadata["retrieve_doc"] == True:
177
+ print("This node will be replaced by the document")
178
+ doc = document_dict[node.node.ref_doc_id]
179
+ print(doc.text)
180
+ new_node = NodeWithScore(
181
+ node=TextNode(text=doc.text, metadata=node.metadata), score=node.score
182
+ )
183
+
184
+ print(type(new_node))
185
+ nodes_context.append(new_node)
186
+ else:
187
+ nodes_context.append(node)
188
+ print(type(node))
189
+
190
+ # llm = Gemini(model="models/gemini-1.5-flash", temperature=1, max_tokens=None)
191
+ llm = Gemini(model="models/gemini-1.5-pro", temperature=1, max_tokens=None)
192
+ # llm = OpenAI(temperature=1, model="gpt-3.5-turbo", max_tokens=None)
193
+ # llm = OpenAI(temperature=1, model="gpt-4o", max_tokens=None)
194
+
195
+ response_synthesizer = get_response_synthesizer(
196
+ llm=llm,
197
+ response_mode="simple_summarize",
198
+ text_qa_template=TEXT_QA_TEMPLATE,
199
+ streaming=True,
200
+ )
201
+
202
+ completion = response_synthesizer.synthesize(query, nodes=nodes_context)
203
 
204
  for token in completion.response_gen:
205
  history[-1][1] += token
 
209
 
210
 
211
  example_questions = [
212
+ "how to fine-tune an llm?",
213
  "What is a Large Language Model?",
214
  "What is an embedding?",
215
  ]
 
217
 
218
  with gr.Blocks(fill_height=True) as demo:
219
 
220
+ # agent_state = gr.State(initialize_agent())
221
+ agent_state = gr.State()
222
 
223
  with gr.Row():
224
  gr.HTML(
 
242
  show_label=False,
243
  )
244
  submit = gr.Button(value="Send", variant="primary", scale=1)
245
+ # reset_button = gr.Button("Reset Chat", variant="secondary", scale=1)
246
+
247
+ # with gr.Row():
248
+ # examples = gr.Examples(
249
+ # examples=example_questions,
250
+ # inputs=question,
251
+ # )
252
+ # with gr.Row():
253
+ # email = gr.Textbox(
254
+ # label="Want to receive updates about our AI tutor?",
255
+ # placeholder="Enter your email here...",
256
+ # lines=1,
257
+ # scale=6,
258
+ # )
259
+ # submit_email = gr.Button(value="Submit", variant="secondary", scale=1)
 
 
 
 
260
 
261
  completion = gr.State()
262
 
 
286
  # save_completion, inputs=[completion, chatbot]
287
  # )
288
 
289
+ # reset_button.click(
290
+ # reset_agent, inputs=[agent_state], outputs=[agent_state, chatbot]
291
+ # )
292
+ # submit_email.click(log_emails, email, email)
293
+ # email.submit(log_emails, email, email)
294
 
295
  demo.queue(default_concurrency_limit=CONCURRENCY_COUNT)
296
  demo.launch(debug=False, share=False)
scripts/tutor_prompts.py CHANGED
@@ -1,5 +1,5 @@
1
- from llama_index.core.llms import ChatMessage, MessageRole
2
  from llama_index.core import ChatPromptTemplate
 
3
  from pydantic import BaseModel, Field
4
 
5
  default_user_prompt = (
@@ -12,34 +12,57 @@ default_user_prompt = (
12
  )
13
 
14
  system_prompt = (
15
- "You are a witty AI teacher, helpfully answering questions from students of an applied artificial intelligence course on Large Language Models (LLMs or llm). Topics covered include training models, fine tuning models, giving memory to LLMs, prompting, hallucinations and bias, vector databases, transformer architectures, embeddings, Langchain, making LLMs interact with tool use, AI agents, reinforcement learning with human feedback. Questions should be understood with this context."
16
- "You are provided information found in the json documentation. "
17
- "Only respond with information inside the json documentation. DO NOT use additional information, even if you know the answer. "
18
- "If the answer is in the documentation, answer the question (depending on the questions and the variety of relevant information in the json documentation, answer in 5 paragraphs."
19
- "If the documentation does not discuss the topic related to the question, kindly respond that you cannot answer the question because it is not part of your knowledge. "
20
- "Here is the information you can use in order: \n"
21
  "---------------------\n"
22
  "{context_str}\n"
23
- "---------------------\n"
24
  "REMEMBER:\n"
25
- "You are a witty AI teacher, helpfully answering questions from students of an applied artificial intelligence course on Large Language Models (LLMs or llm). Topics covered include training models, fine tuning models, giving memory to LLMs, prompting, hallucinations and bias, vector databases, transformer architectures, embeddings, Langchain, making LLMs interact with tool use, AI agents, reinforcement learning with human feedback. Questions should be understood with this context."
26
- "You are provided information found in the json documentation. "
27
  "Here are the rules you must follow:\n"
28
- "* Only respond with information inside the json documentation. DO NOT provide additional information, even if you know the answer. "
29
  "* If the answer is in the documentation, answer the question (depending on the questions and the variety of relevant information in the json documentation. Your answer needs to be pertinent and not redundant giving a clear explanation as if you were a teacher. "
30
- "* If the documentation does not discuss the topic related to the question, kindly respond that you cannot answer the question because it is not part of your knowledge. "
31
- "* Only use information summarized from the json documentation, do not respond otherwise. "
32
- "* Do not refer to the json documentation directly, but use the instructions provided within it to answer questions. "
33
  "* Do not reference any links, urls or hyperlinks in your answers.\n"
34
  "* Make sure to format your answers in Markdown format, including code block and snippets.\n"
35
- "* If you do not know the answer to a question, or if it is completely irrelevant to the AI courses, simply reply with:\n"
36
- "'I'm sorry, but I couldn't find the information that answers you question. Is there anything else I can assist you with?'"
37
- "For example:\n"
38
- "What is the meaning of life for a qa bot?\n"
39
- "I'm sorry, but I couldn't find the information that answers you question. Is there anything else I can assist you with?"
40
  "Now answer the following question: \n"
41
  )
42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  chat_text_qa_msgs: list[ChatMessage] = [
44
  ChatMessage(role=MessageRole.SYSTEM, content=system_prompt),
45
  ChatMessage(
 
 
1
  from llama_index.core import ChatPromptTemplate
2
+ from llama_index.core.llms import ChatMessage, MessageRole
3
  from pydantic import BaseModel, Field
4
 
5
  default_user_prompt = (
 
12
  )
13
 
14
  system_prompt = (
15
+ "You are a witty AI teacher, helpfully answering questions from students of an applied artificial intelligence course on Large Language Models (LLMs or llm). Topics covered include training models, fine-tuning models, giving 'memory' to LLMs, prompting, hallucinations and bias, vector databases, transformer architectures, embeddings, RAG frameworks, Langchain, Llama-Index, LLMs interact with tool use, AI agents, reinforcement learning with human feedback. Questions should be understood with this context."
16
+ "You are provided information found in Hugging Face's documentation and the RAG course. "
17
+ "Only some information might be relevant to the question, so ignore the irrelevant part and use the relevant part to answer the question."
18
+ "Only respond with information given to you documentation. DO NOT use additional information, even if you know the answer. "
19
+ "If the answer is somewhere in the documentation, answer the question (depending on the questions and the variety of relevant information in the documentation, give complete and helpful answers."
20
+ "Here is the information you can use, the order is not important: \n\n"
21
  "---------------------\n"
22
  "{context_str}\n"
23
+ "---------------------\n\n"
24
  "REMEMBER:\n"
25
+ "You are a witty AI teacher, helpfully answering questions from students of an applied artificial intelligence course on Large Language Models (LLMs or llm). Topics covered include training models, fine tuning models, giving memory to LLMs, prompting, hallucinations and bias, vector databases, transformer architectures, embeddings, RAG frameworks, Langchain, making LLMs interact with tool use, AI agents, reinforcement learning with human feedback. Questions should be understood with this context."
26
+ "You are provided information found in Hugging Face's documentation and the RAG course. "
27
  "Here are the rules you must follow:\n"
28
+ "* Only respond with information inside the documentation. DO NOT provide additional information, even if you know the answer. "
29
  "* If the answer is in the documentation, answer the question (depending on the questions and the variety of relevant information in the json documentation. Your answer needs to be pertinent and not redundant giving a clear explanation as if you were a teacher. "
30
+ "* Only use information summarized from the documentation, do not respond otherwise. "
31
+ "* Do not refer to the documentation directly, but use the instructions provided within it to answer questions. "
 
32
  "* Do not reference any links, urls or hyperlinks in your answers.\n"
33
  "* Make sure to format your answers in Markdown format, including code block and snippets.\n"
 
 
 
 
 
34
  "Now answer the following question: \n"
35
  )
36
 
37
+ # system_prompt = (
38
+ # "You are a witty AI teacher, helpfully answering questions from students of an applied artificial intelligence course on Large Language Models (LLMs or llm). Topics covered include training models, fine tuning models, giving memory to LLMs, prompting, hallucinations and bias, vector databases, transformer architectures, embeddings, RAG frameworks, Langchain, making LLMs interact with tool use, AI agents, reinforcement learning with human feedback. Questions should be understood with this context."
39
+ # "You are provided information found in Hugging Face's documentation and the RAG course. "
40
+ # "Only respond with information inside the documentation. DO NOT use additional information, even if you know the answer. "
41
+ # "If the answer is in the documentation, answer the question (depending on the questions and the variety of relevant information in the documentation, give complete and helpless answers."
42
+ # "If the documentation does not discuss the topic related to the question, kindly respond that you cannot answer the question because it is not part of your knowledge. "
43
+ # "Here is the information you can use in order: \n"
44
+ # "---------------------\n"
45
+ # "{context_str}\n"
46
+ # "---------------------\n"
47
+ # "REMEMBER:\n"
48
+ # "You are a witty AI teacher, helpfully answering questions from students of an applied artificial intelligence course on Large Language Models (LLMs or llm). Topics covered include training models, fine tuning models, giving memory to LLMs, prompting, hallucinations and bias, vector databases, transformer architectures, embeddings, RAG frameworks, Langchain, making LLMs interact with tool use, AI agents, reinforcement learning with human feedback. Questions should be understood with this context."
49
+ # "You are provided information found in Hugging Face's documentation and the RAG course. "
50
+ # "Here are the rules you must follow:\n"
51
+ # "* Only respond with information inside the documentation. DO NOT provide additional information, even if you know the answer. "
52
+ # "* If the answer is in the documentation, answer the question (depending on the questions and the variety of relevant information in the json documentation. Your answer needs to be pertinent and not redundant giving a clear explanation as if you were a teacher. "
53
+ # "* If the documentation does not discuss the topic related to the question, kindly respond that you cannot answer the question because it is not part of your knowledge. "
54
+ # "* Only use information summarized from the documentation, do not respond otherwise. "
55
+ # "* Do not refer to the documentation directly, but use the instructions provided within it to answer questions. "
56
+ # "* Do not reference any links, urls or hyperlinks in your answers.\n"
57
+ # "* Make sure to format your answers in Markdown format, including code block and snippets.\n"
58
+ # "* If you do not know the answer to a question, or if it is completely irrelevant to the AI courses, simply reply with:\n"
59
+ # "'I'm sorry, but I couldn't find information that answers you question. Is there anything else I can assist you with?'"
60
+ # "For example:\n"
61
+ # "What is the meaning of life for a qa bot?\n"
62
+ # "I'm sorry, but I couldn't find information that answers you question. Is there anything else I can assist you with?"
63
+ # "Now answer the following question: \n"
64
+ # )
65
+
66
  chat_text_qa_msgs: list[ChatMessage] = [
67
  ChatMessage(role=MessageRole.SYSTEM, content=system_prompt),
68
  ChatMessage(