anpigon commited on
Commit
5030f92
β€’
1 Parent(s): 4390612

chore: Add langchain_faiss to git-lfs tracking

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ langchain_faiss/* filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py,cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # poetry
98
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102
+ #poetry.lock
103
+
104
+ # pdm
105
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
106
+ #pdm.lock
107
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
108
+ # in version control.
109
+ # https://pdm.fming.dev/#use-with-ide
110
+ .pdm.toml
111
+
112
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
113
+ __pypackages__/
114
+
115
+ # Celery stuff
116
+ celerybeat-schedule
117
+ celerybeat.pid
118
+
119
+ # SageMath parsed files
120
+ *.sage.py
121
+
122
+ # Environments
123
+ .env
124
+ .venv
125
+ env/
126
+ venv/
127
+ ENV/
128
+ env.bak/
129
+ venv.bak/
130
+
131
+ # Spyder project settings
132
+ .spyderproject
133
+ .spyproject
134
+
135
+ # Rope project settings
136
+ .ropeproject
137
+
138
+ # mkdocs documentation
139
+ /site
140
+
141
+ # mypy
142
+ .mypy_cache/
143
+ .dmypy.json
144
+ dmypy.json
145
+
146
+ # Pyre type checker
147
+ .pyre/
148
+
149
+ # pytype static type analyzer
150
+ .pytype/
151
+
152
+ # Cython debug symbols
153
+ cython_debug/
154
+
155
+ # PyCharm
156
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
157
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
158
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
159
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
160
+ #.idea/
161
+
app.py CHANGED
@@ -1,63 +1,232 @@
 
 
1
  import gradio as gr
2
- from huggingface_hub import InferenceClient
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  """
5
- For more information on `huggingface_hub` Inference API support, please check the docs: https://huggingface.co/docs/huggingface_hub/v0.22.2/en/guides/inference
6
- """
7
- client = InferenceClient("HuggingFaceH4/zephyr-7b-beta")
8
 
9
 
10
- def respond(
11
- message,
12
- history: list[tuple[str, str]],
13
- system_message,
14
- max_tokens,
15
- temperature,
16
- top_p,
17
- ):
18
- messages = [{"role": "system", "content": system_message}]
19
 
20
- for val in history:
21
- if val[0]:
22
- messages.append({"role": "user", "content": val[0]})
23
- if val[1]:
24
- messages.append({"role": "assistant", "content": val[1]})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
- messages.append({"role": "user", "content": message})
 
 
 
 
 
 
27
 
28
- response = ""
29
 
30
- for message in client.chat_completion(
31
- messages,
32
- max_tokens=max_tokens,
33
- stream=True,
34
- temperature=temperature,
35
- top_p=top_p,
36
- ):
37
- token = message.choices[0].delta.content
38
 
39
- response += token
 
 
 
 
 
 
 
40
  yield response
41
 
 
42
  """
43
  For information on how to customize the ChatInterface, peruse the gradio docs: https://www.gradio.app/docs/chatinterface
44
  """
45
  demo = gr.ChatInterface(
46
  respond,
47
- additional_inputs=[
48
- gr.Textbox(value="You are a friendly Chatbot.", label="System message"),
49
- gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
50
- gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
51
- gr.Slider(
52
- minimum=0.1,
53
- maximum=1.0,
54
- value=0.95,
55
- step=0.05,
56
- label="Top-p (nucleus sampling)",
57
- ),
58
- ],
59
  )
60
 
61
 
62
  if __name__ == "__main__":
63
- demo.launch()
 
1
+ import os
2
+
3
  import gradio as gr
4
+ from dotenv import load_dotenv
5
+ from langchain.callbacks.base import BaseCallbackHandler
6
+ from langchain.embeddings import CacheBackedEmbeddings
7
+ from langchain.retrievers import BM25Retriever, EnsembleRetriever
8
+ from langchain.storage import LocalFileStore
9
+ from langchain_anthropic import ChatAnthropic
10
+ from langchain_community.chat_models import ChatOllama
11
+ from langchain_community.document_loaders import NotebookLoader, TextLoader
12
+ from langchain_community.document_loaders.generic import GenericLoader
13
+ from langchain_community.document_loaders.parsers.language.language_parser import (
14
+ LanguageParser,
15
+ )
16
+ from langchain_community.embeddings import HuggingFaceBgeEmbeddings
17
+ from langchain_community.vectorstores import FAISS
18
+ from langchain_core.callbacks.manager import CallbackManager
19
+ from langchain_core.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
20
+ from langchain_core.output_parsers import StrOutputParser
21
+ from langchain_core.prompts import PromptTemplate
22
+ from langchain_core.runnables import ConfigurableField, RunnablePassthrough
23
+ from langchain_google_genai import GoogleGenerativeAI
24
+ from langchain_groq import ChatGroq
25
+ from langchain_openai import ChatOpenAI, OpenAIEmbeddings
26
+ from langchain_text_splitters import Language, RecursiveCharacterTextSplitter
27
 
28
+ # Load environment variables
29
+ load_dotenv()
30
+
31
+ # Repository directories
32
+ repo_root_dir = "./docs/langchain"
33
+ repo_dirs = [
34
+ "libs/core/langchain_core",
35
+ "libs/community/langchain_community",
36
+ "libs/experimental/langchain_experimental",
37
+ "libs/partners",
38
+ "libs/cookbook",
39
+ ]
40
+ repo_dirs = [os.path.join(repo_root_dir, repo) for repo in repo_dirs]
41
+
42
+ # Load Python documents
43
+ py_documents = []
44
+ for path in repo_dirs:
45
+ py_loader = GenericLoader.from_filesystem(
46
+ path,
47
+ glob="**/*",
48
+ suffixes=[".py"],
49
+ parser=LanguageParser(language=Language.PYTHON, parser_threshold=30),
50
+ )
51
+ py_documents.extend(py_loader.load())
52
+ print(f".py 파일의 개수: {len(py_documents)}")
53
+
54
+ # Load Markdown documents
55
+ mdx_documents = []
56
+ for dirpath, _, filenames in os.walk(repo_root_dir):
57
+ for file in filenames:
58
+ if file.endswith(".mdx") and "*venv/" not in dirpath:
59
+ try:
60
+ mdx_loader = TextLoader(os.path.join(dirpath, file), encoding="utf-8")
61
+ mdx_documents.extend(mdx_loader.load())
62
+ except Exception:
63
+ pass
64
+ print(f".mdx 파일의 개수: {len(mdx_documents)}")
65
+
66
+ # Load Jupyter Notebook documents
67
+ ipynb_documents = []
68
+ for dirpath, _, filenames in os.walk(repo_root_dir):
69
+ for file in filenames:
70
+ if file.endswith(".ipynb") and "*venv/" not in dirpath:
71
+ try:
72
+ ipynb_loader = NotebookLoader(
73
+ os.path.join(dirpath, file),
74
+ include_outputs=True,
75
+ max_output_length=20,
76
+ remove_newline=True,
77
+ )
78
+ ipynb_documents.extend(ipynb_loader.load())
79
+ except Exception:
80
+ pass
81
+ print(f".ipynb 파일의 개수: {len(ipynb_documents)}")
82
+
83
+
84
+ # Split documents into chunks
85
+ def split_documents(documents, language, chunk_size=2000, chunk_overlap=200):
86
+ splitter = RecursiveCharacterTextSplitter.from_language(
87
+ language=language, chunk_size=chunk_size, chunk_overlap=chunk_overlap
88
+ )
89
+ return splitter.split_documents(documents)
90
+
91
+
92
+ py_docs = split_documents(py_documents, Language.PYTHON)
93
+ mdx_docs = split_documents(mdx_documents, Language.MARKDOWN)
94
+ ipynb_docs = split_documents(ipynb_documents, Language.PYTHON)
95
+
96
+ print(f"λΆ„ν• λœ .py 파일의 개수: {len(py_docs)}")
97
+ print(f"λΆ„ν• λœ .mdx 파일의 개수: {len(mdx_docs)}")
98
+ print(f"λΆ„ν• λœ .ipynb 파일의 개수: {len(ipynb_docs)}")
99
+
100
+ combined_documents = py_docs + mdx_docs + ipynb_docs
101
+ print(f"총 λ„νλ¨ΌνŠΈ 개수: {len(combined_documents)}")
102
+
103
+ # Initialize embeddings and cache
104
+ store = LocalFileStore("~/.cache/embedding")
105
+ embeddings = HuggingFaceBgeEmbeddings(
106
+ model_name="BAAI/bge-m3",
107
+ model_kwargs={"device": "mps"},
108
+ encode_kwargs={"normalize_embeddings": True},
109
+ )
110
+ cached_embeddings = CacheBackedEmbeddings.from_bytes_store(
111
+ embeddings, store, namespace=embeddings.model_name
112
+ )
113
+
114
+ # Create and save FAISS index
115
+ FAISS_DB_INDEX = "./langchain_faiss"
116
+ # db = FAISS.from_documents(combined_documents, cached_embeddings)
117
+ # db.save_local(folder_path=FAISS_DB_INDEX)
118
+ db = FAISS.load_local(
119
+ FAISS_DB_INDEX, cached_embeddings, allow_dangerous_deserialization=True
120
+ )
121
+
122
+ # Create retrievers
123
+ faiss_retriever = db.as_retriever(search_type="mmr", search_kwargs={"k": 10})
124
+ bm25_retriever = BM25Retriever.from_documents(combined_documents)
125
+ bm25_retriever.k = 10
126
+ ensemble_retriever = EnsembleRetriever(
127
+ retrievers=[bm25_retriever, faiss_retriever], weights=[0.5, 0.5], search_type="mmr"
128
+ )
129
+
130
+ # Create prompt template
131
+ prompt = PromptTemplate.from_template(
132
+ """당신은 20λ…„μ°¨ AI κ°œλ°œμžμž…λ‹ˆλ‹€. λ‹Ήμ‹ μ˜ μž„λ¬΄λŠ” 주어진 μ§ˆλ¬Έμ— λŒ€ν•˜μ—¬ μ΅œλŒ€ν•œ λ¬Έμ„œμ˜ 정보λ₯Ό ν™œμš©ν•˜μ—¬ λ‹΅λ³€ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.
133
+ λ¬Έμ„œλŠ” Python μ½”λ“œμ— λŒ€ν•œ 정보λ₯Ό λ‹΄κ³  μžˆμŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ, 닡변을 μž‘μ„±ν•  λ•Œμ—λŠ” Python μ½”λ“œμ— λŒ€ν•œ μƒμ„Έν•œ code snippet을 ν¬ν•¨ν•˜μ—¬ μž‘μ„±ν•΄μ£Όμ„Έμš”.
134
+ μ΅œλŒ€ν•œ μžμ„Έν•˜κ²Œ λ‹΅λ³€ν•˜κ³ , ν•œκΈ€λ‘œ λ‹΅λ³€ν•΄ μ£Όμ„Έμš”. 주어진 λ¬Έμ„œμ—μ„œ 닡변을 찾을 수 μ—†λŠ” 경우, "λ¬Έμ„œμ— 닡변이 μ—†μŠ΅λ‹ˆλ‹€."라고 λ‹΅λ³€ν•΄ μ£Όμ„Έμš”.
135
+ 닡변은 좜처(source)λ₯Ό λ°˜λ“œμ‹œ ν‘œκΈ°ν•΄ μ£Όμ„Έμš”.
136
+
137
+ #μ°Έκ³ λ¬Έμ„œ:
138
+ {context}
139
+
140
+ #질문:
141
+ {question}
142
+
143
+ #λ‹΅λ³€:
144
+
145
+ 좜처:
146
+ - source1
147
+ - source2
148
+ - ...
149
  """
150
+ )
 
 
151
 
