Pijush2023 commited on
Commit
b370650
·
verified ·
1 Parent(s): 0f95a25

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +106 -23
app.py CHANGED
@@ -17,7 +17,20 @@ graph = Neo4jGraph(
17
  password="Z10duoPkKCtENuOukw3eIlvl0xJWKtrVSr-_hGX1LQ4"
18
  )
19
 
20
- # Function to clean input for Neo4j full-text query
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  def remove_lucene_chars(input: str) -> str:
22
  return input.translate(str.maketrans({
23
  "\\": r"\\", "+": r"\+", "-": r"\-", "&": r"\&", "|": r"\|", "!": r"\!",
@@ -26,7 +39,6 @@ def remove_lucene_chars(input: str) -> str:
26
  ";": r"\;", " ": r"\ "
27
  }))
28
 
29
- # Function to generate a full-text query
30
  def generate_full_text_query(input: str) -> str:
31
  full_text_query = ""
32
  words = [el for el in remove_lucene_chars(input).split() if el]
@@ -35,29 +47,100 @@ def generate_full_text_query(input: str) -> str:
35
  full_text_query += f" {words[-1]}~2"
36
  return full_text_query.strip()
37
 
38
- # Define the function to query Neo4j and get a response
39
- def get_response(question):
40
- query = generate_full_text_query(question)
41
- try:
42
- # Query the Neo4j database using a full-text search
 
 
43
  response = graph.query(
44
- """
45
- CALL db.index.fulltext.queryNodes('entity', $query)
46
- YIELD node, score
47
- RETURN node.content AS content, score
48
- ORDER BY score DESC LIMIT 1
 
 
 
 
 
 
 
49
  """,
50
- {"query": query}
51
  )
52
- # Extract the content from the top response
53
- if response:
54
- result = response[0]['content']
55
- return result
56
- else:
57
- return "Sorry, I couldn't find any relevant information in the database."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  except Exception as e:
59
- logging.error(f"Error querying Neo4j: {e}")
60
- return "An error occurred while fetching data from the database."
 
61
 
62
  # Function to generate audio with Eleven Labs TTS
63
  def generate_audio_elevenlabs(text):
@@ -131,8 +214,8 @@ def handle_voice_to_voice(audio):
131
 
132
 
133
  # Define the Gradio interface
134
- with gr.Blocks() as demo:
135
- audio_input = gr.Audio(sources=["microphone"], type='numpy', streaming=False, label="Speak to Ask")
136
  submit_voice_btn = gr.Button("Submit Voice")
137
  audio_output = gr.Audio(label="Response Audio", type="filepath", autoplay=True, interactive=False)
138
 
 
17
  password="Z10duoPkKCtENuOukw3eIlvl0xJWKtrVSr-_hGX1LQ4"
18
  )
19
 
20
+ # Define entity extraction and retrieval functions
21
+ class Entities(BaseModel):
22
+ names: List[str] = Field(
23
+ ..., description="All the person, organization, or business entities that appear in the text"
24
+ )
25
+
26
+ entity_prompt = ChatPromptTemplate.from_messages([
27
+ ("system", "You are extracting organization and person entities from the text."),
28
+ ("human", "Use the given format to extract information from the following input: {question}"),
29
+ ])
30
+
31
+ chat_model = ChatOpenAI(temperature=0, model_name="gpt-4o", api_key=os.environ['OPENAI_API_KEY'])
32
+ entity_chain = entity_prompt | chat_model.with_structured_output(Entities)
33
+
34
  def remove_lucene_chars(input: str) -> str:
35
  return input.translate(str.maketrans({
36
  "\\": r"\\", "+": r"\+", "-": r"\-", "&": r"\&", "|": r"\|", "!": r"\!",
 
39
  ";": r"\;", " ": r"\ "
40
  }))
41
 
 
42
  def generate_full_text_query(input: str) -> str:
43
  full_text_query = ""
44
  words = [el for el in remove_lucene_chars(input).split() if el]
 
47
  full_text_query += f" {words[-1]}~2"
48
  return full_text_query.strip()
49
 
