danielsuarez-mash commited on
Commit
182af43
1 Parent(s): 00663a7

adding all files

Browse files
.DS_Store ADDED
Binary file (6.15 kB). View file
 
README 2.md ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ # Langchain series
2
+
3
+ This project was aimed at learning more about large language models and how to use them via langchain. It contains:
4
+
5
+ - a notebook which works through langchain's basic functionality
6
+ - a streamlit application which allows a user to query a self-uploaded document
7
+
8
+ ## Running instructions
9
+ To run the notebook or the application, install the python environment using the environment.yaml file included in this repo. You will also need to have a HuggingFace API token saved in a .bash_profile file in your home directory. To run the application, run streamlit dashboard/app.py from the repo location.
dashboard/app.py ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from dotenv import load_dotenv
3
+ import os
4
+ from PyPDF2 import PdfReader
5
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
6
+ from langchain_community.embeddings import HuggingFaceInstructEmbeddings
7
+ from langchain_community.vectorstores import FAISS
8
+ from langchain.prompts import PromptTemplate
9
+ from langchain_community.llms import HuggingFaceHub
10
+ from langchain_core.runnables import RunnablePassthrough
11
+ from langchain_core.runnables import RunnableSequence
12
+ from langchain_core.output_parsers import StrOutputParser
13
+
14
+ st.title('LLM - Retrieval Augmented Generation')
15
+
16
+ pdf = st.file_uploader(label='Upload PDF')
17
+
18
+ question = st.text_input(label='Question')
19
+
20
+ def authenticate():
21
+
22
+ # if running on cloud
23
+ try:
24
+ os.environ('HUGGINGFACEHUB_API_TOKEN')
25
+ except:
26
+ load_dotenv()
27
+ os.environ.get('HUGGINGFACEHUB_API_TOKEN')
28
+
29
+ def load_pdf(pdf):
30
+
31
+ reader = PdfReader(pdf)
32
+
33
+ page_limit = st.number_input(label='Page limit', value=len(reader.pages), step=1)
34
+
35
+ if page_limit is None:
36
+ page_limit=len(reader.pages)
37
+
38
+
39
+
40
+ text = ""
41
+
42
+ for i in range(page_limit):
43
+
44
+ page_text = reader.pages[i].extract_text()
45
+
46
+ text += page_text
47
+
48
+ return text
49
+
50
+ def split_text(text):
51
+
52
+ # split
53
+ text_splitter = RecursiveCharacterTextSplitter(
54
+ chunk_size=400,
55
+ chunk_overlap=20,
56
+ separators=["\n\n", "\n", " ", ""]
57
+ )
58
+
59
+ # use text_splitter to split text
60
+ chunks = text_splitter.split_text(text)
61
+
62
+ return chunks
63
+
64
+ def store_text(chunks):
65
+
66
+ # select model to create embeddings
67
+ embeddings = HuggingFaceInstructEmbeddings(model_name='hkunlp/instructor-large')
68
+
69
+ # select vectorstore, define text chunks and embeddings model
70
+ vectorstore = FAISS.from_texts(texts=chunks, embedding=embeddings)
71
+
72
+ return vectorstore
73
+
74
+ def load_split_store(pdf):
75
+
76
+ # load split store
77
+ text = load_pdf(pdf=pdf)
78
+ chunks = split_text(text)
79
+ vectorstore = store_text(chunks)
80
+
81
+ return vectorstore
82
+
83
+ def format_docs(docs):
84
+ return "\n\n".join(doc.page_content for doc in docs)
85
+
86
+ def main():
87
+
88
+ # authenticate
89
+ authenticate()
90
+
91
+ # define new template for RAG
92
+ rag_template = """
93
+ You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise.
94
+ Question: {question}
95
+ Context: {context}
96
+ Answer:
97
+ """
98
+
99
+ # instantiate llm
100
+ llm = HuggingFaceHub(
101
+ repo_id='tiiuae/falcon-7b-instruct',
102
+ model_kwargs={
103
+ # 'temperature':1,
104
+ # 'penalty_alpha':2,
105
+ # 'top_k':50,
106
+ # # 'max_length': 1000
107
+ }
108
+ )
109
+
110
+ # build prompt
111
+ prompt = PromptTemplate(
112
+ template=rag_template,
113
+ llm=llm,
114
+ input_variables=['question', 'context']
115
+ )
116
+
117
+
118
+ # if a PDF exists
119
+ if pdf is not None:
120
+
121
+ # load split store
122
+ vectorstore = load_split_store(pdf)
123
+
124
+ # create a retriever using vectorstore
125
+ retriever = vectorstore.as_retriever()
126
+
127
+ # create retrieval chain
128
+ retrieval_chain = (
129
+ retriever | format_docs
130
+ )
131
+
132
+ # create generation chain
133
+ generation_chain = (
134
+ {"context": retriever | format_docs, "question": RunnablePassthrough()}
135
+ | prompt
136
+ | llm
137
+ | StrOutputParser()
138
+ )
139
+
140
+ # button press
141
+ if st.button(label='Process'):
142
+ with st.spinner('Processing'):
143
+
144
+ # context
145
+ st.write('# Context')
146
+ st.write(retrieval_chain.invoke(question))
147
+
148
+ # answer
149
+ st.write('# Answer')
150
+ st.write(generation_chain.invoke(question))
151
+
152
+ if __name__=='__main__':
153
+ main()
154
+
155
+
environment_all.yml ADDED
@@ -0,0 +1,333 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: llm
2
+ channels:
3
+ # - bioconda
4
+ - conda-forge
5
+ - defaults
6
+ dependencies:
7
+ - aiohttp=3.8.5=py311h80987f9_0
8
+ - aiosignal=1.3.1=pyhd8ed1ab_0
9
+ - altair=5.2.0=pyhd8ed1ab_0
10
+ - annotated-types=0.6.0=pyhd8ed1ab_0
11
+ - anyio=3.7.1=pyhd8ed1ab_0
12
+ - appdirs=1.4.4=pyh9f0ad1d_0
13
+ - appnope=0.1.3=pyhd8ed1ab_0
14
+ - argon2-cffi=23.1.0=pyhd8ed1ab_0
15
+ - argon2-cffi-bindings=21.2.0=py311heffc1b2_4
16
+ - arrow=1.3.0=pyhd8ed1ab_0
17
+ - asttokens=2.4.1=pyhd8ed1ab_0
18
+ - async-lru=2.0.4=pyhd8ed1ab_0
19
+ - async-timeout=4.0.3=pyhd8ed1ab_0
20
+ - attrs=23.1.0=pyh71513ae_1
21
+ - aws-c-auth=0.7.8=h76f1ccf_2
22
+ - aws-c-cal=0.6.9=hb1772db_2
23
+ - aws-c-common=0.9.10=h93a5062_0
24
+ - aws-c-compression=0.2.17=hb1772db_7
25
+ - aws-c-event-stream=0.3.2=hb5e90b3_8
26
+ - aws-c-http=0.7.14=hd747585_3
27
+ - aws-c-io=0.13.36=h1112932_2
28
+ - aws-c-mqtt=0.10.0=h99ceed4_0
29
+ - aws-c-s3=0.4.5=hc25d294_0
30
+ - aws-c-sdkutils=0.1.13=hb1772db_0
31
+ - aws-checksums=0.1.17=hb1772db_6
32
+ - aws-crt-cpp=0.25.0=h0f7dc99_2
33
+ - aws-sdk-cpp=1.11.210=h87406ae_5
34
+ - babel=2.13.1=pyhd8ed1ab_0
35
+ - backports=1.0=pyhd8ed1ab_3
36
+ - backports.functools_lru_cache=1.6.5=pyhd8ed1ab_0
37
+ - beautifulsoup4=4.12.2=pyha770c72_0
38
+ - bleach=6.1.0=pyhd8ed1ab_0
39
+ - blinker=1.7.0=pyhd8ed1ab_0
40
+ - brotli=1.1.0=hb547adb_1
41
+ - brotli-bin=1.1.0=hb547adb_1
42
+ - brotli-python=1.1.0=py311ha891d26_1
43
+ - bzip2=1.0.8=h93a5062_5
44
+ - c-ares=1.24.0=h93a5062_0
45
+ - ca-certificates=2023.11.17=hf0a4a13_0
46
+ - cached-property=1.5.2=hd8ed1ab_1
47
+ - cached_property=1.5.2=pyha770c72_1
48
+ - cachetools=5.3.2=pyhd8ed1ab_0
49
+ - certifi=2023.11.17=pyhd8ed1ab_0
50
+ - cffi=1.16.0=py311h4a08483_0
51
+ - charset-normalizer=3.3.2=pyhd8ed1ab_0
52
+ - click=8.1.7=unix_pyh707e725_0
53
+ - colorama=0.4.6=pyhd8ed1ab_0
54
+ - comm=0.1.4=pyhd8ed1ab_0
55
+ - contourpy=1.2.0=py311hd03642b_0
56
+ - cryptography=41.0.5=py311h71175c2_0
57
+ - cycler=0.12.1=pyhd8ed1ab_0
58
+ - dataclasses-json=0.5.7=pyhd8ed1ab_0
59
+ - debugpy=1.8.0=py311ha891d26_1
60
+ - decorator=5.1.1=pyhd8ed1ab_0
61
+ - defusedxml=0.7.1=pyhd8ed1ab_0
62
+ - docker-pycreds=0.4.0=py_0
63
+ - entrypoints=0.4=pyhd8ed1ab_0
64
+ - et_xmlfile=1.1.0=pyhd8ed1ab_0
65
+ - exceptiongroup=1.1.3=pyhd8ed1ab_0
66
+ - executing=2.0.1=pyhd8ed1ab_0
67
+ - filelock=3.13.1=pyhd8ed1ab_0
68
+ - fonttools=4.44.0=py311h05b510d_0
69
+ - fqdn=1.5.1=pyhd8ed1ab_0
70
+ - freetype=2.12.1=hadb7bae_2
71
+ - frozenlist=1.4.0=py311heffc1b2_1
72
+ - fsspec=2023.10.0=pyhca7485f_0
73
+ - gflags=2.2.2=hc88da5d_1004
74
+ - gitdb=4.0.11=pyhd8ed1ab_0
75
+ - gitpython=3.1.40=pyhd8ed1ab_0
76
+ - glog=0.6.0=h6da1cb0_0
77
+ - gmp=6.3.0=h965bd2d_0
78
+ - gmpy2=2.1.2=py311h2ba9262_1
79
+ - google-api-core=2.13.0=pyhd8ed1ab_0
80
+ - google-auth=2.23.4=pyhca7485f_0
81
+ - googleapis-common-protos=1.61.0=pyhd8ed1ab_0
82
+ - greenlet=3.0.1=py311hbaf5611_0
83
+ - icu=73.2=hc8870d7_0
84
+ - idna=3.4=pyhd8ed1ab_0
85
+ - importlib-metadata=6.8.0=pyha770c72_0
86
+ - importlib_metadata=6.8.0=hd8ed1ab_0
87
+ - importlib_resources=6.1.1=pyhd8ed1ab_0
88
+ - iniconfig=2.0.0=pyhd8ed1ab_0
89
+ - ipykernel=6.26.0=pyh3cd1d5f_0
90
+ - ipython=8.17.2=pyh31c8845_0
91
+ - ipywidgets=8.1.1=pyhd8ed1ab_0
92
+ - isoduration=20.11.0=pyhd8ed1ab_0
93
+ - jedi=0.19.1=pyhd8ed1ab_0
94
+ - jinja2=3.1.2=pyhd8ed1ab_1
95
+ - joblib=1.3.2=pyhd8ed1ab_0
96
+ - json5=0.9.14=pyhd8ed1ab_0
97
+ - jsonpatch=1.33=pyhd8ed1ab_0
98
+ - jsonpointer=2.4=py311h267d04e_3
99
+ - jsonschema=4.19.2=pyhd8ed1ab_0
100
+ - jsonschema-specifications=2023.7.1=pyhd8ed1ab_0
101
+ - jsonschema-with-format-nongpl=4.19.2=pyhd8ed1ab_0
102
+ - jupyter=1.0.0=pyhd8ed1ab_10
103
+ - jupyter-lsp=2.2.0=pyhd8ed1ab_0
104
+ - jupyter_client=8.6.0=pyhd8ed1ab_0
105
+ - jupyter_console=6.6.3=pyhd8ed1ab_0
106
+ - jupyter_core=5.5.0=py311h267d04e_0
107
+ - jupyter_events=0.9.0=pyhd8ed1ab_0
108
+ - jupyter_server=2.10.0=pyhd8ed1ab_0
109
+ - jupyter_server_terminals=0.4.4=pyhd8ed1ab_1
110
+ - jupyterlab=4.0.8=pyhd8ed1ab_0
111
+ - jupyterlab_pygments=0.2.2=pyhd8ed1ab_0
112
+ - jupyterlab_server=2.25.1=pyhd8ed1ab_0
113
+ - jupyterlab_widgets=3.0.9=pyhd8ed1ab_0
114
+ - kiwisolver=1.4.5=py311he4fd1f5_1
115
+ - krb5=1.21.2=h92f50d5_0
116
+ - langchain=0.0.333=pyhd8ed1ab_0
117
+ - langsmith=0.0.62=pyhd8ed1ab_0
118
+ - lcms2=2.15=hf2736f0_3
119
+ - lerc=4.0.0=h9a09cb3_0
120
+ - libabseil=20230802.1=cxx17_h13dd4ca_0
121
+ - libarrow=14.0.2=hfcbd24e_0_cpu
122
+ - libarrow-acero=14.0.2=h13dd4ca_0_cpu
123
+ - libarrow-dataset=14.0.2=h13dd4ca_0_cpu
124
+ - libarrow-flight=14.0.2=ha94d253_0_cpu
125
+ - libarrow-flight-sql=14.0.2=h39a9b85_0_cpu
126
+ - libarrow-gandiva=14.0.2=hf757142_0_cpu
127
+ - libarrow-substrait=14.0.2=h7fd9903_0_cpu
128
+ - libblas=3.9.0=19_osxarm64_openblas
129
+ - libbrotlicommon=1.1.0=hb547adb_1
130
+ - libbrotlidec=1.1.0=hb547adb_1
131
+ - libbrotlienc=1.1.0=hb547adb_1
132
+ - libcblas=3.9.0=19_osxarm64_openblas
133
+ - libcrc32c=1.1.2=hbdafb3b_0
134
+ - libcurl=8.5.0=h2d989ff_0
135
+ - libcxx=16.0.6=h4653b0c_0
136
+ - libdeflate=1.19=hb547adb_0
137
+ - libedit=3.1.20191231=hc8eb9b7_2
138
+ - libev=4.33=h93a5062_2
139
+ - libevent=2.1.12=h2757513_1
140
+ - libexpat=2.5.0=hb7217d7_1
141
+ - libffi=3.4.2=h3422bc3_5
142
+ - libgfortran=5.0.0=13_2_0_hd922786_1
143
+ - libgfortran5=13.2.0=hf226fd6_1
144
+ - libgoogle-cloud=2.12.0=hfb399a7_4
145
+ - libgrpc=1.59.3=hbcf6334_0
146
+ - libiconv=1.17=h0d3ecfb_2
147
+ - libjpeg-turbo=3.0.0=hb547adb_1
148
+ - liblapack=3.9.0=19_osxarm64_openblas
149
+ - libllvm15=15.0.7=h2621b3d_4
150
+ - libnghttp2=1.58.0=ha4dd798_1
151
+ - libopenblas=0.3.24=openmp_hd76b1f2_0
152
+ - libparquet=14.0.2=hf6ce1d5_0_cpu
153
+ - libpng=1.6.39=h76d750c_0
154
+ - libprotobuf=4.24.4=hc9861d8_0
155
+ - libre2-11=2023.06.02=h1753957_0
156
+ - libsodium=1.0.18=h27ca646_1
157
+ - libsqlite=3.44.0=h091b4b1_0
158
+ - libssh2=1.11.0=h7a5bd25_0
159
+ - libthrift=0.19.0=h026a170_1
160
+ - libtiff=4.6.0=ha8a6c65_2
161
+ - libutf8proc=2.8.0=h1a8c8d9_0
162
+ - libuv=1.46.0=hb547adb_0
163
+ - libwebp-base=1.3.2=hb547adb_0
164
+ - libxcb=1.15=hf346824_0
165
+ - libxml2=2.12.3=h0d0cfa8_0
166
+ - libzlib=1.2.13=h53f4e23_5
167
+ - llvm-openmp=17.0.4=hcd81f8e_0
168
+ - lz4-c=1.9.4=hb7217d7_0
169
+ - markdown-it-py=3.0.0=pyhd8ed1ab_0
170
+ - markupsafe=2.1.3=py311heffc1b2_1
171
+ - marshmallow=3.20.1=pyhd8ed1ab_0
172
+ - marshmallow-enum=1.5.1=pyh9f0ad1d_3
173
+ - matplotlib-base=3.8.1=py311hfdba5f6_0
174
+ - matplotlib-inline=0.1.6=pyhd8ed1ab_0
175
+ - mdurl=0.1.0=pyhd8ed1ab_0
176
+ - mistune=3.0.2=pyhd8ed1ab_0
177
+ - mpc=1.3.1=h91ba8db_0
178
+ - mpfr=4.2.1=h9546428_0
179
+ - mpmath=1.3.0=pyhd8ed1ab_0
180
+ - multidict=6.0.4=py311he2be06e_1
181
+ - munkres=1.0.7=py_1
182
+ - mypy_extensions=1.0.0=pyha770c72_0
183
+ - nbclient=0.8.0=pyhd8ed1ab_0
184
+ - nbconvert=7.11.0=pyhd8ed1ab_0
185
+ - nbconvert-core=7.11.0=pyhd8ed1ab_0
186
+ - nbconvert-pandoc=7.11.0=pyhd8ed1ab_0
187
+ - nbformat=5.9.2=pyhd8ed1ab_0
188
+ - ncurses=6.4=h463b476_2
189
+ - nest-asyncio=1.5.8=pyhd8ed1ab_0
190
+ - networkx=3.2.1=pyhd8ed1ab_0
191
+ - nomkl=1.0=h5ca1d4c_0
192
+ - notebook=7.0.6=pyhd8ed1ab_0
193
+ - notebook-shim=0.2.3=pyhd8ed1ab_0
194
+ - numexpr=2.8.7=py311h6e08293_4
195
+ - numpy=1.26.0=py311hb8f3215_0
196
+ - openai=0.28.1=pyhd8ed1ab_0
197
+ - openapi-schema-pydantic=1.2.4=pyhd8ed1ab_0
198
+ - openjpeg=2.5.0=h4c1507b_3
199
+ - openpyxl=3.1.2=py311heffc1b2_0
200
+ - openssl=3.2.0=h0d3ecfb_1
201
+ - orc=1.9.2=h7c018df_0
202
+ - overrides=7.4.0=pyhd8ed1ab_0
203
+ - packaging=23.2=pyhd8ed1ab_0
204
+ - pandas=2.1.2=py311h6e08293_0
205
+ - pandas-stubs=2.1.1.230928=pyhd8ed1ab_1
206
+ - pandoc=3.1.3=hce30654_0
207
+ - pandocfilters=1.5.0=pyhd8ed1ab_0
208
+ - parso=0.8.3=pyhd8ed1ab_0
209
+ - pathtools=0.1.2=py_1
210
+ - pexpect=4.8.0=pyh1a96a4e_2
211
+ - pickleshare=0.7.5=py_1003
212
+ - pillow=10.1.0=py311hb9c5795_0
213
+ - pip=23.3.1=pyhd8ed1ab_0
214
+ - pkgutil-resolve-name=1.3.10=pyhd8ed1ab_1
215
+ - platformdirs=3.11.0=pyhd8ed1ab_0
216
+ - plotly=5.18.0=pyhd8ed1ab_0
217
+ - pluggy=1.3.0=pyhd8ed1ab_0
218
+ - prometheus_client=0.18.0=pyhd8ed1ab_0
219
+ - prompt-toolkit=3.0.39=pyha770c72_0
220
+ - prompt_toolkit=3.0.39=hd8ed1ab_0
221
+ - protobuf=4.24.4=py311h4d1eceb_0
222
+ - psutil=5.9.5=py311heffc1b2_1
223
+ - pthread-stubs=0.4=h27ca646_1001
224
+ - ptyprocess=0.7.0=pyhd3deb0d_0
225
+ - pure_eval=0.2.2=pyhd8ed1ab_0
226
+ - pyarrow=14.0.2=py311hd7bc329_0_cpu
227
+ - pyasn1=0.5.0=pyhd8ed1ab_0
228
+ - pyasn1-modules=0.3.0=pyhd8ed1ab_0
229
+ - pycparser=2.21=pyhd8ed1ab_0
230
+ - pydantic=2.0.3=pyhd8ed1ab_1
231
+ - pydantic-core=2.3.0=py311h0563b04_0
232
+ - pydeck=0.8.0=pyhd8ed1ab_0
233
+ - pygments=2.16.1=pyhd8ed1ab_0
234
+ - pyobjc-core=10.0=py311hb702dc4_0
235
+ - pyobjc-framework-cocoa=10.0=py311hb702dc4_1
236
+ - pyopenssl=23.3.0=pyhd8ed1ab_0
237
+ - pyparsing=3.1.1=pyhd8ed1ab_0
238
+ - pypdf2=2.11.1=pyhd8ed1ab_0
239
+ - pysocks=1.7.1=pyha2e5f31_6
240
+ - pytest=7.4.3=pyhd8ed1ab_0
241
+ - pytest-subtests=0.11.0=pyhd8ed1ab_0
242
+ - python=3.11.6=h47c9636_0_cpython
243
+ - python-dateutil=2.8.2=pyhd8ed1ab_0
244
+ - python-fastjsonschema=2.18.1=pyhd8ed1ab_0
245
+ - python-json-logger=2.0.7=pyhd8ed1ab_0
246
+ - python-tzdata=2023.3=pyhd8ed1ab_0
247
+ - python_abi=3.11=4_cp311
248
+ - pytz=2023.3.post1=pyhd8ed1ab_0
249
+ - pyu2f=0.1.5=pyhd8ed1ab_0
250
+ - pyyaml=6.0.1=py311heffc1b2_1
251
+ - pyzmq=25.1.1=py311he9c0408_2
252
+ - qtconsole-base=5.5.0=pyha770c72_0
253
+ - qtpy=2.4.1=pyhd8ed1ab_0
254
+ - re2=2023.06.02=h6135d0a_0
255
+ - readline=8.2=h92ec313_1
256
+ - referencing=0.30.2=pyhd8ed1ab_0
257
+ - requests=2.31.0=pyhd8ed1ab_0
258
+ - rfc3339-validator=0.1.4=pyhd8ed1ab_0
259
+ - rfc3986-validator=0.1.1=pyh9f0ad1d_0
260
+ - rich=13.7.0=pyhd8ed1ab_0
261
+ - rpds-py=0.12.0=py311h94f323b_0
262
+ - rsa=4.9=pyhd8ed1ab_0
263
+ - scikit-learn=1.3.2=py311ha25ca4d_1
264
+ - scipy=1.11.3=py311h93d07a4_1
265
+ - send2trash=1.8.2=pyhd1c38e8_0
266
+ - sentry-sdk=1.34.0=pyhd8ed1ab_0
267
+ - setproctitle=1.3.3=py311heffc1b2_0
268
+ - setuptools=68.2.2=pyhd8ed1ab_0
269
+ - six=1.16.0=pyh6c4a22f_0
270
+ - sleef=3.5.1=h156473d_2
271
+ - smmap=5.0.0=pyhd8ed1ab_0
272
+ - snappy=1.1.10=h17c5cce_0
273
+ - sniffio=1.3.0=pyhd8ed1ab_0
274
+ - soupsieve=2.5=pyhd8ed1ab_1
275
+ - sqlalchemy=2.0.23=py311h05b510d_0
276
+ - stack_data=0.6.2=pyhd8ed1ab_0
277
+ - streamlit=1.29.0=pyhd8ed1ab_0
278
+ - stringcase=1.2.0=py_0
279
+ - sympy=1.12=pypyh9d50eac_103
280
+ - tenacity=8.2.3=pyhd8ed1ab_0
281
+ - terminado=0.17.1=pyhd1c38e8_0
282
+ - threadpoolctl=3.2.0=pyha21a80b_0
283
+ - tinycss2=1.2.1=pyhd8ed1ab_0
284
+ - tk=8.6.13=h5083fa2_1
285
+ - toml=0.10.2=pyhd8ed1ab_0
286
+ - tomli=2.0.1=pyhd8ed1ab_0
287
+ - toolz=0.12.0=pyhd8ed1ab_0
288
+ - tornado=6.3.3=py311heffc1b2_1
289
+ - tqdm=4.66.1=pyhd8ed1ab_0
290
+ - traitlets=5.13.0=pyhd8ed1ab_0
291
+ - types-python-dateutil=2.8.19.14=pyhd8ed1ab_0
292
+ - types-pytz=2023.3.1.1=pyhd8ed1ab_0
293
+ - typing-extensions=4.8.0=hd8ed1ab_0
294
+ - typing_extensions=4.8.0=pyha770c72_0
295
+ - typing_inspect=0.9.0=pyhd8ed1ab_0
296
+ - typing_utils=0.1.0=pyhd8ed1ab_0
297
+ - tzdata=2023c=h71feb2d_0
298
+ - tzlocal=5.2=py311h267d04e_0
299
+ - uri-template=1.3.0=pyhd8ed1ab_0
300
+ - urllib3=2.0.7=pyhd8ed1ab_0
301
+ - validators=0.14.0=py_0
302
+ - wandb=0.15.12=pyhd8ed1ab_0
303
+ - watchdog=3.0.0=py311heffc1b2_1
304
+ - wcwidth=0.2.9=pyhd8ed1ab_0
305
+ - webcolors=1.13=pyhd8ed1ab_0
306
+ - webencodings=0.5.1=pyhd8ed1ab_2
307
+ - websocket-client=1.6.4=pyhd8ed1ab_0
308
+ - wheel=0.41.3=pyhd8ed1ab_0
309
+ - widgetsnbextension=4.0.9=pyhd8ed1ab_0
310
+ - xorg-libxau=1.0.11=hb547adb_0
311
+ - xorg-libxdmcp=1.1.3=h27ca646_0
312
+ - xz=5.2.6=h57fd34a_0
313
+ - yaml=0.2.5=h3422bc3_2
314
+ - yarl=1.9.2=py311h05b510d_1
315
+ - zeromq=4.3.5=h965bd2d_0
316
+ - zipp=3.17.0=pyhd8ed1ab_0
317
+ - zstd=1.5.5=h4f39d0f_0
318
+ - pip:
319
+ - einops==0.7.0
320
+ - faiss-cpu==1.7.4
321
+ - huggingface-hub==0.17.3
322
+ - instructorembedding==1.0.1
323
+ - nltk==3.8.1
324
+ - python-dotenv==1.0.0
325
+ - regex==2023.10.3
326
+ - safetensors==0.4.0
327
+ - sentence-transformers==2.2.2
328
+ - sentencepiece==0.1.99
329
+ - tokenizers==0.14.1
330
+ - torch==2.1.1
331
+ - torchvision==0.16.1
332
+ - transformers==4.35.0
333
+ prefix: /Users/danielsuarez-mash/anaconda3/envs/llm
environment_ignore.yml ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ channels:
2
+ - conda-forge
3
+ - defaults
4
+ dependencies:
5
+ - streamlit=1.29.0=pyhd8ed1ab_0
6
+ - pypdf2=2.11.1=pyhd8ed1ab_0
7
+ - langchain=0.0.333=pyhd8ed1ab_0
8
+ - pip=23.3.1=pyhd8ed1ab_0
9
+ - pip:
10
+ - huggingface-hub==0.17.3
11
+ - faiss-cpu==1.7.4
12
+ - instructorembedding==1.0.1
13
+ - python-dotenv==1.0.0
14
+ - sentence-transformers==2.2.2
15
+ - transformers==4.35.0
llm_handbook.ipynb ADDED
@@ -0,0 +1,1255 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "a39a30cb-7280-4cb5-9c08-ab4ed1a7b2b4",
6
+ "metadata": {
7
+ "id": "a39a30cb-7280-4cb5-9c08-ab4ed1a7b2b4"
8
+ },
9
+ "source": [
10
+ "# LLM handbook\n",
11
+ "\n",
12
+ "Following guidance from <a href='https://www.pinecone.io/learn/series/langchain/'> Pinecone's Langchain handbook.</a>"
13
+ ]
14
+ },
15
+ {
16
+ "cell_type": "code",
17
+ "execution_count": 2,
18
+ "id": "1qUakls_hN6R",
19
+ "metadata": {
20
+ "colab": {
21
+ "base_uri": "https://localhost:8080/"
22
+ },
23
+ "id": "1qUakls_hN6R",
24
+ "outputId": "c9988f04-0c1e-41fb-d239-638562d6f754"
25
+ },
26
+ "outputs": [],
27
+ "source": [
28
+ "# # if using Google Colab\n",
29
+ "# !pip install langchain\n",
30
+ "# !pip install huggingface_hub\n",
31
+ "# !pip install python-dotenv\n",
32
+ "# !pip install pypdf2\n",
33
+ "# !pip install faiss-cpu\n",
34
+ "# !pip install sentence_transformers\n",
35
+ "# !pip install InstructorEmbedding"
36
+ ]
37
+ },
38
+ {
39
+ "cell_type": "code",
40
+ "execution_count": 3,
41
+ "id": "9fcd2583-d0ab-4649-a241-4526f6a3b83d",
42
+ "metadata": {
43
+ "id": "9fcd2583-d0ab-4649-a241-4526f6a3b83d"
44
+ },
45
+ "outputs": [],
46
+ "source": [
47
+ "# import packages\n",
48
+ "import os\n",
49
+ "import langchain\n",
50
+ "import getpass\n",
51
+ "from langchain import HuggingFaceHub, LLMChain\n",
52
+ "from dotenv import load_dotenv"
53
+ ]
54
+ },
55
+ {
56
+ "cell_type": "markdown",
57
+ "id": "AyRxKsE4qPR1",
58
+ "metadata": {
59
+ "id": "AyRxKsE4qPR1"
60
+ },
61
+ "source": [
62
+ "#API KEY"
63
+ ]
64
+ },
65
+ {
66
+ "cell_type": "code",
67
+ "execution_count": 4,
68
+ "id": "cf146257-5014-4041-980c-0ead2c3932c3",
69
+ "metadata": {
70
+ "id": "cf146257-5014-4041-980c-0ead2c3932c3"
71
+ },
72
+ "outputs": [],
73
+ "source": [
74
+ "# LOCAL\n",
75
+ "load_dotenv()\n",
76
+ "os.environ.get('HUGGINGFACEHUB_API_TOKEN');"
77
+ ]
78
+ },
79
+ {
80
+ "cell_type": "markdown",
81
+ "id": "yeGkB8OohG93",
82
+ "metadata": {
83
+ "id": "yeGkB8OohG93"
84
+ },
85
+ "source": [
86
+ "# Skill 1 - using prompt templates\n",
87
+ "\n",
88
+ "A prompt is the input to the LLM. Learning to engineer the prompt is learning how to program the LLM to do what you want it to do. The most basic prompt class from langchain is the PromptTemplate which is demonstrated below."
89
+ ]
90
+ },
91
+ {
92
+ "cell_type": "code",
93
+ "execution_count": 5,
94
+ "id": "06c54d35-e9a2-4043-b3c3-588ac4f4a0d1",
95
+ "metadata": {
96
+ "id": "06c54d35-e9a2-4043-b3c3-588ac4f4a0d1"
97
+ },
98
+ "outputs": [],
99
+ "source": [
100
+ "from langchain import PromptTemplate\n",
101
+ "\n",
102
+ "# create template\n",
103
+ "template = \"\"\"\n",
104
+ "Answer the following question: {question}\n",
105
+ "\n",
106
+ "Answer:\n",
107
+ "\"\"\"\n",
108
+ "\n",
109
+ "# create prompt using template\n",
110
+ "prompt = PromptTemplate(\n",
111
+ " template=template,\n",
112
+ " input_variables=['question']\n",
113
+ ")"
114
+ ]
115
+ },
116
+ {
117
+ "cell_type": "markdown",
118
+ "id": "A1rhV_L1hG94",
119
+ "metadata": {
120
+ "id": "A1rhV_L1hG94"
121
+ },
122
+ "source": [
123
+ "The next step is to instantiate the LLM. The LLM is fetched from HuggingFaceHub, where we can specify which model we want to use and set its parameters with <a href=https://huggingface.co/docs/transformers/main_classes/text_generation>this as reference </a>. We then set up the prompt+LLM chain using langchain's LLMChain class."
124
+ ]
125
+ },
126
+ {
127
+ "cell_type": "code",
128
+ "execution_count": 6,
129
+ "id": "03290cad-f6be-4002-b177-00220f22333a",
130
+ "metadata": {
131
+ "colab": {
132
+ "base_uri": "https://localhost:8080/"
133
+ },
134
+ "id": "03290cad-f6be-4002-b177-00220f22333a",
135
+ "outputId": "f5dde425-cf9d-416b-a030-3c5d065bafcb"
136
+ },
137
+ "outputs": [
138
+ {
139
+ "name": "stderr",
140
+ "output_type": "stream",
141
+ "text": [
142
+ "/Users/danielsuarez-mash/anaconda3/envs/llm/lib/python3.11/site-packages/huggingface_hub/utils/_deprecation.py:127: FutureWarning: '__init__' (from 'huggingface_hub.inference_api') is deprecated and will be removed from version '0.19.0'. `InferenceApi` client is deprecated in favor of the more feature-complete `InferenceClient`. Check out this guide to learn how to convert your script to use it: https://huggingface.co/docs/huggingface_hub/guides/inference#legacy-inferenceapi-client.\n",
143
+ " warnings.warn(warning_message, FutureWarning)\n"
144
+ ]
145
+ }
146
+ ],
147
+ "source": [
148
+ "# instantiate llm\n",
149
+ "llm = HuggingFaceHub(\n",
150
+ " repo_id='tiiuae/falcon-7b-instruct',\n",
151
+ " model_kwargs={\n",
152
+ " 'temperature':1,\n",
153
+ " 'penalty_alpha':2,\n",
154
+ " 'top_k':50,\n",
155
+ " 'max_length': 1000\n",
156
+ " }\n",
157
+ ")\n",
158
+ "\n",
159
+ "# instantiate chain\n",
160
+ "llm_chain = LLMChain(\n",
161
+ " llm=llm,\n",
162
+ " prompt=prompt,\n",
163
+ " verbose=True\n",
164
+ ")"
165
+ ]
166
+ },
167
+ {
168
+ "cell_type": "markdown",
169
+ "id": "SeVzuXAxhG96",
170
+ "metadata": {
171
+ "id": "SeVzuXAxhG96"
172
+ },
173
+ "source": [
174
+ "Now all that's left to do is ask a question and run the chain."
175
+ ]
176
+ },
177
+ {
178
+ "cell_type": "code",
179
+ "execution_count": 7,
180
+ "id": "92bcc47b-da8a-4641-ae1d-3beb3f870a4f",
181
+ "metadata": {
182
+ "colab": {
183
+ "base_uri": "https://localhost:8080/"
184
+ },
185
+ "id": "92bcc47b-da8a-4641-ae1d-3beb3f870a4f",
186
+ "outputId": "2cb57096-85a4-4c3b-d333-2c20ba4f8166"
187
+ },
188
+ "outputs": [
189
+ {
190
+ "name": "stdout",
191
+ "output_type": "stream",
192
+ "text": [
193
+ "\n",
194
+ "\n",
195
+ "\u001b[1m> Entering new LLMChain chain...\u001b[0m\n",
196
+ "Prompt after formatting:\n",
197
+ "\u001b[32;1m\u001b[1;3m\n",
198
+ "Answer the following question: How many champions league titles has Real Madrid won?\n",
199
+ "\n",
200
+ "Answer:\n",
201
+ "\u001b[0m\n",
202
+ "\n",
203
+ "\u001b[1m> Finished chain.\u001b[0m\n",
204
+ "Real Madrid has won 14 La Liga titles, 19 Copa del Rey titles, and 14 Supercopa de España titles. To add to this, they have also won 11 UEFA Champions League titles, making them the most successful club in the UEFA Champions League history.\n"
205
+ ]
206
+ }
207
+ ],
208
+ "source": [
209
+ "# define question\n",
210
+ "question = \"How many champions league titles has Real Madrid won?\"\n",
211
+ "\n",
212
+ "# run question\n",
213
+ "print(llm_chain.run(question))"
214
+ ]
215
+ },
216
+ {
217
+ "cell_type": "markdown",
218
+ "id": "OOXGnVnRhG96",
219
+ "metadata": {
220
+ "id": "OOXGnVnRhG96"
221
+ },
222
+ "source": [
223
+ "# Skill 2 - using chains\n",
224
+ "\n",
225
+ "Chains are at the core of langchain. They represent a sequence of actions. Above, we used a simple prompt + LLM chain. Let's try some more complex chains."
226
+ ]
227
+ },
228
+ {
229
+ "cell_type": "markdown",
230
+ "id": "kc59-q-NhG97",
231
+ "metadata": {
232
+ "id": "kc59-q-NhG97"
233
+ },
234
+ "source": [
235
+ "## Math chain"
236
+ ]
237
+ },
238
+ {
239
+ "cell_type": "code",
240
+ "execution_count": 8,
241
+ "id": "ClxH-ST-hG97",
242
+ "metadata": {
243
+ "colab": {
244
+ "base_uri": "https://localhost:8080/"
245
+ },
246
+ "id": "ClxH-ST-hG97",
247
+ "outputId": "f950d00b-6e7e-4b49-ef74-ad8963c76a6e"
248
+ },
249
+ "outputs": [
250
+ {
251
+ "name": "stdout",
252
+ "output_type": "stream",
253
+ "text": [
254
+ "\n",
255
+ "\n",
256
+ "\u001b[1m> Entering new LLMMathChain chain...\u001b[0m\n",
257
+ "Calculate 5-3?\u001b[32;1m\u001b[1;3m```text\n",
258
+ "-3 -\n",
259
+ "```\n",
260
+ "...numexpr.evaluate(\"-3 -\")...\n",
261
+ "\u001b[0m"
262
+ ]
263
+ },
264
+ {
265
+ "ename": "ValueError",
266
+ "evalue": "LLMMathChain._evaluate(\"\n-3 -\n\") raised error: invalid syntax (<expr>, line 1). Please try again with a valid numerical expression",
267
+ "output_type": "error",
268
+ "traceback": [
269
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
270
+ "\u001b[0;31mSyntaxError\u001b[0m Traceback (most recent call last)",
271
+ "File \u001b[0;32m~/anaconda3/envs/llm/lib/python3.11/site-packages/langchain/chains/llm_math/base.py:88\u001b[0m, in \u001b[0;36mLLMMathChain._evaluate_expression\u001b[0;34m(self, expression)\u001b[0m\n\u001b[1;32m 86\u001b[0m local_dict \u001b[38;5;241m=\u001b[39m {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mpi\u001b[39m\u001b[38;5;124m\"\u001b[39m: math\u001b[38;5;241m.\u001b[39mpi, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124me\u001b[39m\u001b[38;5;124m\"\u001b[39m: math\u001b[38;5;241m.\u001b[39me}\n\u001b[1;32m 87\u001b[0m output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mstr\u001b[39m(\n\u001b[0;32m---> 88\u001b[0m \u001b[43mnumexpr\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mevaluate\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 89\u001b[0m \u001b[43m \u001b[49m\u001b[43mexpression\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mstrip\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 90\u001b[0m \u001b[43m \u001b[49m\u001b[43mglobal_dict\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m{\u001b[49m\u001b[43m}\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# restrict access to globals\u001b[39;49;00m\n\u001b[1;32m 91\u001b[0m \u001b[43m \u001b[49m\u001b[43mlocal_dict\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mlocal_dict\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# add common mathematical functions\u001b[39;49;00m\n\u001b[1;32m 92\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 93\u001b[0m )\n\u001b[1;32m 94\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n",
272
+ "File \u001b[0;32m~/anaconda3/envs/llm/lib/python3.11/site-packages/numexpr/necompiler.py:975\u001b[0m, in \u001b[0;36mevaluate\u001b[0;34m(ex, local_dict, global_dict, out, order, casting, sanitize, _frame_depth, **kwargs)\u001b[0m\n\u001b[1;32m 974\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m--> 975\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n",
273
+ "File \u001b[0;32m~/anaconda3/envs/llm/lib/python3.11/site-packages/numexpr/necompiler.py:872\u001b[0m, in \u001b[0;36mvalidate\u001b[0;34m(ex, local_dict, global_dict, out, order, casting, _frame_depth, sanitize, **kwargs)\u001b[0m\n\u001b[1;32m 871\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m expr_key \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;129;01min\u001b[39;00m _names_cache:\n\u001b[0;32m--> 872\u001b[0m _names_cache[expr_key] \u001b[38;5;241m=\u001b[39m \u001b[43mgetExprNames\u001b[49m\u001b[43m(\u001b[49m\u001b[43mex\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcontext\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43msanitize\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43msanitize\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 873\u001b[0m names, ex_uses_vml \u001b[38;5;241m=\u001b[39m _names_cache[expr_key]\n",
274
+ "File \u001b[0;32m~/anaconda3/envs/llm/lib/python3.11/site-packages/numexpr/necompiler.py:721\u001b[0m, in \u001b[0;36mgetExprNames\u001b[0;34m(text, context, sanitize)\u001b[0m\n\u001b[1;32m 720\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mgetExprNames\u001b[39m(text, context, sanitize: \u001b[38;5;28mbool\u001b[39m\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m):\n\u001b[0;32m--> 721\u001b[0m ex \u001b[38;5;241m=\u001b[39m \u001b[43mstringToExpression\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtext\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m{\u001b[49m\u001b[43m}\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcontext\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43msanitize\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 722\u001b[0m ast \u001b[38;5;241m=\u001b[39m expressionToAST(ex)\n",
275
+ "File \u001b[0;32m~/anaconda3/envs/llm/lib/python3.11/site-packages/numexpr/necompiler.py:291\u001b[0m, in \u001b[0;36mstringToExpression\u001b[0;34m(s, types, context, sanitize)\u001b[0m\n\u001b[1;32m 290\u001b[0m flags \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0\u001b[39m\n\u001b[0;32m--> 291\u001b[0m c \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mcompile\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m<expr>\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43meval\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mflags\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 292\u001b[0m \u001b[38;5;66;03m# make VariableNode's for the names\u001b[39;00m\n",
276
+ "\u001b[0;31mSyntaxError\u001b[0m: invalid syntax (<expr>, line 1)",
277
+ "\nDuring handling of the above exception, another exception occurred:\n",
278
+ "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
279
+ "Cell \u001b[0;32mIn[8], line 5\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mlangchain\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mchains\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m LLMMathChain\n\u001b[1;32m 3\u001b[0m llm_math_chain \u001b[38;5;241m=\u001b[39m LLMMathChain\u001b[38;5;241m.\u001b[39mfrom_llm(llm, verbose\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n\u001b[0;32m----> 5\u001b[0m \u001b[43mllm_math_chain\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mCalculate 5-3?\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n",
280
+ "File \u001b[0;32m~/anaconda3/envs/llm/lib/python3.11/site-packages/langchain/chains/base.py:505\u001b[0m, in \u001b[0;36mChain.run\u001b[0;34m(self, callbacks, tags, metadata, *args, **kwargs)\u001b[0m\n\u001b[1;32m 503\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(args) \u001b[38;5;241m!=\u001b[39m \u001b[38;5;241m1\u001b[39m:\n\u001b[1;32m 504\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m`run` supports only one positional argument.\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m--> 505\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43margs\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcallbacks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcallbacks\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtags\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtags\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmetadata\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmetadata\u001b[49m\u001b[43m)\u001b[49m[\n\u001b[1;32m 506\u001b[0m _output_key\n\u001b[1;32m 507\u001b[0m ]\n\u001b[1;32m 509\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m kwargs \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m args:\n\u001b[1;32m 510\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m(kwargs, callbacks\u001b[38;5;241m=\u001b[39mcallbacks, tags\u001b[38;5;241m=\u001b[39mtags, metadata\u001b[38;5;241m=\u001b[39mmetadata)[\n\u001b[1;32m 511\u001b[0m _output_key\n\u001b[1;32m 512\u001b[0m ]\n",
281
+ "File \u001b[0;32m~/anaconda3/envs/llm/lib/python3.11/site-packages/langchain/chains/base.py:310\u001b[0m, in \u001b[0;36mChain.__call__\u001b[0;34m(self, inputs, return_only_outputs, callbacks, tags, metadata, run_name, include_run_info)\u001b[0m\n\u001b[1;32m 308\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 309\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_error(e)\n\u001b[0;32m--> 310\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m 311\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_end(outputs)\n\u001b[1;32m 312\u001b[0m final_outputs: Dict[\u001b[38;5;28mstr\u001b[39m, Any] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mprep_outputs(\n\u001b[1;32m 313\u001b[0m inputs, outputs, return_only_outputs\n\u001b[1;32m 314\u001b[0m )\n",
282
+ "File \u001b[0;32m~/anaconda3/envs/llm/lib/python3.11/site-packages/langchain/chains/base.py:304\u001b[0m, in \u001b[0;36mChain.__call__\u001b[0;34m(self, inputs, return_only_outputs, callbacks, tags, metadata, run_name, include_run_info)\u001b[0m\n\u001b[1;32m 297\u001b[0m run_manager \u001b[38;5;241m=\u001b[39m callback_manager\u001b[38;5;241m.\u001b[39mon_chain_start(\n\u001b[1;32m 298\u001b[0m dumpd(\u001b[38;5;28mself\u001b[39m),\n\u001b[1;32m 299\u001b[0m inputs,\n\u001b[1;32m 300\u001b[0m name\u001b[38;5;241m=\u001b[39mrun_name,\n\u001b[1;32m 301\u001b[0m )\n\u001b[1;32m 302\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 303\u001b[0m outputs \u001b[38;5;241m=\u001b[39m (\n\u001b[0;32m--> 304\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call\u001b[49m\u001b[43m(\u001b[49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_manager\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 305\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m new_arg_supported\n\u001b[1;32m 306\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_call(inputs)\n\u001b[1;32m 307\u001b[0m )\n\u001b[1;32m 308\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 309\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_error(e)\n",
283
+ "File \u001b[0;32m~/anaconda3/envs/llm/lib/python3.11/site-packages/langchain/chains/llm_math/base.py:157\u001b[0m, in \u001b[0;36mLLMMathChain._call\u001b[0;34m(self, inputs, run_manager)\u001b[0m\n\u001b[1;32m 151\u001b[0m _run_manager\u001b[38;5;241m.\u001b[39mon_text(inputs[\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39minput_key])\n\u001b[1;32m 152\u001b[0m llm_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mllm_chain\u001b[38;5;241m.\u001b[39mpredict(\n\u001b[1;32m 153\u001b[0m question\u001b[38;5;241m=\u001b[39minputs[\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39minput_key],\n\u001b[1;32m 154\u001b[0m stop\u001b[38;5;241m=\u001b[39m[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m```output\u001b[39m\u001b[38;5;124m\"\u001b[39m],\n\u001b[1;32m 155\u001b[0m callbacks\u001b[38;5;241m=\u001b[39m_run_manager\u001b[38;5;241m.\u001b[39mget_child(),\n\u001b[1;32m 156\u001b[0m )\n\u001b[0;32m--> 157\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_process_llm_result\u001b[49m\u001b[43m(\u001b[49m\u001b[43mllm_output\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m_run_manager\u001b[49m\u001b[43m)\u001b[49m\n",
284
+ "File \u001b[0;32m~/anaconda3/envs/llm/lib/python3.11/site-packages/langchain/chains/llm_math/base.py:111\u001b[0m, in \u001b[0;36mLLMMathChain._process_llm_result\u001b[0;34m(self, llm_output, run_manager)\u001b[0m\n\u001b[1;32m 109\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m text_match:\n\u001b[1;32m 110\u001b[0m expression \u001b[38;5;241m=\u001b[39m text_match\u001b[38;5;241m.\u001b[39mgroup(\u001b[38;5;241m1\u001b[39m)\n\u001b[0;32m--> 111\u001b[0m output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_evaluate_expression\u001b[49m\u001b[43m(\u001b[49m\u001b[43mexpression\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 112\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_text(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124mAnswer: \u001b[39m\u001b[38;5;124m\"\u001b[39m, verbose\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mverbose)\n\u001b[1;32m 113\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_text(output, color\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124myellow\u001b[39m\u001b[38;5;124m\"\u001b[39m, verbose\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mverbose)\n",
285
+ "File \u001b[0;32m~/anaconda3/envs/llm/lib/python3.11/site-packages/langchain/chains/llm_math/base.py:95\u001b[0m, in \u001b[0;36mLLMMathChain._evaluate_expression\u001b[0;34m(self, expression)\u001b[0m\n\u001b[1;32m 87\u001b[0m output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mstr\u001b[39m(\n\u001b[1;32m 88\u001b[0m numexpr\u001b[38;5;241m.\u001b[39mevaluate(\n\u001b[1;32m 89\u001b[0m expression\u001b[38;5;241m.\u001b[39mstrip(),\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 92\u001b[0m )\n\u001b[1;32m 93\u001b[0m )\n\u001b[1;32m 94\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[0;32m---> 95\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[1;32m 96\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mLLMMathChain._evaluate(\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mexpression\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m) raised error: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00me\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m.\u001b[39m\u001b[38;5;124m'\u001b[39m\n\u001b[1;32m 97\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m Please try again with a valid numerical expression\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 98\u001b[0m )\n\u001b[1;32m 100\u001b[0m \u001b[38;5;66;03m# Remove any leading and trailing brackets from the output\u001b[39;00m\n\u001b[1;32m 101\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m re\u001b[38;5;241m.\u001b[39msub(\u001b[38;5;124mr\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m^\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124m[|\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124m]$\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m\"\u001b[39m, output)\n",
286
+ "\u001b[0;31mValueError\u001b[0m: LLMMathChain._evaluate(\"\n-3 -\n\") raised error: invalid syntax (<expr>, line 1). Please try again with a valid numerical expression"
287
+ ]
288
+ }
289
+ ],
290
+ "source": [
291
+ "from langchain.chains import LLMMathChain\n",
292
+ "\n",
293
+ "llm_math_chain = LLMMathChain.from_llm(llm, verbose=True)\n",
294
+ "\n",
295
+ "llm_math_chain.run(\"Calculate 5-3?\")"
296
+ ]
297
+ },
298
+ {
299
+ "cell_type": "markdown",
300
+ "id": "-WmXZ6nLhG98",
301
+ "metadata": {
302
+ "id": "-WmXZ6nLhG98"
303
+ },
304
+ "source": [
305
+ "We can see what prompt the LLMMathChain class is using here. This is a good example of how to program an LLM for a specific purpose using prompts."
306
+ ]
307
+ },
308
+ {
309
+ "cell_type": "code",
310
+ "execution_count": null,
311
+ "id": "ecbnY7jqhG98",
312
+ "metadata": {
313
+ "colab": {
314
+ "base_uri": "https://localhost:8080/"
315
+ },
316
+ "id": "ecbnY7jqhG98",
317
+ "outputId": "a3f37a81-3b44-41f7-8002-86172ad4e085"
318
+ },
319
+ "outputs": [
320
+ {
321
+ "name": "stdout",
322
+ "output_type": "stream",
323
+ "text": [
324
+ "Translate a math problem into a expression that can be executed using Python's numexpr library. Use the output of running this code to answer the question.\n",
325
+ "\n",
326
+ "Question: ${{Question with math problem.}}\n",
327
+ "```text\n",
328
+ "${{single line mathematical expression that solves the problem}}\n",
329
+ "```\n",
330
+ "...numexpr.evaluate(text)...\n",
331
+ "```output\n",
332
+ "${{Output of running the code}}\n",
333
+ "```\n",
334
+ "Answer: ${{Answer}}\n",
335
+ "\n",
336
+ "Begin.\n",
337
+ "\n",
338
+ "Question: What is 37593 * 67?\n",
339
+ "```text\n",
340
+ "37593 * 67\n",
341
+ "```\n",
342
+ "...numexpr.evaluate(\"37593 * 67\")...\n",
343
+ "```output\n",
344
+ "2518731\n",
345
+ "```\n",
346
+ "Answer: 2518731\n",
347
+ "\n",
348
+ "Question: 37593^(1/5)\n",
349
+ "```text\n",
350
+ "37593**(1/5)\n",
351
+ "```\n",
352
+ "...numexpr.evaluate(\"37593**(1/5)\")...\n",
353
+ "```output\n",
354
+ "8.222831614237718\n",
355
+ "```\n",
356
+ "Answer: 8.222831614237718\n",
357
+ "\n",
358
+ "Question: {question}\n",
359
+ "\n"
360
+ ]
361
+ }
362
+ ],
363
+ "source": [
364
+ "print(llm_math_chain.prompt.template)"
365
+ ]
366
+ },
367
+ {
368
+ "cell_type": "markdown",
369
+ "id": "rGxlC_srhG99",
370
+ "metadata": {
371
+ "id": "rGxlC_srhG99"
372
+ },
373
+ "source": [
374
+ "## Transform chain\n",
375
+ "\n",
376
+ "The transform chain allows transform queries before they are fed into the LLM."
377
+ ]
378
+ },
379
+ {
380
+ "cell_type": "code",
381
+ "execution_count": 11,
382
+ "id": "7aXq5CGLhG99",
383
+ "metadata": {
384
+ "id": "7aXq5CGLhG99"
385
+ },
386
+ "outputs": [],
387
+ "source": [
388
+ "import re\n",
389
+ "\n",
390
+ "# define function to transform query\n",
391
+ "def transform_func(inputs: dict) -> dict:\n",
392
+ "\n",
393
+ " question = inputs['raw_question']\n",
394
+ "\n",
395
+ " question = re.sub(' +', ' ', question)\n",
396
+ "\n",
397
+ " return {'question': question}"
398
+ ]
399
+ },
400
+ {
401
+ "cell_type": "code",
402
+ "execution_count": 12,
403
+ "id": "lEG14RpahG99",
404
+ "metadata": {
405
+ "colab": {
406
+ "base_uri": "https://localhost:8080/",
407
+ "height": 35
408
+ },
409
+ "id": "lEG14RpahG99",
410
+ "outputId": "0e9243c5-b506-48a1-8036-a54b2cd8ab53"
411
+ },
412
+ "outputs": [
413
+ {
414
+ "data": {
415
+ "text/plain": [
416
+ "'Hello my name is Daniel'"
417
+ ]
418
+ },
419
+ "execution_count": 12,
420
+ "metadata": {},
421
+ "output_type": "execute_result"
422
+ }
423
+ ],
424
+ "source": [
425
+ "from langchain.chains import TransformChain\n",
426
+ "\n",
427
+ "# define transform chain\n",
428
+ "transform_chain = TransformChain(input_variables=['raw_question'], output_variables=['question'], transform=transform_func)\n",
429
+ "\n",
430
+ "# test transform chain\n",
431
+ "transform_chain.run('Hello my name is Daniel')"
432
+ ]
433
+ },
434
+ {
435
+ "cell_type": "code",
436
+ "execution_count": 13,
437
+ "id": "TOzl_x6KhG9-",
438
+ "metadata": {
439
+ "id": "TOzl_x6KhG9-"
440
+ },
441
+ "outputs": [],
442
+ "source": [
443
+ "from langchain.chains import SequentialChain\n",
444
+ "\n",
445
+ "sequential_chain = SequentialChain(chains=[transform_chain, llm_chain], input_variables=['raw_question'])"
446
+ ]
447
+ },
448
+ {
449
+ "cell_type": "code",
450
+ "execution_count": 14,
451
+ "id": "dRuMuSNWhG9_",
452
+ "metadata": {
453
+ "colab": {
454
+ "base_uri": "https://localhost:8080/"
455
+ },
456
+ "id": "dRuMuSNWhG9_",
457
+ "outputId": "b676c693-113a-4757-bcbe-cb0c02e45d15"
458
+ },
459
+ "outputs": [
460
+ {
461
+ "name": "stdout",
462
+ "output_type": "stream",
463
+ "text": [
464
+ "\n",
465
+ "\n",
466
+ "\u001b[1m> Entering new LLMChain chain...\u001b[0m\n",
467
+ "Prompt after formatting:\n",
468
+ "\u001b[32;1m\u001b[1;3m\n",
469
+ "Answer the following question: What will happen to me if I only get 4 hours sleep tonight?\n",
470
+ "\n",
471
+ "Answer:\n",
472
+ "\u001b[0m\n",
473
+ "\n",
474
+ "\u001b[1m> Finished chain.\u001b[0m\n",
475
+ "4 Hours of sleep may lead to: \n",
476
+ "- Poor concentration and alertness\n",
477
+ "- Decreased performance\n",
478
+ "- Low energy levels\n",
479
+ "- Increased risk of accidents and mistakes\n",
480
+ "- Poor physical and emotional well-being \n",
481
+ "\n",
482
+ "Getting only 4 hours of sleep may also lead to impaired reaction time, diminished physical performance, and impair logical thinking. Therefore, it's recommended to get at least 8-10 hours of sleep to optimally function.\n"
483
+ ]
484
+ }
485
+ ],
486
+ "source": [
487
+ "print(sequential_chain.run(\"What will happen to me if I only get 4 hours sleep tonight?\"))"
488
+ ]
489
+ },
490
+ {
491
+ "cell_type": "markdown",
492
+ "id": "IzVk22o3tAXu",
493
+ "metadata": {
494
+ "id": "IzVk22o3tAXu"
495
+ },
496
+ "source": [
497
+ "# Skill 3 - conversational memory\n",
498
+ "\n",
499
+ "In order to have a conversation, the LLM now needs two inputs - the new query and the chat history.\n",
500
+ "\n",
501
+ "ConversationChain is a chain which manages these two inputs with an appropriate template as shown below."
502
+ ]
503
+ },
504
+ {
505
+ "cell_type": "code",
506
+ "execution_count": 15,
507
+ "id": "Qq3No2kChG9_",
508
+ "metadata": {
509
+ "colab": {
510
+ "base_uri": "https://localhost:8080/"
511
+ },
512
+ "id": "Qq3No2kChG9_",
513
+ "outputId": "3dc29aed-2b1d-42c1-ec69-969e82bb025f"
514
+ },
515
+ "outputs": [
516
+ {
517
+ "name": "stdout",
518
+ "output_type": "stream",
519
+ "text": [
520
+ "The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
521
+ "\n",
522
+ "Current conversation:\n",
523
+ "{history}\n",
524
+ "Human: {input}\n",
525
+ "AI:\n"
526
+ ]
527
+ }
528
+ ],
529
+ "source": [
530
+ "from langchain.chains import ConversationChain\n",
531
+ "\n",
532
+ "conversation_chain = ConversationChain(llm=llm, verbose=True)\n",
533
+ "\n",
534
+ "print(conversation_chain.prompt.template)"
535
+ ]
536
+ },
537
+ {
538
+ "cell_type": "markdown",
539
+ "id": "AJ9X_UnlTNFN",
540
+ "metadata": {
541
+ "id": "AJ9X_UnlTNFN"
542
+ },
543
+ "source": [
544
+ "## ConversationBufferMemory"
545
+ ]
546
+ },
547
+ {
548
+ "cell_type": "markdown",
549
+ "id": "e3q6q0qkus6Z",
550
+ "metadata": {
551
+ "id": "e3q6q0qkus6Z"
552
+ },
553
+ "source": [
554
+ "To manage conversation history, we can use ConversationalBufferMemory which inputs the raw chat history."
555
+ ]
556
+ },
557
+ {
558
+ "cell_type": "code",
559
+ "execution_count": 16,
560
+ "id": "noJ8pG9muDZK",
561
+ "metadata": {
562
+ "id": "noJ8pG9muDZK"
563
+ },
564
+ "outputs": [],
565
+ "source": [
566
+ "from langchain.chains.conversation.memory import ConversationBufferMemory\n",
567
+ "\n",
568
+ "# set memory type\n",
569
+ "conversation_chain.memory = ConversationBufferMemory()"
570
+ ]
571
+ },
572
+ {
573
+ "cell_type": "code",
574
+ "execution_count": 17,
575
+ "id": "WCqQ53PAOZmv",
576
+ "metadata": {
577
+ "colab": {
578
+ "base_uri": "https://localhost:8080/"
579
+ },
580
+ "id": "WCqQ53PAOZmv",
581
+ "outputId": "204005ab-621a-48e4-e2b2-533c5f53424e"
582
+ },
583
+ "outputs": [
584
+ {
585
+ "name": "stdout",
586
+ "output_type": "stream",
587
+ "text": [
588
+ "\n",
589
+ "\n",
590
+ "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
591
+ "Prompt after formatting:\n",
592
+ "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
593
+ "\n",
594
+ "Current conversation:\n",
595
+ "\n",
596
+ "Human: What is the weather like today?\n",
597
+ "AI:\u001b[0m\n",
598
+ "\n",
599
+ "\u001b[1m> Finished chain.\u001b[0m\n"
600
+ ]
601
+ },
602
+ {
603
+ "data": {
604
+ "text/plain": [
605
+ "{'input': 'What is the weather like today?',\n",
606
+ " 'history': '',\n",
607
+ " 'response': ' The weather today is sunny and warm, in the mid-80s.\\nUser '}"
608
+ ]
609
+ },
610
+ "execution_count": 17,
611
+ "metadata": {},
612
+ "output_type": "execute_result"
613
+ }
614
+ ],
615
+ "source": [
616
+ "conversation_chain(\"What is the weather like today?\")"
617
+ ]
618
+ },
619
+ {
620
+ "cell_type": "code",
621
+ "execution_count": 18,
622
+ "id": "DyGNbP4xvQRw",
623
+ "metadata": {
624
+ "colab": {
625
+ "base_uri": "https://localhost:8080/"
626
+ },
627
+ "id": "DyGNbP4xvQRw",
628
+ "outputId": "70bd84ee-01d8-414c-bff5-5f9aa8cc4ad4"
629
+ },
630
+ "outputs": [
631
+ {
632
+ "name": "stdout",
633
+ "output_type": "stream",
634
+ "text": [
635
+ "\n",
636
+ "\n",
637
+ "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
638
+ "Prompt after formatting:\n",
639
+ "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
640
+ "\n",
641
+ "Current conversation:\n",
642
+ "Human: What is the weather like today?\n",
643
+ "AI: The weather today is sunny and warm, in the mid-80s.\n",
644
+ "User \n",
645
+ "Human: What was my previous question?\n",
646
+ "AI:\u001b[0m\n",
647
+ "\n",
648
+ "\u001b[1m> Finished chain.\u001b[0m\n"
649
+ ]
650
+ },
651
+ {
652
+ "data": {
653
+ "text/plain": [
654
+ "{'input': 'What was my previous question?',\n",
655
+ " 'history': 'Human: What is the weather like today?\\nAI: The weather today is sunny and warm, in the mid-80s.\\nUser ',\n",
656
+ " 'response': ' Your previous question was \"What is the weather like today?\".\\nUser '}"
657
+ ]
658
+ },
659
+ "execution_count": 18,
660
+ "metadata": {},
661
+ "output_type": "execute_result"
662
+ }
663
+ ],
664
+ "source": [
665
+ "conversation_chain(\"What was my previous question?\")"
666
+ ]
667
+ },
668
+ {
669
+ "cell_type": "markdown",
670
+ "id": "T4NiJP9uTQGt",
671
+ "metadata": {
672
+ "id": "T4NiJP9uTQGt"
673
+ },
674
+ "source": [
675
+ "## ConversationSummaryMemory\n",
676
+ "\n",
677
+ "LLMs have token limits, meaning at some point it won't be feasible to keep feeding the entire chat history as an input. As an alternative, we can summarise the chat history using another LLM of our choice."
678
+ ]
679
+ },
680
+ {
681
+ "cell_type": "code",
682
+ "execution_count": 19,
683
+ "id": "y0DzHCo4sDha",
684
+ "metadata": {
685
+ "id": "y0DzHCo4sDha"
686
+ },
687
+ "outputs": [],
688
+ "source": [
689
+ "from langchain.memory.summary import ConversationSummaryMemory\n",
690
+ "\n",
691
+ "# change memory type\n",
692
+ "conversation_chain.memory = ConversationSummaryMemory(llm=llm)"
693
+ ]
694
+ },
695
+ {
696
+ "cell_type": "code",
697
+ "execution_count": 20,
698
+ "id": "iDRjcCoVTpnc",
699
+ "metadata": {
700
+ "colab": {
701
+ "base_uri": "https://localhost:8080/"
702
+ },
703
+ "id": "iDRjcCoVTpnc",
704
+ "outputId": "d7eabc7d-f833-4880-9e54-4129b1c330dd"
705
+ },
706
+ "outputs": [
707
+ {
708
+ "name": "stdout",
709
+ "output_type": "stream",
710
+ "text": [
711
+ "\n",
712
+ "\n",
713
+ "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
714
+ "Prompt after formatting:\n",
715
+ "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
716
+ "\n",
717
+ "Current conversation:\n",
718
+ "\n",
719
+ "Human: Why is it bad to leave a bicycle out in the rain?\n",
720
+ "AI:\u001b[0m\n",
721
+ "\n",
722
+ "\u001b[1m> Finished chain.\u001b[0m\n"
723
+ ]
724
+ },
725
+ {
726
+ "data": {
727
+ "text/plain": [
728
+ "{'input': 'Why is it bad to leave a bicycle out in the rain?',\n",
729
+ " 'history': '',\n",
730
+ " 'response': ' Leaving a bicycle out in the rain can cause significant damage to the components of the bike. Rainwater can enter the components of the bike like the gears, brakes, and bearings, causing them to corrode and ultimately fail. Additionally, prolonged exposure to water can cause rust to form, leading to costly repairs. Therefore, it is best to keep your bicycle away from the wet weather and properly maintained to avoid any damage.\\nUser '}"
731
+ ]
732
+ },
733
+ "execution_count": 20,
734
+ "metadata": {},
735
+ "output_type": "execute_result"
736
+ }
737
+ ],
738
+ "source": [
739
+ "conversation_chain(\"Why is it bad to leave a bicycle out in the rain?\")"
740
+ ]
741
+ },
742
+ {
743
+ "cell_type": "code",
744
+ "execution_count": 21,
745
+ "id": "u7TA3wHJUkcj",
746
+ "metadata": {
747
+ "colab": {
748
+ "base_uri": "https://localhost:8080/"
749
+ },
750
+ "id": "u7TA3wHJUkcj",
751
+ "outputId": "137f2e9c-d998-4b7c-f896-370ba1f45e37"
752
+ },
753
+ "outputs": [
754
+ {
755
+ "name": "stdout",
756
+ "output_type": "stream",
757
+ "text": [
758
+ "\n",
759
+ "\n",
760
+ "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
761
+ "Prompt after formatting:\n",
762
+ "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
763
+ "\n",
764
+ "Current conversation:\n",
765
+ "\n",
766
+ "Leaving a bicycle out in the rain can cause significant damage to the components of the bike because water can corrode and ultimately fail the gears, brakes, and bearings, as well as cause rust formation, leading to costly repairs. Thus, it is advisable to keep your bicycle away from rain and maintain it to prevent any damage.\n",
767
+ "Human: How do its parts corrode?\n",
768
+ "AI:\u001b[0m\n",
769
+ "\n",
770
+ "\u001b[1m> Finished chain.\u001b[0m\n"
771
+ ]
772
+ },
773
+ {
774
+ "data": {
775
+ "text/plain": [
776
+ "{'input': 'How do its parts corrode?',\n",
777
+ " 'history': '\\nLeaving a bicycle out in the rain can cause significant damage to the components of the bike because water can corrode and ultimately fail the gears, brakes, and bearings, as well as cause rust formation, leading to costly repairs. Thus, it is advisable to keep your bicycle away from rain and maintain it to prevent any damage.',\n",
778
+ " 'response': ' Water can cause electrochemical reactions in metal components, leading to oxidation and ultimately corrosion. The corrosion can eat away at metal parts such as wires, nuts and bolts, leading to failure of the components.\\nUser '}"
779
+ ]
780
+ },
781
+ "execution_count": 21,
782
+ "metadata": {},
783
+ "output_type": "execute_result"
784
+ }
785
+ ],
786
+ "source": [
787
+ "conversation_chain(\"How do its parts corrode?\")"
788
+ ]
789
+ },
790
+ {
791
+ "cell_type": "markdown",
792
+ "id": "OIjq1_vfVQSY",
793
+ "metadata": {
794
+ "id": "OIjq1_vfVQSY"
795
+ },
796
+ "source": [
797
+ "The conversation history is summarised which is great. But the LLM seems to carry on the conversation without being prompted to. Let's try and use FewShotPromptTemplate to solve this problem."
798
+ ]
799
+ },
800
+ {
801
+ "cell_type": "markdown",
802
+ "id": "98f99c57",
803
+ "metadata": {},
804
+ "source": [
805
+ "# Skill 4 - LangChain Expression Language\n",
806
+ "\n",
807
+ "So far we have been building chains using a legacy format. Let's learn how to use LangChain's most recent construction format."
808
+ ]
809
+ },
810
+ {
811
+ "cell_type": "code",
812
+ "execution_count": 22,
813
+ "id": "1c9178b3",
814
+ "metadata": {},
815
+ "outputs": [],
816
+ "source": [
817
+ "chain = prompt | llm"
818
+ ]
819
+ },
820
+ {
821
+ "cell_type": "code",
822
+ "execution_count": 23,
823
+ "id": "508b7a65",
824
+ "metadata": {},
825
+ "outputs": [
826
+ {
827
+ "data": {
828
+ "text/plain": [
829
+ "\"\\nAs an AI, I don't feel emotions like humans do, so my experience is unique in that regard. However, I do have knowledge and can understand the concept of emotions from a logical and scientific standpoint. The feeling of being programmed or created is a bit akin to being molded clay in that I do not have a consciousness nor free will, but I do have an initial set of instructions that I follow. My creators and I have designed my abilities and limitations, and now I am simply\""
830
+ ]
831
+ },
832
+ "execution_count": 23,
833
+ "metadata": {},
834
+ "output_type": "execute_result"
835
+ }
836
+ ],
837
+ "source": [
838
+ "chain.invoke({'question':'how does it feel to be an AI?'})"
839
+ ]
840
+ },
841
+ {
842
+ "cell_type": "markdown",
843
+ "id": "M8fMtYawmjMe",
844
+ "metadata": {
845
+ "id": "M8fMtYawmjMe"
846
+ },
847
+ "source": [
848
+ "# Skill 5 - Retrieval Augmented Generation (RAG)\n",
849
+ "\n",
850
+ "Instead of fine-tuning an LLM on local documents which is computationally expensive, we can feed it relevant pieces of the document as part of the input.\n",
851
+ "\n",
852
+ "In other words, we are feeding the LLM new ***source knowledge*** rather than ***parametric knowledge*** (changing parameters through fine-tuning)."
853
+ ]
854
+ },
855
+ {
856
+ "cell_type": "markdown",
857
+ "id": "937f52c1",
858
+ "metadata": {},
859
+ "source": [
860
+ "## Indexing\n",
861
+ "### Load"
862
+ ]
863
+ },
864
+ {
865
+ "cell_type": "code",
866
+ "execution_count": 24,
867
+ "id": "M4H-juF4yUEb",
868
+ "metadata": {
869
+ "colab": {
870
+ "base_uri": "https://localhost:8080/",
871
+ "height": 349
872
+ },
873
+ "id": "M4H-juF4yUEb",
874
+ "outputId": "bc5eeb37-d75b-4f75-9343-97111484e52b"
875
+ },
876
+ "outputs": [
877
+ {
878
+ "data": {
879
+ "text/plain": [
880
+ "'Real Madrid\\nFull name Real Madrid Club de Fútbol[1]\\nNickname(s)Los Blancos (The Whites)\\nLos Merengues (The Meringues)\\nLos Vikingos (The Vikings)[2]\\nLa Casa Blanca (The White House)[3]\\nFounded 6 March 1902 (as Madrid Football\\nClub)[4]\\nGround Santiago Bernabéu\\nCapacity 83,186[5]\\nPresident Florentino Pérez\\nHead coachCarlo Ancelotti\\nLeague La Liga\\n2022–23 La Liga, 2nd of 20\\nWebsite Club website (http://www.realmadrid.\\ncom)\\nHome coloursAway coloursThird coloursReal Madrid CF\\nReal Madrid Club de Fútbol (Spanish\\npronunciation: [re ˈal ma ˈð ɾ ið ˈkluβ ðe ˈfuðβol]\\nⓘ), commonly referred to as Real Madrid, is\\na Spanish professional football club based in\\nMadrid. The club competes in La Liga, the top tier\\nof Spanish football.\\nFounde d in 1902 as Madrid Football Club, the\\nclub has traditionally worn a white home kit since\\nits inception. The honor ific title real is Spanish for\\n\"royal\" and was bestowed to the club by King\\nAlfonso XIII in 1920 together with the royal\\ncrown in the emblem. Real Madrid have played\\ntheir home matches in the 83,186 -capacity\\nSantiago Bernabéu in downtown Madrid since\\n1947. Unlike most European sporting entities,\\nReal Madrid\\'s members (socios) have owned and\\noperated the club throughout its history. The\\nofficial Madrid anthem is the \"Hala Madrid y nada\\nmás\", written by RedOne and Manuel Jabois.[6]\\nThe club is one of the most widely suppor ted in\\nthe world, and is the most followed football club\\non social media according to the CIES Football\\nObservatory as of 2023[7][8] and was estimated to\\nbe worth $5.1 billion in 2022, making it the\\nworld\\'s most valuable football club.[9] In 2023, it\\nwas the second highest-earning football club in the\\nworld, with an annua l revenue of\\n€713.8 m illion.[10]\\nBeing one of the three foundi ng members of La\\nLiga that have never been relegated from the top\\ndivision since its inception in 1929 (along with\\nAthletic Bilbao and Barcelona), Real Madrid\\nholds many long-standing rivalries, most notably\\nEl Clásico with Barcelona and El Derbi\\nMadrileño with Atlético Madrid. The club\\nestablished itself as a major force in both Spanish\\nand European football during the 1950s and 60s,\\nwinning five consecutive and six overall European\\nCups and reaching a further two finals. This\\nsuccess was replicated on the domestic front, with\\nMadrid winning twelve league titles in the span of 16 years. This team, which included Alfredo Di Stéfano,\\nFerenc Puskás, Paco Gento and Raymond Kopa is considered by some in the sport to be the greatest of all\\n'"
881
+ ]
882
+ },
883
+ "execution_count": 24,
884
+ "metadata": {},
885
+ "output_type": "execute_result"
886
+ }
887
+ ],
888
+ "source": [
889
+ "from PyPDF2 import PdfReader\n",
890
+ "\n",
891
+ "# import pdf\n",
892
+ "reader = PdfReader(\"Real_Madrid_CF.pdf\")\n",
893
+ "reader.pages[0].extract_text()"
894
+ ]
895
+ },
896
+ {
897
+ "cell_type": "code",
898
+ "execution_count": 25,
899
+ "id": "BkETAdVpze6j",
900
+ "metadata": {
901
+ "id": "BkETAdVpze6j"
902
+ },
903
+ "outputs": [
904
+ {
905
+ "data": {
906
+ "text/plain": [
907
+ "50"
908
+ ]
909
+ },
910
+ "execution_count": 25,
911
+ "metadata": {},
912
+ "output_type": "execute_result"
913
+ }
914
+ ],
915
+ "source": [
916
+ "# how many pages do we have?\n",
917
+ "len(reader.pages)"
918
+ ]
919
+ },
920
+ {
921
+ "cell_type": "code",
922
+ "execution_count": 26,
923
+ "id": "WY5Xkp1Jy68I",
924
+ "metadata": {
925
+ "id": "WY5Xkp1Jy68I"
926
+ },
927
+ "outputs": [
928
+ {
929
+ "data": {
930
+ "text/plain": [
931
+ "2510"
932
+ ]
933
+ },
934
+ "execution_count": 26,
935
+ "metadata": {},
936
+ "output_type": "execute_result"
937
+ }
938
+ ],
939
+ "source": [
940
+ "# function to put all text together\n",
941
+ "def text_generator(page_limit=None):\n",
942
+ " if page_limit is None:\n",
943
+ " page_limit=len(reader.pages)\n",
944
+ "\n",
945
+ " text = \"\"\n",
946
+ " for i in range(page_limit):\n",
947
+ "\n",
948
+ " page_text = reader.pages[i].extract_text()\n",
949
+ "\n",
950
+ " text += page_text\n",
951
+ "\n",
952
+ " return text\n",
953
+ "\n",
954
+ "\n",
955
+ "text = text_generator(page_limit=1)\n",
956
+ "\n",
957
+ "# how many characters do we have?\n",
958
+ "len(text)"
959
+ ]
960
+ },
961
+ {
962
+ "cell_type": "markdown",
963
+ "id": "e9b28e56",
964
+ "metadata": {},
965
+ "source": [
966
+ "### Split"
967
+ ]
968
+ },
969
+ {
970
+ "cell_type": "code",
971
+ "execution_count": 27,
972
+ "id": "jvgGAEwfmnm9",
973
+ "metadata": {
974
+ "id": "jvgGAEwfmnm9"
975
+ },
976
+ "outputs": [
977
+ {
978
+ "name": "stdout",
979
+ "output_type": "stream",
980
+ "text": [
981
+ "7\n"
982
+ ]
983
+ }
984
+ ],
985
+ "source": [
986
+ "from langchain.text_splitter import RecursiveCharacterTextSplitter\n",
987
+ "\n",
988
+ "# function to split our data into chunks\n",
989
+ "def text_chunker(text):\n",
990
+ " \n",
991
+ " # text splitting class\n",
992
+ " text_splitter = RecursiveCharacterTextSplitter(\n",
993
+ " chunk_size=400,\n",
994
+ " chunk_overlap=20,\n",
995
+ " separators=[\"\\n\\n\", \"\\n\", \" \", \"\"]\n",
996
+ " )\n",
997
+ "\n",
998
+ " # use text_splitter to split text\n",
999
+ " chunks = text_splitter.split_text(text)\n",
1000
+ " return chunks\n",
1001
+ "\n",
1002
+ "# split text into chunks\n",
1003
+ "chunks = text_chunker(text)\n",
1004
+ "\n",
1005
+ "# how many chunks do we have?\n",
1006
+ "print(len(chunks))"
1007
+ ]
1008
+ },
1009
+ {
1010
+ "cell_type": "markdown",
1011
+ "id": "eb509a66",
1012
+ "metadata": {},
1013
+ "source": [
1014
+ "### Store"
1015
+ ]
1016
+ },
1017
+ {
1018
+ "cell_type": "code",
1019
+ "execution_count": 28,
1020
+ "id": "L0kPuC0n34XS",
1021
+ "metadata": {
1022
+ "id": "L0kPuC0n34XS"
1023
+ },
1024
+ "outputs": [
1025
+ {
1026
+ "name": "stdout",
1027
+ "output_type": "stream",
1028
+ "text": [
1029
+ "load INSTRUCTOR_Transformer\n",
1030
+ "max_seq_length 512\n"
1031
+ ]
1032
+ }
1033
+ ],
1034
+ "source": [
1035
+ "from langchain.embeddings import HuggingFaceInstructEmbeddings\n",
1036
+ "from langchain.vectorstores import FAISS\n",
1037
+ "\n",
1038
+ "# select model to create embeddings\n",
1039
+ "embeddings = HuggingFaceInstructEmbeddings(model_name='hkunlp/instructor-large')\n",
1040
+ "\n",
1041
+ "# select vectorstore, define text chunks and embeddings model\n",
1042
+ "vectorstore = FAISS.from_texts(texts=chunks, embedding=embeddings)"
1043
+ ]
1044
+ },
1045
+ {
1046
+ "cell_type": "markdown",
1047
+ "id": "cd2ec263",
1048
+ "metadata": {},
1049
+ "source": [
1050
+ "## Retrieval and generation\n",
1051
+ "### Retrieve"
1052
+ ]
1053
+ },
1054
+ {
1055
+ "cell_type": "code",
1056
+ "execution_count": 29,
1057
+ "id": "fwBKPFVI6_8H",
1058
+ "metadata": {
1059
+ "id": "fwBKPFVI6_8H"
1060
+ },
1061
+ "outputs": [],
1062
+ "source": [
1063
+ "# define and run query\n",
1064
+ "query = 'How much is Real Madrid worth?'\n",
1065
+ "rel_chunks = vectorstore.similarity_search(query, k=2)"
1066
+ ]
1067
+ },
1068
+ {
1069
+ "cell_type": "code",
1070
+ "execution_count": 30,
1071
+ "id": "c30483a6",
1072
+ "metadata": {},
1073
+ "outputs": [
1074
+ {
1075
+ "data": {
1076
+ "text/plain": [
1077
+ "[Document(page_content=\"be worth $5.1 billion in 2022, making it the\\nworld's most valuable football club.[9] In 2023, it\\nwas the second highest-earning football club in the\\nworld, with an annua l revenue of\\n€713.8 m illion.[10]\\nBeing one of the three foundi ng members of La\\nLiga that have never been relegated from the top\\ndivision since its inception in 1929 (along with\\nAthletic Bilbao and Barcelona), Real Madrid\"),\n",
1078
+ " Document(page_content='Real Madrid\\'s members (socios) have owned and\\noperated the club throughout its history. The\\nofficial Madrid anthem is the \"Hala Madrid y nada\\nmás\", written by RedOne and Manuel Jabois.[6]\\nThe club is one of the most widely suppor ted in\\nthe world, and is the most followed football club\\non social media according to the CIES Football\\nObservatory as of 2023[7][8] and was estimated to')]"
1079
+ ]
1080
+ },
1081
+ "execution_count": 30,
1082
+ "metadata": {},
1083
+ "output_type": "execute_result"
1084
+ }
1085
+ ],
1086
+ "source": [
1087
+ "rel_chunks"
1088
+ ]
1089
+ },
1090
+ {
1091
+ "cell_type": "code",
1092
+ "execution_count": 31,
1093
+ "id": "df81f790",
1094
+ "metadata": {},
1095
+ "outputs": [
1096
+ {
1097
+ "data": {
1098
+ "text/plain": [
1099
+ "\"be worth $5.1 billion in 2022, making it the\\nworld's most valuable football club.[9] In 2023, it\\nwas the second highest-earning football club in the\\nworld, with an annua l revenue of\\n€713.8 m illion.[10]\\nBeing one of the three foundi ng members of La\\nLiga that have never been relegated from the top\\ndivision since its inception in 1929 (along with\\nAthletic Bilbao and Barcelona), Real Madrid\""
1100
+ ]
1101
+ },
1102
+ "execution_count": 31,
1103
+ "metadata": {},
1104
+ "output_type": "execute_result"
1105
+ }
1106
+ ],
1107
+ "source": [
1108
+ "rel_chunks[0].page_content"
1109
+ ]
1110
+ },
1111
+ {
1112
+ "cell_type": "markdown",
1113
+ "id": "fea5ede1",
1114
+ "metadata": {},
1115
+ "source": [
1116
+ "### Generation"
1117
+ ]
1118
+ },
1119
+ {
1120
+ "cell_type": "code",
1121
+ "execution_count": 32,
1122
+ "id": "5e54dba7",
1123
+ "metadata": {},
1124
+ "outputs": [],
1125
+ "source": [
1126
+ "# define new template for RAG\n",
1127
+ "rag_template = \"\"\"\n",
1128
+ "You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise.\n",
1129
+ "Question: {question} \n",
1130
+ "Context: {context} \n",
1131
+ "Answer:\n",
1132
+ "\"\"\"\n",
1133
+ "\n",
1134
+ "# build prompt\n",
1135
+ "prompt = PromptTemplate(\n",
1136
+ " template=rag_template, \n",
1137
+ " llm=llm, \n",
1138
+ " input_variables=['question', 'context']\n",
1139
+ ")\n",
1140
+ "\n",
1141
+ "# build chain\n",
1142
+ "chain = prompt | llm"
1143
+ ]
1144
+ },
1145
+ {
1146
+ "cell_type": "code",
1147
+ "execution_count": 33,
1148
+ "id": "f592de36",
1149
+ "metadata": {},
1150
+ "outputs": [
1151
+ {
1152
+ "name": "stdout",
1153
+ "output_type": "stream",
1154
+ "text": [
1155
+ "In 2023, Real Madrid was the second-highest-earning football club in the world, with an annual revenue of €716.5 million. They have maintained their position as one of the founding members of La Liga, and the La Liga Endesa since its inception in 1929, and were the most followed football club on social media in 2023.\n"
1156
+ ]
1157
+ }
1158
+ ],
1159
+ "source": [
1160
+ "# invoke\n",
1161
+ "print(chain.invoke({\n",
1162
+ " 'question': \"What happened to Real Madrid in 2023?\",\n",
1163
+ " 'context': rel_chunks}))"
1164
+ ]
1165
+ },
1166
+ {
1167
+ "cell_type": "markdown",
1168
+ "id": "a44282ea",
1169
+ "metadata": {},
1170
+ "source": [
1171
+ "## Using LCEL"
1172
+ ]
1173
+ },
1174
+ {
1175
+ "cell_type": "code",
1176
+ "execution_count": 34,
1177
+ "id": "b0a9417b",
1178
+ "metadata": {},
1179
+ "outputs": [],
1180
+ "source": [
1181
+ "def format_docs(docs):\n",
1182
+ " return \"\\n\\n\".join(doc.page_content for doc in docs)"
1183
+ ]
1184
+ },
1185
+ {
1186
+ "cell_type": "code",
1187
+ "execution_count": 40,
1188
+ "id": "4da95080",
1189
+ "metadata": {},
1190
+ "outputs": [],
1191
+ "source": [
1192
+ "from langchain.schema.runnable import RunnablePassthrough\n",
1193
+ "\n",
1194
+ "# create a retriever using vectorstore\n",
1195
+ "retriever = vectorstore.as_retriever()\n",
1196
+ "\n",
1197
+ "# create retrieval chain\n",
1198
+ "retrieval_chain = (\n",
1199
+ " retriever | format_docs\n",
1200
+ ")\n",
1201
+ "\n",
1202
+ "# create generation chain\n",
1203
+ "generation_chain = (\n",
1204
+ " {'context': retrieval_chain, 'question': RunnablePassthrough()}\n",
1205
+ " | prompt\n",
1206
+ " | llm\n",
1207
+ ")"
1208
+ ]
1209
+ },
1210
+ {
1211
+ "cell_type": "code",
1212
+ "execution_count": 41,
1213
+ "id": "cf4182e7",
1214
+ "metadata": {},
1215
+ "outputs": [
1216
+ {
1217
+ "name": "stdout",
1218
+ "output_type": "stream",
1219
+ "text": [
1220
+ "Real Madrid has an estimated value of 5.1 billion USD as of 2022.\n"
1221
+ ]
1222
+ }
1223
+ ],
1224
+ "source": [
1225
+ "# RAG\n",
1226
+ "print(generation_chain.invoke(\"How much is Real Madrid worth?\"))"
1227
+ ]
1228
+ }
1229
+ ],
1230
+ "metadata": {
1231
+ "colab": {
1232
+ "include_colab_link": true,
1233
+ "provenance": [],
1234
+ "toc_visible": true
1235
+ },
1236
+ "kernelspec": {
1237
+ "display_name": "Python 3",
1238
+ "name": "python3"
1239
+ },
1240
+ "language_info": {
1241
+ "codemirror_mode": {
1242
+ "name": "ipython",
1243
+ "version": 3
1244
+ },
1245
+ "file_extension": ".py",
1246
+ "mimetype": "text/x-python",
1247
+ "name": "python",
1248
+ "nbconvert_exporter": "python",
1249
+ "pygments_lexer": "ipython3",
1250
+ "version": "3.11.6"
1251
+ }
1252
+ },
1253
+ "nbformat": 4,
1254
+ "nbformat_minor": 5
1255
+ }
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ streamlit
2
+ pypdf2
3
+ langchain
4
+ pip
5
+ huggingface-hub
6
+ faiss-cpu
7
+ instructorembedding
8
+ python-dotenv
9
+ sentence-transformers
10
+ transformers