davidfearne commited on
Commit
2c0bc7b
·
verified ·
1 Parent(s): 4c2934b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +130 -45
app.py CHANGED
@@ -8,7 +8,11 @@ from datetime import date, datetime
8
  import requests
9
  from pydantic import BaseModel, Field
10
  from typing import Optional
11
- from
 
 
 
 
12
 
13
  placeHolderPersona1 = """
14
  ##Mission
@@ -37,6 +41,102 @@ class ChatRequestClient(BaseModel):
37
  tokens2: int
38
  temperature2: float
39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  def call_chat_api(data: ChatRequestClient):
41
  url = "https://agent-builder-api.greensea-b20be511.northeurope.azurecontainerapps.io/chat/"
42
  # Validate and convert the data to a dictionary
@@ -46,24 +146,18 @@ def call_chat_api(data: ChatRequestClient):
46
  response = requests.post(url, json=validated_data)
47
 
48
  if response.status_code == 200:
49
- return response.json() # Return the JSON response if successful
 
 
 
50
  else:
51
  return "An error occured" # Return the raw response text if not successful
52
 
53
- def genuuid ():
54
- return uuid.uuid4()
55
-
56
- def format_elapsed_time(time):
57
- # Format the elapsed time to two decimal places
58
- return "{:.2f}".format(time)
59
 
60
- def search_knowledgebase(query)
61
- return results
62
-
63
 
64
  # Title of the application
65
  # st.image('agentBuilderLogo.png')
66
- st.title('RAG Query Designer')
67
 
68
  # Sidebar for inputting personas
69
  st.sidebar.image('cognizant_logo.jpg')
@@ -78,19 +172,8 @@ llm1 = st.sidebar.selectbox("Model Selection", ['GPT-4', 'GPT3.5'], key='persona
78
  temp1 = st.sidebar.slider("Temperature", min_value=0.0, max_value=1.0, step=0.1, value=0.6, key='persona1_temp')
79
  tokens1 = st.sidebar.slider("Tokens", min_value=0, max_value=4000, step=100, value=500, key='persona1_tokens')
80
 
81
- # # Persona 2
82
- # st.sidebar.subheader("Recommendation and Next Best Action AI")
83
- # persona2SystemMessage = st.sidebar.text_area("Define Recommendation Persona", value=placeHolderPersona2, height=300)
84
- # with st.sidebar.expander("See explanation"):
85
- # st.write("This AI persona uses the output of the symptom intake AI as its input. This AI’s job is to augment a health professional by assisting with a diagnosis and possible next best action. The teams will need to determine if this should be a tool used directly by the patient, as an assistant to the health professional or a hybrid of the two. ")
86
- # st.image("agentPersona2.png")
87
- # llm2 = st.sidebar.selectbox("Model Selection", ['GPT-4', 'GPT3.5'], key='persona2_size')
88
- # temp2 = st.sidebar.slider("Temperature", min_value=0.0, max_value=1.0, step=0.1, value=0.5, key='persona2_temp')
89
- # tokens2 = st.sidebar.slider("Tokens", min_value=0, max_value=4000, step=100, value=500, key='persona2_tokens')
90
- # userMessage2 = st.sidebar.text_area("Define User Message", value="This is the conversation todate, ", height=150)
91
  st.sidebar.caption(f"Session ID: {genuuid()}")
92
 
93
-
94
  # Main chat interface
95
  st.markdown("""#### Query Translation in RAG Architecture
96
 
@@ -103,6 +186,9 @@ Query translation in a Retrieval-Augmented Generation (RAG) architecture is the
103
  2. **Converts to Concise Query**
104
  The LLM reformulates the input into a succinct and effective query optimized for the retrieval system's semantic search capabilities.
105
 
 
 
 
106
  ##### Purpose