50
+ # Setup logging to a file to capture debug information
51
+ logging.basicConfig(filename='neo4j_retrieval.log', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
52
+
53
+ def structured_retriever(question: str) -> str:
54
+ result = ""
55
+ entities = entity_chain.invoke({"question": question})
56
+ for entity in entities.names:
57
  response = graph.query(
58
+ """CALL db.index.fulltext.queryNodes('entity', $query, {limit:2})
59
+ YIELD node,score
60
+ CALL {
61
+ WITH node
62
+ MATCH (node)-[r:!MENTIONS]->(neighbor)
63
+ RETURN node.id + ' - ' + type(r) + ' -> ' + neighbor.id AS output
64
+ UNION ALL
65
+ WITH node
66
+ MATCH (node)<-[r:!MENTIONS]-(neighbor)
67
+ RETURN neighbor.id + ' - ' + type(r) + ' -> ' + node.id AS output
68
+ }
69
+ RETURN output LIMIT 50
70
  """,
71
+ {"query": generate_full_text_query(entity)},
72
  )
73
+ result += "\n".join([el['output'] for el in response])
74
+ return result
75
+
76
+ def retriever_neo4j(question: str):
77
+ structured_data = structured_retriever(question)
78
+ logging.debug(f"Structured data: {structured_data}")
79
+ return structured_data
80
+
81
+ # Setup for condensing the follow-up questions
82
+ _template = """Given the following conversation and a follow-up question, rephrase the follow-up question to be a standalone question,
83
+ in its original language.
84
+ Chat History:
85
+ {chat_history}
86
+ Follow Up Input: {question}
87
+ Standalone question:"""
88
+
89
+ CONDENSE_QUESTION_PROMPT = PromptTemplate.from_template(_template)
90
+
91
+ def _format_chat_history(chat_history: list[tuple[str, str]]) -> list:
92
+ buffer = []
93
+ for human, ai in chat_history:
94
+ buffer.append(HumanMessage(content=human))
95
+ buffer.append(AIMessage(content=ai))
96
+ return buffer
97
+
98
+ _search_query = RunnableBranch(
99
+ (
100
+ RunnableLambda(lambda x: bool(x.get("chat_history"))).with_config(
101
+ run_name="HasChatHistoryCheck"
102
+ ),
103
+ RunnablePassthrough.assign(
104
+ chat_history=lambda x: _format_chat_history(x["chat_history"])
105
+ )
106
+ | CONDENSE_QUESTION_PROMPT
107
+ | ChatOpenAI(temperature=0, api_key=os.environ['OPENAI_API_KEY'])
108
+ | StrOutputParser(),
109
+ ),
110
+ RunnableLambda(lambda x: x["question"]),
111
+ )
112
+
113
+
114
+ template = """I am a guide for Birmingham, Alabama. I can provide recommendations and insights about the city, including events and activities.
115
+ Ask your question directly, and I'll provide a precise and quick,short and crisp response in a conversational way without any Greet.
116
+ {context}
117
+ Question: {question}
118
+ Answer:"""
119
+
120
+
121
+ qa_prompt = ChatPromptTemplate.from_template(template)
122
+
123
+ # Define the chain for Neo4j-based retrieval and response generation
124
+ chain_neo4j = (
125
+ RunnableParallel(
126
+ {
127
+ "context": RunnableLambda(lambda x: retriever_neo4j(x["question"])),
128
+ "question": RunnablePassthrough(),
129
+ }
130
+ )
131
+ | ChatPromptTemplate.from_template("Answer: {context} Question: {question}")
132
+ | chat_model
133
+ | StrOutputParser()
134
+ )
135
+
136
+ # Define the function to query Neo4j and get a response
137
+ def get_response(question):
138
+ try:
139
+ return chain_neo4j.invoke({"question": question})
140
  except Exception as e:
141
+ return f"Error: {str(e)}"
142
+
143
+
144
 
145
  # Function to generate audio with Eleven Labs TTS
146
  def generate_audio_elevenlabs(text):
 
214
 
215
 
216
  # Define the Gradio interface
217
+ with gr.Blocks(theme="rawrsor1/Everforest") as demo:
218
+ audio_input = gr.Audio(sources=["microphone"], type='numpy', streaming=True, label="Speak to Ask")
219
  submit_voice_btn = gr.Button("Submit Voice")
220
  audio_output = gr.Audio(label="Response Audio", type="filepath", autoplay=True, interactive=False)
221