152
 
153
+ # Define callback handler for streaming
154
+ class StreamCallback(BaseCallbackHandler):
155
+ def on_llm_new_token(self, token: str, **kwargs):
156
+ print(token, end="", flush=True)
157
+
 
 
 
 
158
 
159
+ # Initialize LLMs with configuration
160
+ llm = ChatOpenAI(
161
+ model="gpt-4o",
162
+ temperature=0,
163
+ streaming=True,
164
+ callbacks=[StreamCallback()],
165
+ ).configurable_alternatives(
166
+ ConfigurableField(id="llm"),
167
+ default_key="gpt4",
168
+ claude=ChatAnthropic(
169
+ model="claude-3-opus-20240229",
170
+ temperature=0,
171
+ streaming=True,
172
+ callbacks=[StreamCallback()],
173
+ ),
174
+ gpt3=ChatOpenAI(
175
+ model="gpt-3.5-turbo",
176
+ temperature=0,
177
+ streaming=True,
178
+ callbacks=[StreamCallback()],
179
+ ),
180
+ gemini=GoogleGenerativeAI(
181
+ model="gemini-1.5-flash",
182
+ temperature=0,
183
+ streaming=True,
184
+ callbacks=[StreamCallback()],
185
+ ),
186
+ llama3=ChatGroq(
187
+ model_name="llama3-70b-8192",
188
+ temperature=0,
189
+ streaming=True,
190
+ callbacks=[StreamCallback()],
191
+ ),
192
+ ollama=ChatOllama(
193
+ model="EEVE-Korean-10.8B:long",
194
+ callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]),
195
+ ),
196
+ )
197
 