107
  This ensures that the retrieval system receives a clear and focused query, increasing the relevance of the information it retrieves. The query translator acts as a bridge between human conversational language and the technical requirements of a semantic retrieval system.""")
108
  # User ID Input
@@ -116,20 +202,13 @@ else:
116
  if "messages" not in st.session_state:
117
  st.session_state.messages = []
118
 
119
- # Display chat messages from history on app rerun
120
- for message in st.session_state.messages:
121
- with st.chat_message(message["role"]):
122
- st.markdown(message["content"])
123
 
124
- # Collect user input
125
  if user_input := st.chat_input("Start chat:"):
126
- # Add user message to the chat history
127
  st.session_state.messages.append({"role": "user", "content": user_input})
128
- st.chat_message("user").markdown(user_input)
129
-
130
- # Prepare data for API call
131
  data = ChatRequestClient(
132
- user_id=user_id, # Ensure user_id is passed correctly
133
  user_input=user_input,
134
  numberOfQuestions=1000,
135
  welcomeMessage="",
@@ -144,21 +223,27 @@ else:
144
  temperature2=0.2
145
  )
146
 
147
- # Call the API
148
- response = call_chat_api(data)
149
-
150
- # Process the API response
151
  agent_message = response.get("content", "No response received from the agent.")
152
  elapsed_time = response.get("elapsed_time", 0)
153
- count = response.get("count", 0)
154
-
155
- # Add agent response to the chat history
156
  st.session_state.messages.append({"role": "assistant", "content": agent_message})
157
- with st.chat_message("assistant"):
158
- st.markdown(agent_message)
159
 
160
- # Display additional metadata
161
- st.caption(f"##### Time taken: {format_elapsed_time(elapsed_time)} seconds")
162
- # st.caption(f"##### Question Count: {count} of {numberOfQuestions}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
 
164
 
 
8
  import requests
9
  from pydantic import BaseModel, Field
10
  from typing import Optional
11
+ from retriver import retriever
12
+ import pandas as pd
13
+ import os
14
+
15
+ df_chunks = pd.read_pickle('Chunks_Complete.pkl')
16
 
17
  placeHolderPersona1 = """
18
  ##Mission
 
41
  tokens2: int
42
  temperature2: float
43
 
44
+
45
+ def genuuid ():
46
+ return uuid.uuid4()
47
+
48
+ def format_elapsed_time(time):
49
+ # Format the elapsed time to two decimal places
50
+ return "{:.2f}".format(time)
51
+
52
+ def search_knowledgebase(query):
53
+ results = retriever(query)
54
+ return results
55
+
56
+ def process_search_results(search_results):
57
+ """
58
+ Processes search results to extract and organize metadata and other details.
59
+
60
+ :param search_results: List of search result matches from Pinecone.
61
+ :return: A list of dictionaries containing relevant metadata and scores.
62
+ """
63
+ processed_results = []
64
+
65
+ for result in search_results:
66
+ processed_results.append({
67
+ "id": result['id'],
68
+ "score": result['score'],
69
+ "Title": result['metadata'].get('Title', ''),
70
+ "ChunkText": result['metadata'].get('ChunkText', ''),
71
+ "PageNumber": result['metadata'].get('PageNumber', ''),
72
+ "Chunk": result['metadata'].get('Chunk', '')
73
+ })
74
+
75
+ return processed_results
76
+
77
+ def reconstruct_text_from_chunks(df_chunks):
78
+ """
79
+ Reconstructs a single string of text from the chunks in the DataFrame.
80
+
81
+ :param df_chunks: DataFrame with columns ['Title', 'Chunk', 'ChunkText', 'TokenCount', 'PageNumber', 'ChunkID']
82
+ :return: A string combining all chunk texts in order.
83
+ """
84
+ return " ".join(df_chunks.sort_values(by=['Chunk'])['ChunkText'].tolist())
85
+
86
+ def lookup_related_chunks(df_chunks, chunk_id):
87
+ """
88
+ Returns all chunks matching the title and page number of the specified chunk ID,
89
+ including chunks from the previous and next pages, handling edge cases where
90
+ there is no preceding or succeeding page.
91
+
92
+ :param df_chunks: DataFrame with columns ['Title', 'Chunk', 'ChunkText', 'TokenCount', 'PageNumber', 'ChunkID']
93
+ :param chunk_id: The unique ID of the chunk to look up.
94
+ :return: DataFrame with all chunks matching the title and page range of the specified chunk ID.
95
+ """
96
+ target_chunk = df_chunks[df_chunks['ChunkID'] == chunk_id]
97
+ if target_chunk.empty:
98
+ raise ValueError("Chunk ID not found")
99
+
100
+ title = target_chunk.iloc[0]['Title']
101
+ page_number = target_chunk.iloc[0]['PageNumber']
102
+
103
+ # Determine the valid page range
104
+ min_page = df_chunks[df_chunks['Title'] == title]['PageNumber'].min()
105
+ max_page = df_chunks[df_chunks['Title'] == title]['PageNumber'].max()
106
+
107
+ page_range = [page for page in [page_number - 1, page_number, page_number + 1] if min_page <= page <= max_page]
108
+
109
+ return df_chunks[(df_chunks['Title'] == title) & (df_chunks['PageNumber'].isin(page_range))]
110
+
111
+
112
+ def search_and_reconstruct(query, df_chunks):
113
+ """
114
+ Combines search, lookup of related chunks, and text reconstruction.
115
+
116
+ :param query: The query string to search for.
117
+ :param df_chunks: DataFrame with chunk data.
118
+ :param namespace: Pinecone namespace to search within.
119
+ :param top_k: Number of top search results to retrieve.
120
+ :return: A list of dictionaries with document title, page number, and reconstructed text.
121
+ """
122
+ search_results = search_knowledgebase(query)
123
+ processed_results = process_search_results(search_results)
124
+
125
+ reconstructed_results = []
126
+
127
+ for result in processed_results:
128
+ chunk_id = result['id']
129
+ related_chunks = lookup_related_chunks(df_chunks, chunk_id)
130
+ reconstructed_text = reconstruct_text_from_chunks(related_chunks)
131
+
132
+ reconstructed_results.append({
133
+ "Title": result['Title'],
134
+ "PageNumber": result['PageNumber'],
135
+ "ReconstructedText": reconstructed_text
136
+ })
137
+
138
+ return reconstructed_results
139
+
140
  def call_chat_api(data: ChatRequestClient):
