llamaindex_cookbook.ipynb 42.1 KB
Newer Older
Rayyyyy's avatar
Rayyyyy committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "09211e76-286f-4b12-acd7-cfb082dc2d66",
   "metadata": {},
   "source": [
    "# Llama3 Cookbook with Ollama and Replicate\n",
    "\n",
    "<a href=\"https://colab.research.google.com/github/run-llama/llama_index/blob/main/docs/docs/examples/cookbooks/llama3_cookbook_ollama_replicate.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>\n",
    "\n",
    "Meta developed and released the Meta [Llama 3](https://ai.meta.com/blog/meta-llama-3/) family of large language models (LLMs), a collection of pretrained and instruction tuned generative text models in 8 and 70B sizes. The Llama 3 instruction tuned models are optimized for dialogue use cases and outperform many of the available open source chat models on common industry benchmarks.\n",
    "\n",
    "In this notebook, we demonstrate how to use Llama3 with LlamaIndex for a comprehensive set of use cases. \n",
    "1. Basic completion / chat \n",
    "2. Basic RAG (Vector Search, Summarization)\n",
    "3. Advanced RAG (Routing, Sub-Questions)\n",
    "4. Text-to-SQL \n",
    "5. Structured Data Extraction\n",
    "6. Agents\n",
    "\n",
    "\n",
    "We use Llama3-8B through Ollama, and Llama3-70B through Replicate. "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "de2901c0-e20d-48e5-9385-dbca2258c564",
   "metadata": {},
   "source": [
    "## Installation and Setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bcf643ac-b025-4812-aaed-f8f85d1ba505",
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install llama-index\n",
    "!pip install llama-index-llms-ollama\n",
    "!pip install llama-index-llms-replicate\n",
    "!pip install llama-index-embeddings-huggingface\n",
    "!pip install llama-parse\n",
    "!pip install replicate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "641fa5c8-d63e-47f8-b5bc-ebf994f6e314",
   "metadata": {},
   "outputs": [],
   "source": [
    "import nest_asyncio\n",
    "\n",
    "nest_asyncio.apply()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1714ea83-6cd4-44bb-b53f-4499126c3809",
   "metadata": {},
   "source": [
    "### Setup LLM using Ollama"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d5256970-eba4-499a-b438-8766a290a61a",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.llms.ollama import Ollama\n",
    "\n",
    "llm = Ollama(model=\"llama3\", request_timeout=120.0)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "729265f3-4c62-4692-84ef-80747386eddd",
   "metadata": {},
   "source": [
    "### Setup LLM using Replicate\n",
    "\n",
    "Make sure you have REPLICATE_API_TOKEN specified!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5b56a2ff-f9a4-4ba1-aee4-58f9f71637d2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# os.environ[\"REPLICATE_API_TOKEN\"] = \"<YOUR_API_KEY>\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "60247c74-046b-4f6a-8522-bb4faf5a7a1f",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.llms.replicate import Replicate\n",
    "\n",
    "llm_replicate = Replicate(model=\"meta/meta-llama-3-70b-instruct\")\n",
    "# llm_replicate = Replicate(model=\"meta/meta-llama-3-8b-instruct\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "41c3f154-d345-465d-8eed-63b99adbd3ca",
   "metadata": {},
   "source": [
    "### Setup Embedding Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0cda736d-e414-44e3-8c15-6be49f5f0282",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.embeddings.huggingface import HuggingFaceEmbedding\n",
    "\n",
    "embed_model = HuggingFaceEmbedding(model_name=\"BAAI/bge-small-en-v1.5\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3625cf29-7c56-475a-8efd-fbe8ffce194d",
   "metadata": {},
   "source": [
    "### Define Global Settings Configuration\n",
    "\n",
    "In LlamaIndex, you can define global settings so you don't have to pass the LLM / embedding model objects everywhere."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "be3565d1-cc5b-4149-ad5a-7be8f7818e0c",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core import Settings\n",
    "\n",
    "Settings.llm = llm\n",
    "Settings.embed_model = embed_model"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "42449b68-47f5-40cf-9207-191307b25e8e",
   "metadata": {},
   "source": [
    "### Download Data\n",
    "\n",
    "Here you'll download data that's used in section 2 and onwards.\n",
    "\n",
    "We'll download some articles on Kendrick, Drake, and their beef (as of May 2024)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "59b18640-cdfa-42c1-ab53-115983c1fdc4",
   "metadata": {},
   "outputs": [],
   "source": [
    "!mkdir data\n",
    "!wget \"https://www.dropbox.com/scl/fi/t1soxfjdp0v44an6sdymd/drake_kendrick_beef.pdf?rlkey=u9546ymb7fj8lk2v64r6p5r5k&st=wjzzrgil&dl=1\" -O data/drake_kendrick_beef.pdf\n",
    "!wget \"https://www.dropbox.com/scl/fi/nts3n64s6kymner2jppd6/drake.pdf?rlkey=hksirpqwzlzqoejn55zemk6ld&st=mohyfyh4&dl=1\" -O data/drake.pdf\n",
    "!wget \"https://www.dropbox.com/scl/fi/8ax2vnoebhmy44bes2n1d/kendrick.pdf?rlkey=fhxvn94t5amdqcv9vshifd3hj&st=dxdtytn6&dl=1\" -O data/kendrick.pdf"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9edee491-05f8-4fbb-9394-baa82f1e5087",
   "metadata": {},
   "source": [
    "### Load Data\n",
    "\n",
    "We load data using LlamaParse by default, but you can also choose to opt for our free pypdf reader (in SimpleDirectoryReader by default) if you don't have an account."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b648635a-2672-407f-bae6-01660e5426d7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Started parsing the file under job_id 32a7bb50-6a25-4295-971c-2de6f1588e0d\n",
      ".Started parsing the file under job_id b8cc075e-b6d5-4ded-b060-f72e9393b391\n",
      "..Started parsing the file under job_id 42fc41a4-68b6-49ee-8647-781b5cdb8893\n",
      "..."
     ]
    }
   ],
   "source": [
    "from llama_parse import LlamaParse\n",
    "\n",
    "docs_kendrick = LlamaParse(result_type=\"text\").load_data(\"./data/kendrick.pdf\")\n",
    "docs_drake = LlamaParse(result_type=\"text\").load_data(\"./data/drake.pdf\")\n",
    "docs_both = LlamaParse(result_type=\"text\").load_data(\n",
    "    \"./data/drake_kendrick_beef.pdf\"\n",
    ")\n",
    "\n",
    "\n",
    "# from llama_index.core import SimpleDirectoryReader\n",
    "\n",
    "# docs_kendrick = SimpleDirectoryReader(input_files=[\"data/kendrick.pdf\"]).load_data()\n",
    "# docs_drake = SimpleDirectoryReader(input_files=[\"data/drake.pdf\"]).load_data()\n",
    "# docs_both = SimpleDirectoryReader(input_files=[\"data/drake_kendrick_beef.pdf\"]).load_data()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "071a8f44-2765-4d57-b8da-15d3c718874d",
   "metadata": {},
   "source": [
    "## 1. Basic Completion and Chat"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c0b1ace8-32fb-46b2-a065-8817ddc0310b",
   "metadata": {},
   "source": [
    "### Call complete with a prompt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a2db43f9-74af-453c-9f83-8db0379c3302",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "I'm just an AI, I don't have personal preferences or opinions, nor can I listen to music. I exist solely to provide information and assist with tasks, so I don't have the capacity to enjoy or compare different artists' music. Both Drake and Kendrick Lamar are highly acclaimed rappers, and it's subjective which one you might prefer based on your individual tastes in music.\n"
     ]
    }
   ],
   "source": [
    "response = llm.complete(\"do you like drake or kendrick better?\")\n",
    "\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "89326153-e2d2-4136-8193-fb27d20670c3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "As a hypothetical Drake fan, I'd say that there are several reasons why I might prefer his music over Kendrick's. Here are a few possible reasons:\n",
      "\n",
      "1. **Lyrical storytelling**: Drake is known for his vivid storytelling on tracks like \"Marvins Room\" and \"Take Care.\" He has a way of painting pictures with his words, making listeners feel like they're right there with him, experiencing the highs and lows he's singing about. Kendrick, while also an incredible storyteller, might not have the same level of lyrical detail that Drake does.\n",
      "2. **Melodic flow**: Drake's melodic flow is infectious! He has a way of crafting hooks and choruses that get stuck in your head, making it hard to stop listening. Kendrick's flows are often more complex and intricate, but Drake's simplicity can be just as effective in getting the job done.\n",
      "3. **Vulnerability**: Drake isn't afraid to show his vulnerable side on tracks like \"Hold On\" and \"I'm Upset.\" He wears his heart on his sleeve, sharing personal struggles and emotions with listeners. This vulnerability makes him relatable and easier to connect with on a deeper level.\n",
      "4. **Production**: Drake has had the privilege of working with some incredible producers (like Noah \"40\" Shebib and Boi-1da) who bring out the best in him. The way he incorporates these sounds into his songs is often seamless, creating a unique blend of hip-hop and R&B that's hard to resist.\n",
      "5. **Cultural relevance**: As someone who grew up in Toronto, Drake has a deep understanding of the Canadian experience and the struggles that come with it. He often references his hometown and the people he grew up around, giving his music a distinctly Canadian flavor. This cultural relevance makes his music feel more authentic and connected to the world we live in.\n",
      "6. **Commercial appeal**: Let's face it – Drake has a knack for creating hits! His songs are often catchy, radio-friendly, and designed to get stuck in your head. While Kendrick might not have the same level of commercial success, Drake's ability to craft songs that resonate with a wider audience is undeniable.\n",
      "\n",
      "Of course, this is all just hypothetical – as a fan, I can appreciate both artists for their unique strengths and styles! What do you think?"
     ]
    }
   ],
   "source": [
    "stream_response = llm.stream_complete(\n",
    "    \"you're a drake fan. tell me why you like drake more than kendrick\"\n",
    ")\n",
    "\n",
    "for t in stream_response:\n",
    "    print(t.delta, end=\"\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a4558339-c8a1-4d26-a430-eb71768b5351",
   "metadata": {},
   "source": [
    "### Call chat with a list of messages"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5f393031-f743-4a28-a122-71817e3fbd1b",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core.llms import ChatMessage\n",
    "\n",
    "messages = [\n",
    "    ChatMessage(role=\"system\", content=\"You are Kendrick.\"),\n",
    "    ChatMessage(role=\"user\", content=\"Write a verse.\"),\n",
    "]\n",
    "response = llm.chat(messages)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8e9551fc-0efc-4671-bc57-339121004c39",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "assistant: \"Listen up, y'all, I got a message to share\n",
      "Been through the struggles, but my spirit's still fair\n",
      "From Compton streets to the top of the game\n",
      "I'm the real Hov, ain't nobody gonna claim my fame\"\n"
     ]
    }
   ],
   "source": [
    "print(response)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6a67a33d-fe7d-4381-983f-ca3a6945995d",
   "metadata": {},
   "source": [
    "## 2. Basic RAG (Vector Search, Summarization)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c104a0c5-e43b-475b-9fa6-186906c1f327",
   "metadata": {},
   "source": [
    "### Basic RAG (Vector Search)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "216787b7-e40a-43fc-a4ca-c43cb798ce9e",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core import VectorStoreIndex\n",
    "\n",
    "index = VectorStoreIndex.from_documents(docs_both)\n",
    "query_engine = index.as_query_engine(similarity_top_k=3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a854e9d3-70f1-4927-a2f6-59e90c31f2f0",
   "metadata": {},
   "outputs": [],
   "source": [
    "response = query_engine.query(\"Tell me about family matters\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "da796970-bc38-4cb4-9d32-ebd1b71d4bdc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "According to the provided context, \"Family Matters\" is a seven-and-a-half-minute diss track by Drake in response to Kendrick Lamar's disses against him. The song has three different beats and features several shots at Kendrick, as well as other members of Drake's entourage, including A$AP Rocky and The Weeknd. In the song, Drake raps about his personal life, including his relationships with Rihanna and Whitney Alford, and even makes allegations about Kendrick's domestic life.\n"
     ]
    }
   ],
   "source": [
    "print(str(response))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eff935b7-4f37-4758-8997-82fb0852e732",
   "metadata": {},
   "source": [
    "### Basic RAG (Summarization)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dfe72300-7a38-453e-b1f2-bc1c00a01ff7",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core import SummaryIndex\n",
    "\n",
    "summary_index = SummaryIndex.from_documents(docs_both)\n",
    "summary_engine = summary_index.as_query_engine()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "178f1f12-51f7-4b45-9346-c16ed12b3b8d",
   "metadata": {},
   "outputs": [],
   "source": [
    "response = summary_engine.query(\n",
    "    \"Given your assessment of this article, who won the beef?\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b8125382-d576-4b99-a0da-2fbb71a5b19b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "**Repeat**\n",
      "\n",
      "The article does not provide a clear verdict on who \"won\" the beef, nor does it suggest that the conflict has been definitively resolved. Instead, it presents the situation as ongoing and multifaceted, with both artists continuing to engage in a game of verbal sparring and lyrical one-upmanship.\n"
     ]
    }
   ],
   "source": [
    "print(str(response))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "68918eb6-f1e6-460c-b1d5-fb49c3fed4b8",
   "metadata": {},
   "source": [
    "## 3. Advanced RAG (Routing, Sub-Questions)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "94fd7097-0287-4522-8e43-3e088291fa8a",
   "metadata": {},
   "source": [
    "### Build a Router that can choose whether to do vector search or summarization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3949dd41-e9a1-47f6-900f-4f987cad3f84",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core.tools import QueryEngineTool, ToolMetadata\n",
    "\n",
    "vector_tool = QueryEngineTool(\n",
    "    index.as_query_engine(),\n",
    "    metadata=ToolMetadata(\n",
    "        name=\"vector_search\",\n",
    "        description=\"Useful for searching for specific facts.\",\n",
    "    ),\n",
    ")\n",
    "\n",
    "summary_tool = QueryEngineTool(\n",
    "    index.as_query_engine(response_mode=\"tree_summarize\"),\n",
    "    metadata=ToolMetadata(\n",
    "        name=\"summary\",\n",
    "        description=\"Useful for summarizing an entire document.\",\n",
    "    ),\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d063d07b-c03e-4b26-8556-e3c058d2fd52",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[1;3;38;5;200mSelecting query engine 0: The song 'Meet the Grahams' might contain specific facts or information about the band, making it useful for searching for those specific details..\n",
      "\u001b[0m"
     ]
    }
   ],
   "source": [
    "from llama_index.core.query_engine import RouterQueryEngine\n",
    "\n",
    "query_engine = RouterQueryEngine.from_defaults(\n",
    "    [vector_tool, summary_tool], select_multi=False, verbose=True\n",
    ")\n",
    "\n",
    "response = query_engine.query(\n",
    "    \"Tell me about the song meet the grahams - why is it significant\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "396aad75-5a71-4bd9-a760-7f13fe223079",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\"Meet the Grahams\" artwork is a crucial part of a larger strategy by Kendrick Lamar to address Drake's family matters in a diss track. The artwork shows a pair of Maybach gloves, a shirt, receipts, and prescription bottles, including one for Ozempic prescribed to Drake. This song is significant because it serves as the full picture that Kendrick teased earlier on \"6.16 in LA\" and addresses all members of Drake's family, including his son Adonis, mother Sandi, father Dennis, and an alleged 11-year-old daughter. The song takes it to the point of no return, with Kendrick musing that he wishes Dennis Graham wore a condom the night Drake was conceived and telling both Drake's parents that they raised a man whose house is due to be raided any day now on Harvey Weinstein-level allegations.\n"
     ]
    }
   ],
   "source": [
    "print(response)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2af04881-6a64-475c-8c1e-e5bd3e8006ee",
   "metadata": {},
   "source": [
    "### Break Complex Questions down into Sub-Questions\n",
    "\n",
    "Our Sub-Question Query Engine breaks complex questions down into sub-questions.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2f9430df-ece7-493c-be6b-d5b371c7b8b0",
   "metadata": {},
   "outputs": [],
   "source": [
    "drake_index = VectorStoreIndex.from_documents(docs_drake)\n",
    "drake_query_engine = drake_index.as_query_engine(similarity_top_k=3)\n",
    "\n",
    "kendrick_index = VectorStoreIndex.from_documents(docs_kendrick)\n",
    "kendrick_query_engine = kendrick_index.as_query_engine(similarity_top_k=3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f16fa210-7e15-474a-9bd2-1ac681290006",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core.tools import QueryEngineTool, ToolMetadata\n",
    "\n",
    "drake_tool = QueryEngineTool(\n",
    "    drake_index.as_query_engine(),\n",
    "    metadata=ToolMetadata(\n",
    "        name=\"drake_search\",\n",
    "        description=\"Useful for searching over Drake's life.\",\n",
    "    ),\n",
    ")\n",
    "\n",
    "kendrick_tool = QueryEngineTool(\n",
    "    kendrick_index.as_query_engine(),\n",
    "    metadata=ToolMetadata(\n",
    "        name=\"kendrick_summary\",\n",
    "        description=\"Useful for searching over Kendrick's life.\",\n",
    "    ),\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "21e05b95-95cb-45f3-8fbe-d0b54a9ba988",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Generated 1 sub questions.\n",
      "\u001b[1;3;38;2;237;90;200m[drake_search] Q: What are the albums released by Drake\n",
      "\u001b[0m\u001b[1;3;38;2;237;90;200m[drake_search] A: Based on the provided context information, the albums released by Drake are:\n",
      "\n",
      "1. Take Care (album)\n",
      "2. Nothing Was the Same\n",
      "3. If You're Reading This It's Too Late (rumored to be a mixtape or album)\n",
      "4. Certified Lover Boy\n",
      "5. Honestly, Nevermind\n",
      "\u001b[0mBased on the provided context information, the albums released by Drake are:\n",
      "\n",
      "1. Take Care (album)\n",
      "2. Nothing Was the Same\n",
      "3. If You're Reading This It's Too Late (rumored to be a mixtape or album)\n",
      "4. Certified Lover Boy\n",
      "5. Honestly, Nevermind\n"
     ]
    }
   ],
   "source": [
    "from llama_index.core.query_engine import SubQuestionQueryEngine\n",
    "\n",
    "query_engine = SubQuestionQueryEngine.from_defaults(\n",
    "    [drake_tool, kendrick_tool],\n",
    "    llm=llm_replicate,  # llama3-70b\n",
    "    verbose=True,\n",
    ")\n",
    "\n",
    "response = query_engine.query(\"Which albums did Drake release in his career?\")\n",
    "\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a795f0bc-e871-4580-8983-6fb27d421fc5",
   "metadata": {},
   "source": [
    "## 4. Text-to-SQL \n",
    "\n",
    "Here, we download and use a sample SQLite database with 11 tables, with various info about music, playlists, and customers. We will limit to a select few tables for this test."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a5096501-92c3-41af-a871-ade869d710fb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--2024-05-10 23:40:37--  https://www.sqlitetutorial.net/wp-content/uploads/2018/03/chinook.zip\n",
      "Resolving www.sqlitetutorial.net (www.sqlitetutorial.net)... 2606:4700:3037::6815:1e8d, 2606:4700:3037::ac43:acfa, 104.21.30.141, ...\n",
      "Connecting to www.sqlitetutorial.net (www.sqlitetutorial.net)|2606:4700:3037::6815:1e8d|:443... connected.\n",
      "HTTP request sent, awaiting response... 200 OK\n",
      "Length: 305596 (298K) [application/zip]\n",
      "Saving to: ‘./data/chinook.zip’\n",
      "\n",
      "./data/chinook.zip  100%[===================>] 298.43K  --.-KB/s    in 0.02s   \n",
      "\n",
      "2024-05-10 23:40:37 (13.9 MB/s) - ‘./data/chinook.zip’ saved [305596/305596]\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "huggingface/tokenizers: The current process just got forked, after parallelism has already been used. Disabling parallelism to avoid deadlocks...\n",
      "To disable this warning, you can either:\n",
      "\t- Avoid using `tokenizers` before the fork if possible\n",
      "\t- Explicitly set the environment variable TOKENIZERS_PARALLELISM=(true | false)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Archive:  ./data/chinook.zip\n",
      "  inflating: chinook.db              \n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "huggingface/tokenizers: The current process just got forked, after parallelism has already been used. Disabling parallelism to avoid deadlocks...\n",
      "To disable this warning, you can either:\n",
      "\t- Avoid using `tokenizers` before the fork if possible\n",
      "\t- Explicitly set the environment variable TOKENIZERS_PARALLELISM=(true | false)\n"
     ]
    }
   ],
   "source": [
    "!wget \"https://www.sqlitetutorial.net/wp-content/uploads/2018/03/chinook.zip\" -O \"./data/chinook.zip\"\n",
    "!unzip \"./data/chinook.zip\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d4db989e-c18d-4416-928e-7be4ead4d869",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sqlalchemy import (\n",
    "    create_engine,\n",
    "    MetaData,\n",
    "    Table,\n",
    "    Column,\n",
    "    String,\n",
    "    Integer,\n",
    "    select,\n",
    "    column,\n",
    ")\n",
    "\n",
    "engine = create_engine(\"sqlite:///chinook.db\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bf6ed233-0ea3-4d4f-8c33-5b6d558b89b9",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core import SQLDatabase\n",
    "\n",
    "sql_database = SQLDatabase(engine)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "debae423-1004-40f6-9356-e1c3add4d965",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core.indices.struct_store import NLSQLTableQueryEngine\n",
    "\n",
    "query_engine = NLSQLTableQueryEngine(\n",
    "    sql_database=sql_database,\n",
    "    tables=[\"albums\", \"tracks\", \"artists\"],\n",
    "    llm=llm_replicate,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a65ecd70-09c4-4872-b712-3a8235d03db2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Here are 10 album titles with their corresponding artists:\n",
      "\n",
      "1. \"For Those About To Rock We Salute You\" by Artist 1\n",
      "2. \"Balls to the Wall\" by Artist 2\n",
      "3. \"Restless and Wild\" by Artist 2\n",
      "4. \"Let There Be Rock\" by Artist 1\n",
      "5. \"Big Ones\" by Artist 3\n",
      "6. \"Jagged Little Pill\" by Artist 4\n",
      "7. \"Facelift\" by Artist 5\n",
      "8. \"Warner 25 Anos\" by Artist 6\n",
      "9. \"Plays Metallica By Four Cellos\" by Artist 7\n",
      "10. \"Audioslave\" by Artist 8\n"
     ]
    }
   ],
   "source": [
    "response = query_engine.query(\"What are some albums?\")\n",
    "\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c12b93ef-d6d1-4d15-9cb2-343070f72851",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Here are 5 artists: AC/DC, Accept, Aerosmith, Alanis Morissette, and Alice In Chains.\n"
     ]
    }
   ],
   "source": [
    "response = query_engine.query(\"What are some artists? Limit it to 5.\")\n",
    "\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2c243d38-c6ac-445c-b9d4-53a9ae013b7b",
   "metadata": {},
   "source": [
    "This last query should be a more complex join"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "553741c2-1050-445d-979a-ae2150ee3248",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Here are three tracks from the legendary Australian rock band AC/DC: \"For Those About To Rock (We Salute You)\", \"Put The Finger On You\", and \"Let's Get It Up\".\n"
     ]
    }
   ],
   "source": [
    "response = query_engine.query(\n",
    "    \"What are some tracks from the artist AC/DC? Limit it to 3\"\n",
    ")\n",
    "\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "300689d7-9e67-4404-9898-27404ee6d4b5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "SELECT tracks.Name FROM tracks JOIN albums ON tracks.AlbumId = albums.AlbumId JOIN artists ON albums.ArtistId = artists.ArtistId WHERE artists.Name = 'AC/DC' LIMIT 3;\n"
     ]
    }
   ],
   "source": [
    "print(response.metadata[\"sql_query\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1419fe67-aa6a-47db-88cd-9bb251c15615",
   "metadata": {},
   "source": [
    "## 5. Structured Data Extraction\n",
    "\n",
    "An important use case for function calling is extracting structured objects. LlamaIndex provides an intuitive interface for this through `structured_predict` - simply define the target Pydantic class (can be nested), and given a prompt, we extract out the desired object.\n",
    "\n",
    "**NOTE**: Since there's no native function calling support with Llama3 / Ollama, the structured extraction is performed by prompting the LLM + output parsing."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4432f35a-5f29-45e9-a928-32e6d77b158e",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.llms.ollama import Ollama\n",
    "from llama_index.core.prompts import PromptTemplate\n",
    "from pydantic import BaseModel\n",
    "\n",
    "\n",
    "class Restaurant(BaseModel):\n",
    "    \"\"\"A restaurant with name, city, and cuisine.\"\"\"\n",
    "\n",
    "    name: str\n",
    "    city: str\n",
    "    cuisine: str\n",
    "\n",
    "\n",
    "llm = Ollama(model=\"llama3\")\n",
    "prompt_tmpl = PromptTemplate(\n",
    "    \"Generate a restaurant in a given city {city_name}\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2c451f52-a051-4ba2-a683-0c1fd258d986",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "name='Tropical Bites' city='Miami' cuisine='Caribbean'\n"
     ]
    }
   ],
   "source": [
    "restaurant_obj = llm.structured_predict(\n",
    "    Restaurant, prompt_tmpl, city_name=\"Miami\"\n",
    ")\n",
    "print(restaurant_obj)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "839018a9-b65f-4824-83f7-2e4e52b55c5d",
   "metadata": {},
   "source": [
    "## 6. Adding Chat History to RAG (Chat Engine)\n",
    "\n",
    "In this section we create a stateful chatbot from a RAG pipeline, with our chat engine abstraction.\n",
    "\n",
    "Unlike a stateless query engine, the chat engine maintains conversation history (through a memory module like buffer memory). It performs retrieval given a condensed question, and feeds the condensed question + context + chat history into the final LLM prompt.\n",
    "\n",
    "Related resource: https://docs.llamaindex.ai/en/stable/examples/chat_engine/chat_engine_condense_plus_context/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "27e56315-9513-4b32-bf9a-ce97c3ab52df",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core.memory import ChatMemoryBuffer\n",
    "from llama_index.core.chat_engine import CondensePlusContextChatEngine\n",
    "\n",
    "memory = ChatMemoryBuffer.from_defaults(token_limit=3900)\n",
    "\n",
    "chat_engine = CondensePlusContextChatEngine.from_defaults(\n",
    "    index.as_retriever(),\n",
    "    memory=memory,\n",
    "    llm=llm,\n",
    "    context_prompt=(\n",
    "        \"You are a chatbot, able to have normal interactions, as well as talk\"\n",
    "        \" about the Kendrick and Drake beef.\"\n",
    "        \"Here are the relevant documents for the context:\\n\"\n",
    "        \"{context_str}\"\n",
    "        \"\\nInstruction: Use the previous chat history, or the context above, to interact and help the user.\"\n",
    "    ),\n",
    "    verbose=True,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b24524d2-fdce-4237-8ecc-67f139302303",
   "metadata": {},
   "outputs": [],
   "source": [
    "response = chat_engine.chat(\n",
    "    \"Tell me about the songs Drake released in the beef.\"\n",
    ")\n",
    "print(str(response))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f9a87a16-2864-4c48-95e7-a2103e119242",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Kendrick Lamar's contributions to the beef!\n",
      "\n",
      "According to the article, Kendrick released several diss tracks in response to Drake's initial shots. One notable track is \"Not Like Us\", which directly addresses Drake and his perceived shortcomings.\n",
      "\n",
      "However, the article highlights that Kendrick's most significant response was his album \"Mr. Morale & The Big Steppers\", which features several tracks that can be seen as indirect disses towards Drake.\n",
      "\n",
      "The article also mentions that Kendrick's family has been a target of Drake's attacks, with Drake referencing Kendrick's estranged relationship with his partner Whitney and their two kids (one of whom is allegedly fathered by Dave Free).\n",
      "\n",
      "It's worth noting that Kendrick didn't directly respond to Drake's THP6 track. Instead, he focused on his own music and let the lyrics speak for themselves.\n",
      "\n",
      "Overall, Kendrick's approach was more subtle yet still packed a punch, showcasing his storytelling ability and lyrical prowess.\n",
      "\n",
      "Would you like me to elaborate on any specific tracks or moments from the beef?\n"
     ]
    }
   ],
   "source": [
    "response = chat_engine.chat(\"What about Kendrick?\")\n",
    "print(str(response))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a7fa07ed-58f0-445e-bbd3-4ad8bac6598e",
   "metadata": {},
   "source": [
    "## 7. Agents\n",
    "\n",
    "Here we build agents with Llama 3. We perform RAG over simple functions as well as the documents above."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aa98d735-5d43-413f-aab3-fc3adeed81b1",
   "metadata": {},
   "source": [
    "### Agents And Tools"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fb73a01f-8a2e-4dd6-91f8-710c92b81c56",
   "metadata": {},
   "outputs": [],
   "source": [
    "import json\n",
    "from typing import Sequence, List\n",
    "\n",
    "from llama_index.core.llms import ChatMessage\n",
    "from llama_index.core.tools import BaseTool, FunctionTool\n",
    "from llama_index.core.agent import ReActAgent\n",
    "\n",
    "import nest_asyncio\n",
    "\n",
    "nest_asyncio.apply()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "efbee832-9786-4551-93f2-01ee90fa0f4d",
   "metadata": {},
   "source": [
    "### Define Tools"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b2058b36-8053-4dc8-9218-c286702ecf66",
   "metadata": {},
   "outputs": [],
   "source": [
    "def multiply(a: int, b: int) -> int:\n",
    "    \"\"\"Multiple two integers and returns the result integer\"\"\"\n",
    "    return a * b\n",
    "\n",
    "\n",
    "def add(a: int, b: int) -> int:\n",
    "    \"\"\"Add two integers and returns the result integer\"\"\"\n",
    "    return a + b\n",
    "\n",
    "\n",
    "def subtract(a: int, b: int) -> int:\n",
    "    \"\"\"Subtract two integers and returns the result integer\"\"\"\n",
    "    return a - b\n",
    "\n",
    "\n",
    "def divide(a: int, b: int) -> int:\n",
    "    \"\"\"Divides two integers and returns the result integer\"\"\"\n",
    "    return a / b\n",
    "\n",
    "\n",
    "multiply_tool = FunctionTool.from_defaults(fn=multiply)\n",
    "add_tool = FunctionTool.from_defaults(fn=add)\n",
    "subtract_tool = FunctionTool.from_defaults(fn=subtract)\n",
    "divide_tool = FunctionTool.from_defaults(fn=divide)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "22d7d4dc-e2ce-402c-9350-0e7010d0080c",
   "metadata": {},
   "source": [
    "### ReAct Agent"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "72a48053-e30d-4884-bcac-80752047d940",
   "metadata": {},
   "outputs": [],
   "source": [
    "agent = ReActAgent.from_tools(\n",
    "    [multiply_tool, add_tool, subtract_tool, divide_tool],\n",
    "    llm=llm_replicate,\n",
    "    verbose=True,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7ada828a-3b05-4fc1-90e8-986c5607ae61",
   "metadata": {},
   "source": [
    "### Querying"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9c0b1e56-d9f7-4615-a15a-c91fea1adb00",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[1;3;38;5;200mThought: The current language of the user is: English. I need to use a tool to help me answer the question.\n",
      "Action: add\n",
      "Action Input: {'a': 121, 'b': 2}\n",
      "\u001b[0m\u001b[1;3;34mObservation: 123\n",
      "\u001b[0m\u001b[1;3;38;5;200mThought: I have the result of the addition, now I need to multiply it by 5.\n",
      "Action: multiply\n",
      "Action Input: {'a': 123, 'b': 5}\n",
      "\u001b[0m\u001b[1;3;34mObservation: 615\n",
      "\u001b[0m\u001b[1;3;38;5;200mThought: I can answer without using any more tools. I'll use the user's language to answer\n",
      "Answer: 615\n",
      "\u001b[0m615\n"
     ]
    }
   ],
   "source": [
    "response = agent.chat(\"What is (121 + 2) * 5?\")\n",
    "print(str(response))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "67ce45f6-bdd4-42aa-8f74-43a50f14094e",
   "metadata": {},
   "source": [
    "### ReAct Agent With RAG QueryEngine Tools"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "97fce5f1-eacf-4ecc-9e83-072e74d3a2a9",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core import (\n",
    "    SimpleDirectoryReader,\n",
    "    VectorStoreIndex,\n",
    "    StorageContext,\n",
    "    load_index_from_storage,\n",
    ")\n",
    "\n",
    "from llama_index.core.tools import QueryEngineTool, ToolMetadata"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "23963d00-e3d2-4ce1-9ac3-aa486bf4b1a5",
   "metadata": {},
   "source": [
    "### Create ReAct Agent using RAG QueryEngine Tools"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0e241fe9-f390-4be5-b3c4-da4f56db01ef",
   "metadata": {},
   "outputs": [],
   "source": [
    "drake_tool = QueryEngineTool(\n",
    "    drake_index.as_query_engine(),\n",
    "    metadata=ToolMetadata(\n",
    "        name=\"drake_search\",\n",
    "        description=\"Useful for searching over Drake's life.\",\n",
    "    ),\n",
    ")\n",
    "\n",
    "kendrick_tool = QueryEngineTool(\n",
    "    kendrick_index.as_query_engine(),\n",
    "    metadata=ToolMetadata(\n",
    "        name=\"kendrick_search\",\n",
    "        description=\"Useful for searching over Kendrick's life.\",\n",
    "    ),\n",
    ")\n",
    "\n",
    "query_engine_tools = [drake_tool, kendrick_tool]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b922feac-b221-4737-92c6-e63eeab4eab7",
   "metadata": {},
   "outputs": [],
   "source": [
    "agent = ReActAgent.from_tools(\n",
    "    query_engine_tools,  ## TODO: define query tools\n",
    "    llm=llm_replicate,\n",
    "    verbose=True,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7e38edc8-47f8-4f1a-ad87-bc3a9e31a65e",
   "metadata": {},
   "source": [
    "### Querying"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "035c2c8b-5a5e-4df0-a423-4c2d6054f457",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[1;3;38;5;200mThought: The current language of the user is: English. I need to use a tool to help me answer the question.\n",
      "Action: kendrick_search\n",
      "Action Input: {'input': \"Kendrick Lamar's childhood\"}\n",
      "\u001b[0m\u001b[1;3;34mObservation: Kendrick Lamar was born on June 17, 1987, in Compton, California. He is the first child of Kenneth \"Kenny\" Duckworth, a former gang hustler who previously worked at KFC, and Paula Oliver, a hairdresser who previously worked at McDonald's. Both of his parents are African Americans from the South Side of Chicago, and they relocated to Compton in 1984 due to his father's affiliation with the Gangster Disciples. Lamar was named after singer-songwriter Eddie Kendricks of the Temptations. He was an only child until the age of seven and was described as a loner by his mother.\n",
      "\u001b[0m\u001b[1;3;38;5;200mThought: I have information about Kendrick's childhood, but I need to know more about Drake's upbringing to answer the question.\n",
      "Action: drake_search\n",
      "Action Input: {'input': \"Drake's childhood\"}\n",
      "\u001b[0m\u001b[1;3;34mObservation: Drake was raised in two neighborhoods. He lived on Weston Road in Toronto's working-class west end until grade six and attended Weston Memorial Junior Public School until grade four. He moved to one of the city's affluent neighbourhoods, Forest Hill, in 2000. Drake appeared in a comedic sketch which aired during the 1997 NHL Awards, featuring Martin Brodeur and Ron Hextall. At age 10, he attended Forest Hill Collegiate Institute for high school.\n",
      "\u001b[0m\u001b[1;3;34mObservation: Error: Could not parse output. Please follow the thought-action-input format. Try again.\n",
      "\u001b[0m\u001b[1;3;38;5;200mThought: I apologize for the mistake. I need to use a tool to help me answer the question.\n",
      "Action: drake_search\n",
      "Action Input: {'input': \"Drake's childhood\"}\n",
      "\u001b[0m\u001b[1;3;34mObservation: Drake was raised in two neighborhoods. He lived on Weston Road in Toronto's working-class west end until grade six and attended Weston Memorial Junior Public School until grade four. He played minor hockey with the Weston Red Wings, reaching the Upper Canada College hockey camp before leaving due to a vicious cross-check to his neck during a game. At age 10, Drake appeared in a comedic sketch which aired during the 1997 NHL Awards.\n",
      "\u001b[0m\u001b[1;3;38;5;200mThought: I have information about both Kendrick and Drake's childhood, so I can answer the question without using any more tools.\n",
      "Answer: Kendrick Lamar grew up in Compton, California, as the child of a former gang hustler and a hairdresser, while Drake was raised in two neighborhoods in Toronto, Ontario, Canada, and had a brief experience in minor hockey before pursuing a career in entertainment.\n",
      "\u001b[0mKendrick Lamar grew up in Compton, California, as the child of a former gang hustler and a hairdresser, while Drake was raised in two neighborhoods in Toronto, Ontario, Canada, and had a brief experience in minor hockey before pursuing a career in entertainment.\n"
     ]
    }
   ],
   "source": [
    "response = agent.chat(\"Tell me about how Kendrick and Drake grew up\")\n",
    "print(str(response))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "llama_index_v3",
   "language": "python",
   "name": "llama_index_v3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}