kcheng0816 commited on
Commit
ffbd97d
·
1 Parent(s): ce282d0

Update app.py

Browse files
Files changed (2) hide show
  1. README.md +15 -12
  2. app.py +16 -23
README.md CHANGED
@@ -1,12 +1,15 @@
1
- ---
2
- title: BibleStudy
3
- emoji: 💻
4
- colorFrom: yellow
5
- colorTo: pink
6
- sdk: docker
7
- pinned: false
8
- license: openrail++
9
- short_description: 'Bible Study on the book of Genesis '
10
- ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
1
+ ## <h1 align="center" id="heading">An Agentic Bible Study Tool Built with LangChain and LangGraph</h1>
2
+
3
+ Create an intelligent Bible study assistant that utilizes LLMs to enhance contextual understanding of scripture. This tool will enable users to pose questions, and the AI will provide answers grounded in the Bible, by accurately identifying and synthesizing information from relevant verses, chapters, and cross-references, promoting deeper comprehension and reducing misinterpretations.
4
+
5
+
6
+ ### Phase I
7
+ - Book of Genesis
8
+ - Examples of questions:
9
+ - How did GOD create the whole universe based on Genesis?
10
+ - Why LORD God make man leave garden?
11
+ - How did the Israelites, led by Jacob, end up in Egypt, and what role did Joseph play in their settlement there?
12
+
13
+
14
+ ## Ship 🚢
15
+ Check out the prototype at https://huggingface.co/spaces/kcheng0816/BibleStudy
app.py CHANGED
@@ -1,10 +1,10 @@
1
  import os
2
  from dotenv import load_dotenv
3
- from chainlit.types import AskFileResponse
4
  import chainlit as cl
5
 
6
  import pandas as pd
7
  from langchain_community.vectorstores import FAISS
 
8
  from langchain_core.documents import Document
9
  from langchain_community.document_loaders import DirectoryLoader
10
  from langchain_community.document_loaders import BSHTMLLoader
@@ -25,7 +25,10 @@ from langchain_core.documents import Document
25
  from langchain_core.messages import HumanMessage
26
  from langchain_core.tools import tool
27
  from langgraph.prebuilt import ToolNode
28
-
 
 
 
29
 
30
  #Load API Keys
31
  load_dotenv()
@@ -35,7 +38,7 @@ path = "data/"
35
  loader = DirectoryLoader(path, glob="*.html")
36
  docs = loader.load()
37
 
