RCaz commited on
Commit
a25a2ef
·
1 Parent(s): 92766e6

creation of vector_store

Browse files
Files changed (1) hide show
  1. agent/test.ipynb +217 -0
agent/test.ipynb ADDED
@@ -0,0 +1,217 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "id": "0690e575",
7
+ "metadata": {},
8
+ "outputs": [],
9
+ "source": [
10
+ "\n",
11
+ "# load files \n",
12
+ "from langchain_community.document_loaders import FileSystemBlobLoader\n",
13
+ "from langchain_community.document_loaders.generic import GenericLoader\n",
14
+ "from langchain_community.document_loaders.parsers import PyPDFParser\n"
15
+ ]
16
+ },
17
+ {
18
+ "cell_type": "code",
19
+ "execution_count": 11,
20
+ "id": "0793bdad",
21
+ "metadata": {},
22
+ "outputs": [
23
+ {
24
+ "name": "stderr",
25
+ "output_type": "stream",
26
+ "text": [
27
+ "Ignoring wrong pointing object 6 0 (offset 0)\n",
28
+ "Ignoring wrong pointing object 10 0 (offset 0)\n",
29
+ "Ignoring wrong pointing object 12 0 (offset 0)\n",
30
+ "Ignoring wrong pointing object 14 0 (offset 0)\n",
31
+ "Ignoring wrong pointing object 21 0 (offset 0)\n",
32
+ "Ignoring wrong pointing object 27 0 (offset 0)\n",
33
+ "Ignoring wrong pointing object 37 0 (offset 0)\n",
34
+ "Ignoring wrong pointing object 47 0 (offset 0)\n",
35
+ "Ignoring wrong pointing object 53 0 (offset 0)\n",
36
+ "Ignoring wrong pointing object 55 0 (offset 0)\n",
37
+ "Ignoring wrong pointing object 57 0 (offset 0)\n"
38
+ ]
39
+ }
40
+ ],
41
+ "source": [
42
+ "\n",
43
+ "from langchain_community.document_loaders import FileSystemBlobLoader\n",
44
+ "from langchain_community.document_loaders.generic import GenericLoader\n",
45
+ "from langchain_community.document_loaders.parsers import PyPDFParser\n",
46
+ "\n",
47
+ "loader = GenericLoader(\n",
48
+ " blob_loader=FileSystemBlobLoader(\n",
49
+ " path=\"../\",\n",
50
+ " glob=f\"data/**/*.pdf\",\n",
51
+ " ),\n",
52
+ " blob_parser=PyPDFParser(),\n",
53
+ ")\n",
54
+ "\n",
55
+ "docs = loader.load()"
56
+ ]
57
+ },
58
+ {
59
+ "cell_type": "code",
60
+ "execution_count": 36,
61
+ "id": "fbbf5838",
62
+ "metadata": {},
63
+ "outputs": [],
64
+ "source": [
65
+ "from langchain_text_splitters import RecursiveCharacterTextSplitter\n",
66
+ "from transformers import AutoTokenizer\n",
67
+ "\n",
68
+ "\n",
69
+ "chunk_size = 512\n",
70
+ "tokenizer_name = \"intfloat/e5-base-v2\"\n",
71
+ "\n",
72
+ "tokenizer = AutoTokenizer.from_pretrained(tokenizer_name)\n",
73
+ "text_splitter = RecursiveCharacterTextSplitter.from_huggingface_tokenizer(\n",
74
+ " AutoTokenizer.from_pretrained(tokenizer_name),\n",
75
+ " chunk_size=chunk_size,\n",
76
+ " chunk_overlap=int(chunk_size / 10),\n",
77
+ " add_start_index=True,\n",
78
+ " strip_whitespace=True,\n",
79
+ " separators=\".\",\n",
80
+ ")\n",
81
+ "\n",
82
+ "docs_split = text_splitter.split_documents(docs)"
83
+ ]
84
+ },
85
+ {
86
+ "cell_type": "code",
87
+ "execution_count": 38,
88
+ "id": "19f9c7cb",
89
+ "metadata": {},
90
+ "outputs": [
91
+ {
92
+ "data": {
93
+ "text/plain": [
94
+ "Text(0.5, 0.98, 'Distribution of splitted document lengths in the knowledge base')"
95
+ ]
96
+ },
97
+ "execution_count": 38,
98
+ "metadata": {},
99
+ "output_type": "execute_result"
100
+ },
101
+ {
102
+ "data": {
103
+ "image/png": "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iVOkZ8+eTvsrPz/fhISEmL59+zrVKywsNK1atTLXX399sX78s6LzzLXXXuv0hcjevXuNl5eXueeee0p97ZkzZ0xeXp7x9/c3L730klUeGxtrbr311jK3W97jCoDKw63jQA1kyrjdTpKuueYaeXt7695779WcOXOK3WpXXgMGDCh33RYtWqhVq1ZOZUOHDlVubq62bt16QdsvrzVr1qhbt26Kjo52Kh8+fLiOHz9e7Fbifv36Oc23bNlSkordrvdn+fn5+vzzzzVw4EDVrl3bKvfw8NBdd92l/fv3l/v28z+7/vrr9dVXX+n+++/XypUrlZubW2rdYcOGOc0PGjRInp6eWrt2rcvbddVHH32kOnXqqG/fvjpz5ow1XXPNNXI4HNZtl0WxlBbr+axdu1YBAQHF9tHQoUOd5r/77jv99ttvuuuuu1Sr1v+dymrXrq0BAwZo48aNOn78uI4fP6709HQNGjTI+rmEO1xzzTWqV6+eNd+8eXNJf9yG7OfnV6y86L31ww8/6Ntvv7X65899efPNNyszM7PY++hC3q+u+uijjxQbG6trrrnGKaaePXuWeFttly5dFBAQYM1HREQoPDzciik/P1+bN2/WrbfeKm9vb6te7dq11bdvX5fjO18fuOuY92e9e/eWh4dHqdu8UA6HQ9dff71TWcuWLZ3W6+r+KMnJkyd16623at68eVq1alWx/8ki5dmX5T32devWTSdOnNCGDRsk/XH7dY8ePdS9e3elpaVZZZLUvXv3UmP/6KOPZLPZdOeddzq13+FwqFWrVlb7MzIydPLkyWJt69ixo2JiYpzK0tPTFRsbW+w3+UOGDHGa37Bhgw4fPqykpCSnbZ89e1a9evXSpk2bynX7/tChQ51+IhETE6OOHTs6Ha/z8vL06KOP6oorrpCnp6c8PT1Vu3Zt5efn65tvvrHqXX/99fr444/12GOPad26dTpx4oTTti7kuAKg4pFoAzVMfn6+Dh06pKioqFLrNGnSRKtXr1Z4eLhGjRqlJk2aqEmTJk6/+y2PyMjIctd1OByllh06dMil7brq0KFDJcZa1Efnbj80NNRp3m63S1KxDy9/duTIERljXNpOeUyYMEH/+te/tHHjRiUmJio0NFTdunUr8Xe95/axp6enQkNDK7x/JenAgQM6evSovL295eXl5TRlZWXp999/l/R/fVBarOdz6NAha5C/Pzt3fUXbKW1/nD17VkeOHNGRI0dUWFjo9gH8QkJCnOaLksnSyk+ePCnpj36UpPHjxxfrx/vvv1+SrL4sciHvV1cdOHBAX3/9dbGYAgICZIw5b0xFcRXFVPT/UtK+LKnsfM7XB+465rmyTXett2jdf16vq/ujJNnZ2Vq5cqU6dOigjh07XnA8rhz7OnbsKD8/P61evVo//PCD9u7dayXan3/+ufLy8rR69Wo1btxYjRo1KjWmAwcOWO+fc/tg48aN5z3elFRW2rHl3LKi/9GBAwcW2/Zzzz0nY4wOHz5cauylbb+o7M/H66FDh+rll1/WPffco5UrV+qLL77Qpk2bVLduXaf3w7///W89+uijWrJkibp06aKQkBDdeuut2r17t1PMrhxXAFQ8Rh0Haphly5apsLDwvM8HvfHGG3XjjTeqsLBQmzdv1vTp0zVmzBhFRETojjvuKNe2XHk2d0mDVRWVFX2Q8/HxkSRrAKoiF/sBIDQ0VJmZmcXKiwZLCgsLu6j1S1JwcLBq1arl9u14enpq7NixGjt2rI4eParVq1fr8ccfV8+ePbVv3z6nq6NZWVlOV1HPnDmjQ4cOlSuBvVhFg1CtWLGixOVFV8SKYikt1vMJDQ0tceC0c99fRdspbX/UqlVLwcHBstls8vDw0P79+8vc7p/fm0UJleT+D6dF75EJEyaof//+Jda58sor3brN8ggLC5Ovr6/efvvtUpe7oqjvixKAPyttYLuL5Y5jXnXhjv3RoEEDTZ06Vbfddpv69++v9957z3qfu8KVY5+3t7duuOEGrV69WvXr15fD4VBcXJwaN24s6Y8BKT/55BP16dOnzG2GhYXJZrPps88+c/p/LFJU9ufjzbmysrKcBgUMDQ0t1/uxqC3Tp08v9YkN5fmyqLSYimLOycnRRx99pIkTJ+qxxx6z6hQUFBRL5P39/TVp0iRNmjRJBw4csK5u9+3bV99++221Pa4AlzuuaAM1yC+//KLx48crKChI9913X7le4+HhoXbt2umVV16RJOs2bndfFdu5c6e++uorp7L58+crICBA1157rSRZH3q+/vprp3pLly4ttr5zr/CUpVu3blqzZk2xUYjfeecd+fn5ueXxVv7+/mrXrp0WLVrkFNfZs2c1d+5c1a9fX82aNbuobdSpU0cDBw7UqFGjdPjw4WKjs8+bN89p/j//+Y/OnDlz3i9dzlXWvi+t3/v06aNDhw6psLBQbdu2LTYVfYgriqW0WM+nS5cuOnbsWLH3xPz5853mr7zyStWrV0/z5893+ilFfn6+3n//fWsk8qLRft97770yk+bS3psffvjheWN2xZVXXqmmTZvqq6++KrEf27Zt63Qbb3m58v9Skj59+ujHH39UaGhoiTG5Ooq5v7+/2rZtqyVLlujUqVNWeV5eXokjWl9s/H9W2jGvsrjj2Oqu/ZGQkKCVK1fq008/VZ8+fS5oxHJXj33du3fXli1b9P7771u3h/v7+6t9+/aaPn26fvvttzJvGy9qvzFGv/76a4ntj4uLk/THowt9fHyKHW82bNhQ7Bb/zp07a8eOHdq1a5dTeWpqqtN8p06dVKdOHe3atavU/9E//xyiNAsWLHA6Nv3888/asGGDdYy02WwyxhT7IuGtt95SYWFhqeuNiIjQ8OHDNWTIEH333Xc6fvx4hR1XAFwcrmgD1dSOHTus31hlZ2frs88+06xZs+Th4aHFixeX+XvT1157TWvWrFHv3r3VoEEDnTx50royUvQBJyAgQDExMfrggw/UrVs3hYSEKCws7IIeCyT9cQthv379lJycrMjISM2dO1dpaWl67rnnrKuy1113na688kqNHz9eZ86cUXBwsBYvXqz169cXW19cXJwWLVqkGTNmqE2bNqpVq5bTc8X/bOLEifroo4/UpUsX/fOf/1RISIjmzZunZcuWacqUKQoKCrqgNp0rJSVFPXr0UJcuXTR+/Hh5e3vr1Vdf1Y4dO7RgwQKX7gAo0rdvX+uZ6XXr1tXPP/+sadOmKSYmRk2bNnWqu2jRInl6eqpHjx7auXOn/vGPf6hVq1YaNGiQS9uMjY2VJL3xxhsKCAiQj4+PGjVqpNDQ0FL7/Y477tC8efN0880368EHH9T1118vLy8v7d+/X2vXrtUtt9yi2267Tc2bN9edd96padOmycvLS927d9eOHTv0r3/9S4GBgeeN7e6779aLL76ou+++W88884yaNm2q5cuXa+XKlU71atWqpSlTpmjYsGHq06eP7rvvPhUUFOj555/X0aNH9eyzz1p1p06dqhtuuEHt2rXTY489piuuuEIHDhzQ0qVL9frrrysgIEA333yzQkJCNGLECD311FPy9PTU7NmztW/fPpf6tjxef/11JSYmqmfPnho+fLjq1aunw4cP65tvvtHWrVv13nvvubzOuLg4paamauHChWrcuLF8fHysZKQ8xowZo/fff1833XSTHnroIbVs2VJnz57VL7/8olWrVmncuHFq166dSzE99dRT6t27t3r27KkHH3xQhYWFev7551W7du1iV+zi4uK0bt06ffjhh4qMjFRAQIBLV+DKc8yrLGX9f5WXO/fHDTfcoE8++US9evVSQkKCli9f7vIx0ZVjX7du3VRYWKhPPvnE6RGL3bt318SJE2Wz2dS1a9cyt9epUyfde++9+p//+R9t3rxZN910k/z9/ZWZman169crLi5Of/vb3xQcHKzx48fr6aef1j333KPbb79d+/btU3JycrFbt8eMGaO3335biYmJeuqppxQREaH58+fr22+/lSRrrIfatWtr+vTpSkpK0uHDhzVw4ECFh4fr4MGD+uqrr3Tw4EHNmDHjvH2WnZ2t2267TSNHjlROTo4mTpwoHx8fTZgwQZIUGBiom266Sc8//7x17k1PT9fMmTNVp04dp3W1a9dOffr0UcuWLRUcHKxvvvlG7777rvWFolQxxxUAF6lqxmADUJqiUXaLJm9vbxMeHm46d+5sJk+eXOLIyeeOmJyRkWFuu+02ExMTY+x2uwkNDTWdO3d2GvnYGGNWr15tWrdubex2u9OI0EXr+/PjRUrbljF/jGDcu3dv89///te0aNHCeHt7m4YNG5qpU6cWe/33339vEhISTGBgoKlbt64ZPXq0WbZsWbFReg8fPmwGDhxo6tSpY2w2m9M2VcJo6du3bzd9+/Y1QUFBxtvb27Rq1arYI02KRoN97733nMqLRhkuzyNQPvvsM9O1a1fj7+9vfH19Tfv27c2HH35Y4vrKM+r4Cy+8YDp27GjCwsKMt7e3adCggRkxYoTZu3evVaeoz7ds2WL69u1rateubQICAsyQIUPMgQMHnNZXnlHHjTFm2rRpplGjRsbDw8Op7WX1++nTp82//vUv06pVK+Pj42Nq165trrrqKnPfffeZ3bt3W/UKCgrMuHHjTHh4uPHx8THt27c3GRkZxUa6Ls3+/fvNgAEDrHYOGDDAbNiwocR9tGTJEtOuXTvj4+Nj/P39Tbdu3ZweI1Rk165d5vbbbzehoaFWPw8fPtwaHdmYP0aV7tixo/H39zf16tUzEydONG+99VaJo4737t272DYkmVGjRjmVlfZe+Oqrr8ygQYNMeHi48fLyMg6Hw3Tt2tW89tprVp3SnkBQ0ij9e/fuNQkJCSYgIMB6FFxZStoXeXl55sknnzRXXnml8fb2NkFBQSYuLs489NBDTo9TKqmdpa1z8eLFJi4uzurzZ5991vz97383wcHBTvW2bdtmOnXqZPz8/JxGiy5vH5T3mFeS0kYdL+n/t6T/pZKU9v917mO3ipT0eKvy7o/S2nTudnbs2GEcDoe59tprrWO7K/uyPMc+Y4w5e/asCQsLM5LMr7/+apUXjQR+7bXXlqv9xhjz9ttvm3bt2lnbbNKkibn77rvN5s2bnbaXkpJioqOjjbe3t2nZsqX58MMPSzwW7tixw3Tv3t34+PiYkJAQM2LECDNnzhwjyXz11VdOddPT003v3r1NSEiI8fLyMvXq1TO9e/cudv44V9F789133zV///vfTd26dY3dbjc33nijU9zG/N+xLjg42AQEBJhevXqZHTt2FOv/xx57zLRt29YEBwcbu91uGjdubB566CHz+++/O62vPMcVAJXHZsx5hi8GAFSp5ORkTZo0SQcPHnTL782BqnL69GlrxPZVq1ZVdTiA7r33Xi1YsECHDh0q1y3hAFBe3DoOAAAqxIgRI9SjRw9FRkYqKytLr732mr755puLGg0cuFBPPfWUoqKi1LhxY2u8gLfeektPPvkkSTYAtyPRBgAAFeLYsWMaP368Dh48KC8vL1177bVavnx5pf9uGpAkLy8vPf/889q/f7/OnDmjpk2baurUqXrwwQerOjQAlyBuHQcAAAAAwI14vBcAAAAAAG5Eog0AAAAAgBuRaAMAAAAA4EYk2gAAAAAAuBGJNi5ps2fPls1m0969e6s6lEozf/58TZs2rULW/eSTT6pBgwby9PRUnTp1Sq23fPlyJScnX9S2GjZsqD59+lzUOgAA1R/navcq77m6PJKTk2Wz2fT777+7J7hKtGHDBiUnJ+vo0aNVHQouUyTauKT17t1bGRkZioyMrOpQKk1Fnbw/+OADPfPMM7r77ruVnp6u1atXl1p3+fLlmjRpkttjAABcejhXu48r5+pL3YYNGzRp0iQSbVQZnqONS1rdunVVt27dqg7jkrBjxw5J0t///neFh4dXcTQAgEsF52r3qann6uPHj8vPz6+qwyiXmhQrqhZXtHFJK+l2tPj4eMXGxmrTpk268cYb5efnp8aNG+vZZ5/V2bNnz7vOs2fPavr06brmmmvk6+urOnXqqH379lq6dKlTnSlTpuiqq66S3W5XeHi47r77bu3fv99pXQ0bNtTw4cOLbSM+Pl7x8fHW/Lp162Sz2bRgwQI98cQTioqKUmBgoLp3767vvvvO6XXLli3Tzz//LJvNZk3na8/5Ym3YsKGefPJJSVJERIRsNlupt4YPHz5cr7zyiiQ5xVC0D06ePKkJEyaoUaNG8vb2Vr169TRq1KhyfeP86quvytPTUxMnTrTKVq9erW7duikwMFB+fn7q1KmTPvnkE6fXFd36tnPnTg0ZMkRBQUGKiIjQX/7yF+Xk5DjVfe+999SuXTsFBQVZ742//OUv540NAHBhOFdX/rm6yOeff66+ffsqNDRUPj4+atKkicaMGVOs3oEDB857/nzllVd00003KTw8XP7+/oqLi9OUKVN0+vTpYv0WGxurTz/9VB07dpSfn591nl24cKESEhIUGRkpX19fNW/eXI899pjy8/Ndij05OVkPP/ywJKlRo0ZWH69bt856/cKFC9WhQwf5+/urdu3a6tmzp7788kunbQwfPly1a9fW9u3blZCQoICAAHXr1k2S9OWXX6pPnz4KDw+X3W5XVFSUevfuXez9g8sXV7RxWcrKytKwYcM0btw4TZw4UYsXL9aECRMUFRWlu+++u8zXDh8+XHPnztWIESP01FNPydvbW1u3bnX6gPC3v/1Nb7zxhh544AH16dNHe/fu1T/+8Q+tW7dOW7duVVhY2AXF/fjjj6tTp0566623lJubq0cffVR9+/bVN998Iw8PD7366qu699579eOPP2rx4sXlWmd5Yl28eLFeeeUVzZw5UytWrFBQUJDq169f4vr+8Y9/KD8/X//973+VkZFhlUdGRsoYo1tvvVWffPKJJkyYoBtvvFFff/21Jk6cqIyMDGVkZMhutxdbpzFGDz/8sP7973/rrbfesj7wzJ07V3fffbduueUWzZkzR15eXnr99dfVs2dPrVy50joZFhkwYIAGDx6sESNGaPv27ZowYYIk6e2335YkZWRkaPDgwRo8eLCSk5Pl4+Ojn3/+WWvWrClXXwIA3Idz9f9x97laklauXKm+ffuqefPmmjp1qho0aKC9e/dq1apVxeqe7/wpST/++KOGDh1qfZH+1Vdf6ZlnntG3337rVE+S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voqPj9fOnTud1lFQUKDRo0crLCxM/v7+6tevn/bv31/ZTXHy6aefqm/fvoqKipLNZtOSJUuclrurXUeOHNFdd92loKAgBQUF6a677tLRo0cruHV/OF8bhw8fXmzftm/f3qlOdW9jSkqKrrvuOgUEBCg8PFy33nqrvvvuO6c6NX1flqeNNX1fzpgxQy1btlRgYKACAwPVoUMHffzxx9bymr4Pi5yvnTV9P6LmnusrwuVwfK4KKSkpstlsGjNmjFVGP5bPr7/+qjvvvFOhoaHy8/PTNddcoy1btljL6cfzO3PmjJ588kk1atRIvr6+aty4sZ566imdPXvWqkM/VgFzGUtNTTVeXl7mzTffNLt27TIPPvig8ff3Nz///HNVh3ZeEydONC1atDCZmZnWlJ2dbS1/9tlnTUBAgHn//ffN9u3bzeDBg01kZKTJzc216vz1r3819erVM2lpaWbr1q2mS5cuplWrVubMmTNV0SRjjDHLly83TzzxhHn//feNJLN48WKn5e5qV69evUxsbKzZsGGD2bBhg4mNjTV9+vSpFm1MSkoyvXr1ctq3hw4dcqpT3dvYs2dPM2vWLLNjxw6zbds207t3b9OgQQOTl5dn1anp+7I8bazp+3Lp0qVm2bJl5rvvvjPfffedefzxx42Xl5fZsWOHMabm78PytrOm78fLXU0+11eEy+H4XNm++OIL07BhQ9OyZUvz4IMPWuX04/kdPnzYxMTEmOHDh5vPP//c7Nmzx6xevdr88MMPVh368fyefvppExoaaj766COzZ88e895775natWubadOmWXXox8p3WSfa119/vfnrX//qVHbVVVeZxx57rIoiKr+JEyeaVq1albjs7NmzxuFwmGeffdYqO3nypAkKCjKvvfaaMcaYo0ePGi8vL5OammrV+fXXX02tWrXMihUrKjT28jo3CXVXu3bt2mUkmY0bN1p1MjIyjCTz7bffVnCrnJWWaN9yyy2lvqamtdEYY7Kzs40kk56eboy5NPfluW005tLcl8HBweatt966JPfhnxW105hLcz9eTmryub4yXA7H54p07Ngx07RpU5OWlmY6d+5sJdr0Y/k8+uij5oYbbih1Of1YPr179zZ/+ctfnMr69+9v7rzzTmMM/VhVLttbx0+dOqUtW7YoISHBqTwhIUEbNmyooqhcs3v3bkVFRalRo0a64447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",
104
+ "text/plain": [
105
+ "<Figure size 1200x400 with 2 Axes>"
106
+ ]
107
+ },
108
+ "metadata": {},
109
+ "output_type": "display_data"
110
+ }
111
+ ],
112
+ "source": [
113
+ "import matplotlib.pyplot as plt\n",
114
+ "\n",
115
+ "\n",
116
+ "fig, axs = plt.subplots(1,2, figsize=(12,4))\n",
117
+ "\n",
118
+ "\n",
119
+ "n_tokens = [len(tokenizer.encode(a.page_content)) for a in docs]\n",
120
+ "n_tokens_split = [len(tokenizer.encode(a.page_content)) for a in docs_split]\n",
121
+ "axs[0].hist(n_tokens)\n",
122
+ "axs[0].hist(n_tokens_split)\n",
123
+ "\n",
124
+ "axs[0].set_title(\"in count of tokens\")\n",
125
+ "\n",
126
+ "n_caract = [len(a.page_content) for a in docs]\n",
127
+ "n_caract_split = [len(a.page_content) for a in docs_split]\n",
128
+ "\n",
129
+ "axs[1].hist(n_caract)\n",
130
+ "axs[1].hist(n_caract_split)\n",
131
+ "axs[1].set_title(\"in count of characters\")\n",
132
+ "\n",
133
+ "plt.suptitle(\"Distribution of splitted document lengths in the knowledge base\")\n"
134
+ ]
135
+ },
136
+ {
137
+ "cell_type": "code",
138
+ "execution_count": 39,
139
+ "id": "aba59d80",
140
+ "metadata": {},
141
+ "outputs": [
142
+ {
143
+ "name": "stderr",
144
+ "output_type": "stream",
145
+ "text": [
146
+ "/var/folders/dv/gzhyqctn53s9bh23g7tbvl940000gn/T/ipykernel_29697/3187483442.py:4: LangChainDeprecationWarning: The class `HuggingFaceEmbeddings` was deprecated in LangChain 0.2.2 and will be removed in 1.0. An updated version of the class exists in the `langchain-huggingface package and should be used instead. To use it run `pip install -U `langchain-huggingface` and import as `from `langchain_huggingface import HuggingFaceEmbeddings``.\n",
147
+ " embedding_model = HuggingFaceEmbeddings(\n"
148
+ ]
149
+ }
150
+ ],
151
+ "source": [
152
+ "from langchain_community.embeddings import HuggingFaceEmbeddings # deprecated\n",
153
+ "# from langchain_huggingface import HuggingFaceEmbeddings\n",
154
+ "\n",
155
+ "embedding_model = HuggingFaceEmbeddings(\n",
156
+ " model_name=tokenizer_name,\n",
157
+ " # multi_process=True,\n",
158
+ " model_kwargs={\"device\": \"mps\"}, # use cuda for faster embeddings on nbidia GPUs\n",
159
+ " encode_kwargs={\"normalize_embeddings\": True}, # Set `True` for cosine similarity\n",
160
+ ")"
161
+ ]
162
+ },
163
+ {
164
+ "cell_type": "code",
165
+ "execution_count": null,
166
+ "id": "da07d2c2",
167
+ "metadata": {},
168
+ "outputs": [
169
+ {
170
+ "ename": "AttributeError",
171
+ "evalue": "'builtin_function_or_method' object has no attribute 'date'",
172
+ "output_type": "error",
173
+ "traceback": [
174
+ "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
175
+ "\u001b[31mAttributeError\u001b[39m Traceback (most recent call last)",
176
+ "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[44]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[43mdatetime\u001b[49m\u001b[43m.\u001b[49m\u001b[43mnow\u001b[49m\u001b[43m.\u001b[49m\u001b[43mdate\u001b[49m\n\u001b[32m 2\u001b[39m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mlangchain_community\u001b[39;00m\u001b[34;01m.\u001b[39;00m\u001b[34;01mvectorstores\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m FAISS\n\u001b[32m 3\u001b[39m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mlangchain_community\u001b[39;00m\u001b[34;01m.\u001b[39;00m\u001b[34;01mvectorstores\u001b[39;00m\u001b[34;01m.\u001b[39;00m\u001b[34;01mutils\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m DistanceStrategy\n",
177
+ "\u001b[31mAttributeError\u001b[39m: 'builtin_function_or_method' object has no attribute 'date'"
178
+ ]
179
+ }
180
+ ],
181
+ "source": [
182
+ "from langchain_community.vectorstores import FAISS\n",
183
+ "from langchain_community.vectorstores.utils import DistanceStrategy\n",
184
+ "\n",
185
+ "KNOWLEDGE_VECTOR_DATABASE = FAISS.from_documents(\n",
186
+ " docs_split, embedding_model, distance_strategy=DistanceStrategy.COSINE\n",
187
+ ")\n",
188
+ "\n",
189
+ "# Save the vector database\n",
190
+ "from datetime import datetime \n",
191
+ "vector_info = str(chunk_size) + \"-\" + tokenizer_name.replace(\"/\",\"-\") + \"-\" + datetime.now().date().isoformat()\n",
192
+ "KNOWLEDGE_VECTOR_DATABASE.save_local(\"../data/FAISS/{vector_info}\")\n"
193
+ ]
194
+ }
195
+ ],
196
+ "metadata": {
197
+ "kernelspec": {
198
+ "display_name": "genai",
199
+ "language": "python",
200
+ "name": "python3"
201
+ },
202
+ "language_info": {
203
+ "codemirror_mode": {
204
+ "name": "ipython",
205
+ "version": 3
206
+ },
207
+ "file_extension": ".py",
208
+ "mimetype": "text/x-python",
209
+ "name": "python",
210
+ "nbconvert_exporter": "python",
211
+ "pygments_lexer": "ipython3",
212
+ "version": "3.11.14"
213
+ }
214
+ },
215
+ "nbformat": 4,
216
+ "nbformat_minor": 5
217
+ }