198
+ # Create retrieval-augmented generation chain
199
+ rag_chain = (
200
+ {"context": ensemble_retriever, "question": RunnablePassthrough()}
201
+ | prompt
202
+ | llm
203
+ | StrOutputParser()
204
+ )
205
 
 
206
 
207
+ model_key = os.getenv("LLM_MODEL", "gpt4")
208
+ print("model", model_key)
 
 
 
 
 
 
209
 
210
+
211
+ def respond(
212
+ message,
213
+ history: list[tuple[str, str]],
214
+ ):
215
+ response = ""
216
+ for chunk in rag_chain.with_config(configurable={"llm": model_key}).stream(message):
217
+ response += chunk
218
  yield response
219
 
220
+
221
  """
222
  For information on how to customize the ChatInterface, peruse the gradio docs: https://www.gradio.app/docs/chatinterface
223
  """
224
  demo = gr.ChatInterface(
225
  respond,
226
+ title="λž­μ²΄μΈμ— λŒ€ν•΄μ„œ λ¬Όμ–΄λ³΄μ„Έμš”!",
227
+ description="μ•ˆλ…•ν•˜μ„Έμš”!\nμ €λŠ” λž­μ²΄μΈμ— λŒ€ν•œ 인곡지λŠ₯ QAλ΄‡μž…λ‹ˆλ‹€. λž­μ²΄μΈμ— λŒ€ν•΄ κΉŠμ€ 지식을 가지고 μžˆμ–΄μš”. 랭체인 κ°œλ°œμ— κ΄€ν•œ 도움이 ν•„μš”ν•˜μ‹œλ©΄ μ–Έμ œλ“ μ§€ μ§ˆλ¬Έν•΄μ£Όμ„Έμš”!",
 
 
 
 
 
 
 
 
 
 
228
  )
229
 
230
 
231
  if __name__ == "__main__":
232
+ demo.launch()
langchain_faiss/index.faiss ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f50b9cdc2968dd1fe5875e7e1f8ed2689a3e938d505a0e2f06b5257083339bd2
3
+ size 2621485
langchain_faiss/index.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ba84841f2d61493243e47d654cff88c8864c5fa6119469b7569677e4f82f3c5f
3
+ size 862597
requirements.txt CHANGED
@@ -1 +1,12 @@
1
- huggingface_hub==0.22.2
 
 
 
 
 
 
 
 
 
 
 
 
1
+ huggingface_hub==0.22.2
2
+ faiss-cpu
3
+ transformers
4
+ python-dotenv
5
+ langchain
6
+ langchain-anthropic
7
+ langchain-community
8
+ langchain-core
9
+ langchain-google-genai
10
+ langchain-groq
11
+ langchain-openai
12
+ langchain-text-splitters