141
  url = "https://agent-builder-api.greensea-b20be511.northeurope.azurecontainerapps.io/chat/"
142
  # Validate and convert the data to a dictionary
 
146
  response = requests.post(url, json=validated_data)
147
 
148
  if response.status_code == 200:
149
+ body = response.json()
150
+ query = body.get("content")
151
+ final_results = search_and_reconstruct(query, df_chunks)
152
+ return body, final_results # Return the JSON response if successful
153
  else:
154
  return "An error occured" # Return the raw response text if not successful
155
 
 
 
 
 
 
 
156
 
 
 
 
157
 
158
  # Title of the application
159
  # st.image('agentBuilderLogo.png')
160
+ st.title('RAG Design and Evaluator')
161
 
162
  # Sidebar for inputting personas
163
  st.sidebar.image('cognizant_logo.jpg')
 
172
  temp1 = st.sidebar.slider("Temperature", min_value=0.0, max_value=1.0, step=0.1, value=0.6, key='persona1_temp')
173
  tokens1 = st.sidebar.slider("Tokens", min_value=0, max_value=4000, step=100, value=500, key='persona1_tokens')
174
 
 
 
 
 
 
 
 
 
 
 
175
  st.sidebar.caption(f"Session ID: {genuuid()}")
176
 
 
177
  # Main chat interface
178
  st.markdown("""#### Query Translation in RAG Architecture
179
 
 
186
  2. **Converts to Concise Query**
187
  The LLM reformulates the input into a succinct and effective query optimized for the retrieval system's semantic search capabilities.
188
 
189
+ 3. **Uses Concise Query to serach Vector DB**
190
+ The query is used to search the vector DB for suitable grounding information.
191
+
192
  ##### Purpose
193
  This ensures that the retrieval system receives a clear and focused query, increasing the relevance of the information it retrieves. The query translator acts as a bridge between human conversational language and the technical requirements of a semantic retrieval system.""")
194
  # User ID Input
 
202
  if "messages" not in st.session_state:
203
  st.session_state.messages = []
204
 
205
+ retrival = []
206
+ response = {}
 
 
207
 
 
208
  if user_input := st.chat_input("Start chat:"):
 
209
  st.session_state.messages.append({"role": "user", "content": user_input})
 
 
 
210
  data = ChatRequestClient(
211
+ user_id=user_id,
212
  user_input=user_input,
213
  numberOfQuestions=1000,
214
  welcomeMessage="",
 
223
  temperature2=0.2
224
  )
225
 
226
+ response, retrival = call_chat_api(data)
 
 
 
227
  agent_message = response.get("content", "No response received from the agent.")
228
  elapsed_time = response.get("elapsed_time", 0)
 
 
 
229
  st.session_state.messages.append({"role": "assistant", "content": agent_message})
 
 
230
 
231
+ col1, col2 = st.columns(2)
232
+
233
+ with col1:
234
+ for message in st.session_state.messages:
235
+ with st.chat_message(message["role"]):
236
+ st.markdown(message["content"])
237
+
238
+ if response:
239
+ st.chat_message("assistant").markdown(response.get("content", "No response"))
240
+ st.caption(f"##### Time taken: {format_elapsed_time(response.get('elapsed_time', 0))} seconds")
241
+
242
+ with col2:
243
+ for entry in retrival:
244
+ with st.container():
245
+ st.write(f"**Title:** {entry['Title']}")
246
+ st.write(f"**Page Number:** {entry['PageNumber']}")
247
+ st.text_area("Grounding Text", entry['ReconstructedText'], height=150)
248
 
249