38
- #Building RAG Graph with LangGraph
39
  text_splitter = RecursiveCharacterTextSplitter(
40
  chunk_size = 750,
41
  chunk_overlap = 100
@@ -43,9 +46,11 @@ text_splitter = RecursiveCharacterTextSplitter(
43
 
44
  split_documents = text_splitter.split_documents(docs)
45
  len(split_documents)
 
46
  #fine tuned embedding model
47
  huggingface_embeddings = HuggingFaceEmbeddings(model_name="kcheng0816/finetuned_arctic_genesis")
48
 
 
49
  client = QdrantClient(":memory:")
50
  client.create_collection(
51
  collection_name="genesis_bible",
@@ -59,6 +64,7 @@ vector_store = QdrantVectorStore(
59
  )
60
 
61
  _ = vector_store.add_documents(documents=split_documents)
 
62
  #Retrieve
63
  retriever = vector_store.as_retriever(search_kwargs={"k": 5})
64
 
@@ -71,7 +77,7 @@ def retrieve_adjusted(state):
71
  retrieved_docs = compression_retriever.invoke(state["question"])
72
  return {"context" : retrieved_docs}
73
 
74
-
75
  RAG_PROMPT = """\
76
  You are a helpful assistant who answers questions based on provided context. You must only use the provided context, and cannot use your own knowledge.
77
 
@@ -84,7 +90,7 @@ You are a helpful assistant who answers questions based on provided context. You
84
  rag_prompt = ChatPromptTemplate.from_template(RAG_PROMPT)
85
 
86
 
87
- #llm
88
  rate_limiter = InMemoryRateLimiter(
89
  requests_per_second=1, # <-- make a request once every 1 seconds!!
90
  check_every_n_seconds=0.1, # Wake up every 100 ms to check whether allowed to make a request,
@@ -99,9 +105,7 @@ def generate(state):
99
  response = llm.invoke(messages)
100
  return {"response" : response.content}
101
 
102
-
103
-
104
-
105
  class State(TypedDict):
106
  question: str
107
  context: List[Document]
@@ -112,8 +116,6 @@ graph_builder.add_edge(START, "retrieve_adjusted")
112
  graph = graph_builder.compile()
113
 
114
 
115
-
116
-
117
  @tool
118
  def ai_rag_tool(question: str) -> str:
119
  """Useful for when you need to answer questions about Bible """
@@ -127,24 +129,18 @@ tool_belt = [
127
  ai_rag_tool
128
  ]
129
 
130
-
131
  llm = init_chat_model("gpt-4o", temperature=0, rate_limiter=rate_limiter)
132
  llm_with_tools = llm.bind_tools(tool_belt)
133
 
134
 
135
- from langgraph.graph import END
136
- from langchain_core.messages import AnyMessage
137
- from langgraph.graph.message import add_messages
138
- from typing import TypedDict, Annotated
139
- from langchain_core.documents import Document
140
-
141
 
 
142
  class AgentState(TypedDict):
143
  messages: Annotated[list[AnyMessage], add_messages]
144
  context:List[Document]
145
 
146
 
147
-
148
  def call_mode(state):
149
  messages = state["messages"]
150
  response = llm_with_tools.invoke(messages)
@@ -164,7 +160,6 @@ def should_continue(state):
164
  return END
165
 
166
 
167
- #
168
  uncompiled_graph = StateGraph(AgentState)
169
 
170
  uncompiled_graph.add_node("agent", call_mode)
@@ -179,13 +174,11 @@ uncompiled_graph.add_conditional_edges(
179
 
180
  uncompiled_graph.add_edge("action", "agent")
181
 
182
- # Compile and display the graph for a visual overview
183
  compiled_graph = uncompiled_graph.compile()
184
 
185
 
186
-
187
-
188
-
189
  @cl.on_chat_start
190
  async def on_chat_start():
191
  cl.user_session.set("graph", compiled_graph)
 
1
  import os
2
  from dotenv import load_dotenv
 
3
  import chainlit as cl
4
 
5
  import pandas as pd
6
  from langchain_community.vectorstores import FAISS
7
+ from langchain_openai.embeddings import OpenAIEmbeddings
8
  from langchain_core.documents import Document
9
  from langchain_community.document_loaders import DirectoryLoader
10
  from langchain_community.document_loaders import BSHTMLLoader
 
25
  from langchain_core.messages import HumanMessage
26
  from langchain_core.tools import tool
27
  from langgraph.prebuilt import ToolNode
28
+ from langchain_core.messages import AnyMessage
29
+ from langgraph.graph.message import add_messages
30
+ from typing import TypedDict, Annotated
31
+ from langchain_core.documents import Document
32
 
33
  #Load API Keys
34
  load_dotenv()
 
38
  loader = DirectoryLoader(path, glob="*.html")
39
  docs = loader.load()
40
 
41
+ #Text Splitter
42
  text_splitter = RecursiveCharacterTextSplitter(
43
  chunk_size = 750,
44
  chunk_overlap = 100
 
46
 
47
  split_documents = text_splitter.split_documents(docs)
48
  len(split_documents)
49
+
50
  #fine tuned embedding model
51
  huggingface_embeddings = HuggingFaceEmbeddings(model_name="kcheng0816/finetuned_arctic_genesis")
52
 
53
+ #vector datastore
54
  client = QdrantClient(":memory:")
55
  client.create_collection(
56
  collection_name="genesis_bible",
 
64
  )
65
 
66
  _ = vector_store.add_documents(documents=split_documents)
67
+
68
  #Retrieve
69
  retriever = vector_store.as_retriever(search_kwargs={"k": 5})
70
 
 
77
  retrieved_docs = compression_retriever.invoke(state["question"])
78
  return {"context" : retrieved_docs}
79
 
80
+ #RAG prompt
81
  RAG_PROMPT = """\
82
  You are a helpful assistant who answers questions based on provided context. You must only use the provided context, and cannot use your own knowledge.
83
 
 
90
  rag_prompt = ChatPromptTemplate.from_template(RAG_PROMPT)
91
 
92
 
93
+ #llm for RAG
94
  rate_limiter = InMemoryRateLimiter(
95
  requests_per_second=1, # <-- make a request once every 1 seconds!!
96
  check_every_n_seconds=0.1, # Wake up every 100 ms to check whether allowed to make a request,
 
105
  response = llm.invoke(messages)
106
  return {"response" : response.content}
107
 
108
+ #Build RAG graph
 
 
109
  class State(TypedDict):
110
  question: str
111
  context: List[Document]
 
116
  graph = graph_builder.compile()
117
 
118
 
 
 
119
  @tool
120
  def ai_rag_tool(question: str) -> str:
121
  """Useful for when you need to answer questions about Bible """
 
129
  ai_rag_tool
130
  ]
131
 
132
+ #llm for agent reasoning
133
  llm = init_chat_model("gpt-4o", temperature=0, rate_limiter=rate_limiter)
134
  llm_with_tools = llm.bind_tools(tool_belt)
135
 
136
 
 
 
 
 
 
 
137
 
138
+ #Build an agent graph
139
  class AgentState(TypedDict):
140
  messages: Annotated[list[AnyMessage], add_messages]
141
  context:List[Document]
142
 
143
 
 
144
  def call_mode(state):
145
  messages = state["messages"]
146
  response = llm_with_tools.invoke(messages)
 
160
  return END
161
 
162
 
 
163
  uncompiled_graph = StateGraph(AgentState)
164
 
165
  uncompiled_graph.add_node("agent", call_mode)
 
174
 
175
  uncompiled_graph.add_edge("action", "agent")
176
 
177
+ # Compile the graph.
178
  compiled_graph = uncompiled_graph.compile()
179
 
180
 
181
+ #user interface
 
 
182
  @cl.on_chat_start
183
  async def on_chat_start():
184
  cl.user_session.set("graph", compiled_graph)