File size: 20,933 Bytes
5d7ba1e
 
 
 
 
 
 
 
 
62f096d
5d7ba1e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "view-in-github"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/towardsai/ai-tutor-rag-system/blob/main/notebooks/06-Evaluate_RAG.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "5BGJ3fxhOk2V"
      },
      "source": [
        "# Install Packages and Setup Variables"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "QPJzr-I9XQ7l",
        "outputId": "9949a0e5-8bf2-4ae7-9921-1f9dfbece9ae"
      },
      "outputs": [],
      "source": [
        "!pip install -q llama-index==0.9.21 openai==1.6.0 cohere==4.39 tiktoken==0.5.2 chromadb==0.4.21 kaleido==0.2.1 python-multipart==0.0.6"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "metadata": {
        "id": "riuXwpSPcvWC"
      },
      "outputs": [],
      "source": [
        "import os\n",
        "\n",
        "# Set the \"OPENAI_API_KEY\" in the Python environment. Will be used by OpenAI client later.\n",
        "os.environ[\"OPENAI_API_KEY\"] = \"YOUR_API_KEY\""
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "I9JbAzFcjkpn"
      },
      "source": [
        "# Load the Dataset (CSV)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "_Tif8-JoRH68"
      },
      "source": [
        "## Download"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "4fQaa1LN1mXL"
      },
      "source": [
        "The dataset includes several articles from the TowardsAI blog, which provide an in-depth explanation of the LLaMA2 model. Read the dataset as a long string."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {
        "id": "-QTUkdfJjY4N"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current\n",
            "                                 Dload  Upload   Total   Spent    Left  Speed\n",
            "100 23689  100 23689    0     0  55248      0 --:--:-- --:--:-- --:--:-- 55219\n"
          ]
        }
      ],
      "source": [
        "!curl -o ../data/mini-dataset.csv https://raw.githubusercontent.com/AlaFalaki/tutorial_notebooks/main/data/mini-dataset.csv"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "zk-4alIxROo8"
      },
      "source": [
        "## Read File"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "7CYwRT6R0o0I",
        "outputId": "6f0f05ae-c92f-45b2-bbc3-d12add118021"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "23632"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "import csv\n",
        "\n",
        "text = \"\"\n",
        "\n",
        "# Load the file as a JSON\n",
        "with open(\"../data/mini-dataset.csv\", mode=\"r\", encoding=\"ISO-8859-1\") as file:\n",
        "    csv_reader = csv.reader(file)\n",
        "\n",
        "    for row in csv_reader:\n",
        "        text += row[0]\n",
        "\n",
        "# The number of characters in the dataset.\n",
        "len(text)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "S17g2RYOjmf2"
      },
      "source": [
        "# Chunking"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "STACTMUR1z9N",
        "outputId": "8ce58d6b-a38d-48e3-8316-7435907488cf"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "47"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "chunk_size = 512\n",
        "chunks = []\n",
        "\n",
        "# Split the long text into smaller manageable chunks of 512 characters.\n",
        "for i in range(0, len(text), chunk_size):\n",
        "    chunks.append(text[i : i + chunk_size])\n",
        "\n",
        "len(chunks)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "metadata": {
        "id": "CtdsIUQ81_hT"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "47\n",
            "Node ID: node_0\n",
            "Text: Meta has once again pushed the boundaries of AI with the release\n",
            "of Llama 2, the highly anticipated successor to its groundbreaking\n",
            "Llama 1 language model. Boasting a range of cutting-edge features,\n",
            "Llama 2 has already disrupted the AI landscape and poses a real\n",
            "challenge to ChatGPTΓ•s dominance. In this article, we will dive into\n",
            "the exciting wo...\n"
          ]
        }
      ],
      "source": [
        "from llama_index.schema import TextNode\n",
        "nodes = [TextNode(text=t,) for i, t in enumerate(chunks)]\n",
        "\n",
        "# By default, the node ids are set to random uuids. To ensure same id's per run, we manually set them.\n",
        "for idx, node in enumerate(nodes):\n",
        "    node.id_ = f\"node_{idx}\"\n",
        "\n",
        "print(len(nodes))\n",
        "print(nodes[0])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "OWaT6rL7ksp8"
      },
      "source": [
        "# Save on Chroma"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "metadata": {
        "id": "mXi56KTXk2sp"
      },
      "outputs": [],
      "source": [
        "import chromadb\n",
        "\n",
        "# create client and a new collection\n",
        "# chromadb.EphemeralClient saves data in-memory.\n",
        "chroma_client = chromadb.PersistentClient(path=\"../data/mini-chunked-dataset\")\n",
        "chroma_collection = chroma_client.create_collection(\"mini-chunked-dataset\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "metadata": {
        "id": "jKXURvLtkuTS"
      },
      "outputs": [],
      "source": [
        "from llama_index.vector_stores import ChromaVectorStore\n",
        "from llama_index.storage.storage_context import StorageContext\n",
        "\n",
        "# Define a storage context object using the created vector database.\n",
        "vector_store = ChromaVectorStore(chroma_collection=chroma_collection)\n",
        "storage_context = StorageContext.from_defaults(vector_store=vector_store)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "metadata": {
        "id": "WsD52wtrlESi"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<llama_index.indices.vector_store.base.VectorStoreIndex at 0x17e862410>"
            ]
          },
          "execution_count": 9,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from llama_index import VectorStoreIndex\n",
        "\n",
        "# Add the documents to the database and create Index / embeddings\n",
        "index = VectorStoreIndex(nodes=nodes, storage_context=storage_context)\n",
        "index"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "8JPD8yAinVSq"
      },
      "source": [
        "# Query Dataset"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "metadata": {
        "id": "mzS13x1ZlZ5X"
      },
      "outputs": [],
      "source": [
        "# Define a query engine that is responsible for retrieving related pieces of text,\n",
        "# and using a LLM to formulate the final answer.\n",
        "query_engine = index.as_query_engine()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "AYsQ4uLN_Oxg",
        "outputId": "bf2181ad-27f6-40a2-b792-8a2714a60c29"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "The Llama-2 model has three different sizes: 7B, 13B, and 70B.\n"
          ]
        }
      ],
      "source": [
        "response = query_engine.query(\"How many parameters LLaMA2 model has?\")\n",
        "print(response)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Evaluate the retrieval process and quality of answers\n",
        "\n",
        "We can evaluate our RAG system with a dataset of questions and associated chunks. Given a question, we can see if the RAG system retrieves the correct chunks of text that can answer the question.\n",
        "\n",
        "You can generate a synthetic dataset with an LLM such as `gpt-3.5-turbo` or create an authentic and manually curated dataset. \n",
        "\n",
        "Note that a **well curated dataset will always be a better option**, especially for a specific domain or use case.\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "In our example, we will generate a synthetic dataset using `gpt-3.5-turbo` to make it simple.\n",
        "\n",
        "This is the default prompt that the `generate_question_context_pairs` uses:\n",
        "\n",
        "```python\n",
        "DEFAULT_QA_GENERATE_PROMPT_TMPL = \"\"\"\\\n",
        "Context information is below.\n",
        "\n",
        "---------------------\n",
        "{context_str}\n",
        "---------------------\n",
        "\n",
        "Given the context information and not prior knowledge.\n",
        "generate only questions based on the below query.\n",
        "\n",
        "You are a Teacher/ Professor. Your task is to setup \\\n",
        "{num_questions_per_chunk} questions for an upcoming \\\n",
        "quiz/examination. The questions should be diverse in nature \\\n",
        "across the document. Restrict the questions to the \\\n",
        "context information provided.\"\n",
        "\"\"\"\n",
        "```\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "metadata": {},
      "outputs": [
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 47/47 [01:55<00:00,  2.45s/it]\n"
          ]
        }
      ],
      "source": [
        "from llama_index.evaluation import generate_question_context_pairs\n",
        "from llama_index.llms import OpenAI\n",
        "\n",
        "llm = OpenAI(model=\"gpt-3.5-turbo\")\n",
        "rag_eval_dataset = generate_question_context_pairs(\n",
        "    nodes,\n",
        "    llm=llm,\n",
        "    num_questions_per_chunk=1\n",
        ")\n",
        "# We can save the dataset as a json file for later use.\n",
        "rag_eval_dataset.save_json(\"../data/rag_eval_dataset.json\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "metadata": {},
      "outputs": [],
      "source": [
        "# We can also load the dataset from a previously saved json file.\n",
        "from llama_index.finetuning.embeddings.common import (\n",
        "    EmbeddingQAFinetuneDataset,\n",
        ")\n",
        "rag_eval_dataset = EmbeddingQAFinetuneDataset.from_json(\n",
        "    \"../data/rag_eval_dataset.json\"\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Evaluation for Hit Rate and Mean Reciprocal Rank (MRR)\n",
        "\n",
        "We will make use of `RetrieverEvaluator` available in Llama-index. We will measure the Hit Rate and Mean Reciprocal Rank (MRR).\n",
        "\n",
        "**Hit Rate:**\n",
        "\n",
        "Think of the Hit Rate like playing a game of guessing. You're given a question and you need to guess the correct answer from a list of options. The Hit Rate measures how often you guess the correct answer by only looking at your top few guesses. If you often find the right answer in your first few guesses, you have a high Hit Rate. So, in the context of a retrieval system, it's about how frequently the system finds the correct document within its top 'k' picks (where 'k' is a number you decide, like top 5 or top 10).\n",
        "\n",
        "**Mean Reciprocal Rank (MRR):**\n",
        "\n",
        "MRR is a bit like measuring how quickly you can find a treasure in a list of boxes. Imagine you have a row of boxes and only one of them has a treasure. The MRR calculates how close to the start of the row the treasure box is, on average. If the treasure is always in the first box you open, you're doing great and have an MRR of 1. If it's in the second box, the score is 1/2, since you took two tries to find it. If it's in the third box, your score is 1/3, and so on. MRR averages these scores across all your searches. So, for a retrieval system, MRR looks at where the correct document ranks in the system's guesses. If it's usually near the top, the MRR will be high, indicating good performance.\n",
        "In summary, Hit Rate tells you how often the system gets it right in its top guesses, and MRR tells you how close to the top the right answer usually is. Both metrics are useful for evaluating the effectiveness of a retrieval system, like how well a search engine or a recommendation system works."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "metadata": {},
      "outputs": [],
      "source": [
        "import pandas as pd\n",
        "\n",
        "def display_results_retriever(name, eval_results):\n",
        "    \"\"\"Display results from evaluate.\"\"\"\n",
        "\n",
        "    metric_dicts = []\n",
        "    for eval_result in eval_results:\n",
        "        metric_dict = eval_result.metric_vals_dict\n",
        "        metric_dicts.append(metric_dict)\n",
        "\n",
        "    full_df = pd.DataFrame(metric_dicts)\n",
        "\n",
        "    hit_rate = full_df[\"hit_rate\"].mean()\n",
        "    mrr = full_df[\"mrr\"].mean()\n",
        "\n",
        "    metric_df = pd.DataFrame(\n",
        "        {\"Retriever Name\": [name], \"Hit Rate\": [hit_rate], \"MRR\": [mrr]}\n",
        "    )\n",
        "\n",
        "    return metric_df"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Then Run the evaluation procedure. We will evaluate the system with different values of top_k and see how the Hit Rate and MRR change."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "    Retriever Name  Hit Rate       MRR\n",
            "0  Retriever top_2  0.666667  0.606607\n",
            "    Retriever Name  Hit Rate       MRR\n",
            "0  Retriever top_4  0.744745  0.630631\n",
            "    Retriever Name  Hit Rate       MRR\n",
            "0  Retriever top_6  0.780781  0.637337\n",
            "    Retriever Name  Hit Rate       MRR\n",
            "0  Retriever top_8  0.804805  0.640651\n",
            "     Retriever Name  Hit Rate       MRR\n",
            "0  Retriever top_10  0.828829  0.643037\n"
          ]
        }
      ],
      "source": [
        "from llama_index.evaluation import RetrieverEvaluator\n",
        "\n",
        "# We can evaluate the retievers with different top_k values.\n",
        "for i in [2, 4, 6, 8, 10]:\n",
        "    retriever = index.as_retriever(similarity_top_k=i)\n",
        "    retriever_evaluator = RetrieverEvaluator.from_metric_names(\n",
        "        [\"mrr\", \"hit_rate\"], retriever=retriever\n",
        "    )\n",
        "    eval_results = await retriever_evaluator.aevaluate_dataset(rag_eval_dataset)\n",
        "    print(display_results_retriever(f\"Retriever top_{i}\", eval_results))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Evaluation using Relevance and Faithfulness metrics.\n",
        "\n",
        "Here, we evaluate the answer generated by the LLM. Is the answer using the correct context? Is the answer faithful to the context? Is the answer relevant to the question?\n",
        "\n",
        "An LLM will answer these questions, more specifically `gpt-4-0125-preview`.\n",
        "\n",
        "**`FaithfulnessEvaluator`**\n",
        "Evaluates if the answer is faithful to the retrieved contexts (in other words, whether there's an hallucination).\n",
        "\n",
        "**`RelevancyEvaluator`**\n",
        "Evaluates whether the retrieved context and answer are relevant to the user question.\n",
        "\n",
        "\n",
        "Now, let's see how the top_k value affects these two metrics."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "top_2 faithfulness_score: 0.9\n",
            "top_2 relevancy_score: 0.9\n",
            "top_4 faithfulness_score: 1.0\n",
            "top_4 relevancy_score: 1.0\n",
            "top_6 faithfulness_score: 1.0\n",
            "top_6 relevancy_score: 1.0\n",
            "top_8 faithfulness_score: 1.0\n",
            "top_8 relevancy_score: 1.0\n",
            "top_10 faithfulness_score: 1.0\n",
            "top_10 relevancy_score: 1.0\n"
          ]
        }
      ],
      "source": [
        "from llama_index.evaluation import RelevancyEvaluator, FaithfulnessEvaluator, BatchEvalRunner\n",
        "from llama_index import ServiceContext\n",
        "from llama_index.llms import OpenAI\n",
        "\n",
        "for i in [2, 4, 6, 8, 10]:\n",
        "    # Set Faithfulness and Relevancy evaluators\n",
        "    query_engine = index.as_query_engine(similarity_top_k=i)\n",
        "\n",
        "    # While we use GPT3.5-Turbo to answer questions, we can use GPT4 to evaluate the answers.\n",
        "    llm_gpt4 = OpenAI(temperature=0, model=\"gpt-4-0125-preview\")\n",
        "    service_context_gpt4 = ServiceContext.from_defaults(llm=llm_gpt4)\n",
        "\n",
        "    faithfulness_evaluator = FaithfulnessEvaluator(service_context=service_context_gpt4)\n",
        "    relevancy_evaluator = RelevancyEvaluator(service_context=service_context_gpt4)\n",
        "\n",
        "    # Run evaluation\n",
        "    queries = list(rag_eval_dataset.queries.values())\n",
        "    batch_eval_queries = queries[:20]\n",
        "\n",
        "    runner = BatchEvalRunner(\n",
        "    {\"faithfulness\": faithfulness_evaluator, \"relevancy\": relevancy_evaluator},\n",
        "    workers=8,\n",
        "    )\n",
        "    eval_results = await runner.aevaluate_queries(\n",
        "        query_engine, queries=batch_eval_queries\n",
        "    )\n",
        "    faithfulness_score = sum(result.passing for result in eval_results['faithfulness']) / len(eval_results['faithfulness'])\n",
        "    print(f\"top_{i} faithfulness_score: {faithfulness_score}\")\n",
        "\n",
        "    relevancy_score = sum(result.passing for result in eval_results['faithfulness']) / len(eval_results['relevancy'])\n",
        "    print(f\"top_{i} relevancy_score: {relevancy_score}\")\n"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "authorship_tag": "ABX9TyNQkVEh0x7hcM9U+6JSEkSG",
      "include_colab_link": true,
      "provenance": []
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.11.7"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}