drbinna commited on
Commit
c00ae2f
Β·
verified Β·
1 Parent(s): 3da4663

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +155 -30
app.py CHANGED
@@ -1,11 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  def search_knowledge_base(query, search_type="generate"):
2
  """
3
  Search the ORU IT Knowledge Base using Amazon Bedrock
4
  """
5
-
6
  if not query.strip():
7
  return "Please enter a question!", "", "error"
8
-
9
  # Demo mode response
10
  if DEMO_MODE:
11
  demo_response = f"""
@@ -19,34 +53,26 @@ To enable full functionality:
19
  1. Configure your Amazon Bedrock Knowledge Base
20
  2. Set up environment variables in Hugging Face Spaces settings
21
  3. Upload your ORU IT documentation to the knowledge base
22
-
23
- **Expected Response:** Once configured, this system would search through ORU's IT knowledge base and provide accurate, contextual answers to questions like:
24
- - Password reset procedures
25
- - Software installation guides
26
- - Network troubleshooting steps
27
- - Campus system access instructions
28
  """
29
-
30
  demo_sources = """
31
  **Demo Sources:**
32
  - password_authentication_001_student_password_change.txt
33
  - mobile_applications_002_oru_app_experience_fix.txt
34
  - software_applications_003_word_mac_view_only_fix.txt
35
-
36
- *These would be the actual ORU IT knowledge base documents that contain the answer.*
37
  """
38
-
39
  return demo_response, demo_sources, "demo"
40
-
41
  if not bedrock_agent:
42
  error_msg = f"❌ AWS Bedrock client not initialized."
43
  if initialization_error:
44
  error_msg += f" Error: {initialization_error}"
45
  return error_msg, "", "error"
46
-
47
  try:
48
  if search_type == "generate":
49
- # βœ… Corrected RetrieveAndGenerate with separate modelConfiguration
50
  response = bedrock_agent.retrieve_and_generate(
51
  input={'text': query},
52
  retrieveAndGenerateConfiguration={
@@ -64,27 +90,28 @@ To enable full functionality:
64
  }
65
  }
66
  )
67
-
68
  # Extract the generated response
69
  generated_text = response.get('output', {}).get('text', 'No response generated.')
70
-
71
  # Extract sources/citations
72
  sources_info = []
73
  citations = response.get('citations', [])
74
-
75
  for i, citation in enumerate(citations, 1):
76
  retrieved_refs = citation.get('retrievedReferences', [])
77
  for j, ref in enumerate(retrieved_refs, 1):
78
  content = ref.get('content', {}).get('text', 'No content available')
79
  location = ref.get('location', {}).get('s3Location', {}).get('uri', 'Unknown source')
80
- sources_info.append(f"**Source {i}.{j}:**\n{content[:300]}{'...' if len(content) > 300 else ''}\n*From: {location}*\n")
81
-
 
 
82
  sources_text = "\n".join(sources_info) if sources_info else "No sources found."
83
-
84
  return generated_text, sources_text, "success"
85
-
86
  else: # retrieve only
87
- # Use Retrieve for sources only
88
  response = bedrock_agent.retrieve(
89
  knowledgeBaseId=KNOWLEDGE_BASE_ID,
90
  retrievalQuery={'text': query},
@@ -94,34 +121,132 @@ To enable full functionality:
94
  }
95
  }
96
  )
97
-
98
  retrieval_results = response.get('retrievalResults', [])
99
  if not retrieval_results:
100
  return "No relevant sources found.", "", "warning"
101
-
102
  sources_info = []
103
  for i, result in enumerate(retrieval_results, 1):
104
  content = result.get('content', {}).get('text', 'No content available')
105
  score = result.get('score', 0)
106
  location = result.get('location', {}).get('s3Location', {}).get('uri', 'Unknown source')
 
107
  sources_info.append(
108
  f"**Source {i} (Confidence: {score:.2f}):**\n"
109
  f"{content[:400]}{'...' if len(content) > 400 else ''}\n"
110
  f"*From: {location}*\n"
111
  )
112
-
113
  sources_text = "\n".join(sources_info)
114
  response_text = f"Found {len(retrieval_results)} relevant sources from the ORU IT Knowledge Base:"
115
-
116
  return response_text, sources_text, "success"
117
-
118
  except ClientError as e:
119
  error_code = e.response['Error']['Code']
120
  error_message = e.response['Error']['Message']
121
  return f"❌ AWS Error ({error_code}): {error_message}", "", "error"
122
-
123
  except NoCredentialsError:
124
  return "❌ AWS credentials not found. Please configure your credentials in Spaces settings.", "", "error"
125
-
126
  except Exception as e:
127
  return f"❌ Unexpected error: {str(e)}", "", "error"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import boto3
3
+ import json
4
+ import os
5
+ from botocore.exceptions import ClientError, NoCredentialsError
6
+
7
+ # Configuration - Set via Hugging Face Spaces environment variables
8
+ KNOWLEDGE_BASE_ID = os.environ.get("KNOWLEDGE_BASE_ID", "PLEASE_SET_IN_SPACES_SETTINGS")
9
+ AWS_REGION = os.environ.get("AWS_REGION", "us-east-1")
10
+ MODEL_ARN = os.environ.get("MODEL_ARN", "arn:aws:bedrock:us-east-1::foundation-model/amazon.titan-text-express-v1")
11
+
12
+ # Check if running in demo mode (no credentials set)
13
+ DEMO_MODE = KNOWLEDGE_BASE_ID == "PLEASE_SET_IN_SPACES_SETTINGS"
14
+
15
+ # Initialize AWS clients
16
+ bedrock_agent = None
17
+ initialization_error = None
18
+
19
+ if not DEMO_MODE:
20
+ try:
21
+ bedrock_agent = boto3.client(
22
+ 'bedrock-agent-runtime',
23
+ region_name=AWS_REGION,
24
+ aws_access_key_id=os.environ.get('AWS_ACCESS_KEY_ID'),
25
+ aws_secret_access_key=os.environ.get('AWS_SECRET_ACCESS_KEY')
26
+ )
27
+ print(f"βœ… AWS Bedrock client initialized in region: {AWS_REGION}")
28
+ except Exception as e:
29
+ print(f"❌ Error initializing AWS client: {e}")
30
+ initialization_error = str(e)
31
+ else:
32
+ print("🚧 Running in DEMO MODE - Configure environment variables to enable AWS integration")
33
+
34
+
35
  def search_knowledge_base(query, search_type="generate"):
36
  """
37
  Search the ORU IT Knowledge Base using Amazon Bedrock
38
  """
39
+
40
  if not query.strip():
41
  return "Please enter a question!", "", "error"
42
+
43
  # Demo mode response
44
  if DEMO_MODE:
45
  demo_response = f"""
 
53
  1. Configure your Amazon Bedrock Knowledge Base
54
  2. Set up environment variables in Hugging Face Spaces settings
55
  3. Upload your ORU IT documentation to the knowledge base
 
 
 
 
 
 
56
  """
57
+
58
  demo_sources = """
59
  **Demo Sources:**
60
  - password_authentication_001_student_password_change.txt
61
  - mobile_applications_002_oru_app_experience_fix.txt
62
  - software_applications_003_word_mac_view_only_fix.txt
 
 
63
  """
64
+
65
  return demo_response, demo_sources, "demo"
66
+
67
  if not bedrock_agent:
68
  error_msg = f"❌ AWS Bedrock client not initialized."
69
  if initialization_error:
70
  error_msg += f" Error: {initialization_error}"
71
  return error_msg, "", "error"
72
+
73
  try:
74
  if search_type == "generate":
75
+ # βœ… Correct RetrieveAndGenerate with separate modelConfiguration
76
  response = bedrock_agent.retrieve_and_generate(
77
  input={'text': query},
78
  retrieveAndGenerateConfiguration={
 
90
  }
91
  }
92
  )
93
+
94
  # Extract the generated response
95
  generated_text = response.get('output', {}).get('text', 'No response generated.')
96
+
97
  # Extract sources/citations
98
  sources_info = []
99
  citations = response.get('citations', [])
100
+
101
  for i, citation in enumerate(citations, 1):
102
  retrieved_refs = citation.get('retrievedReferences', [])
103
  for j, ref in enumerate(retrieved_refs, 1):
104
  content = ref.get('content', {}).get('text', 'No content available')
105
  location = ref.get('location', {}).get('s3Location', {}).get('uri', 'Unknown source')
106
+ sources_info.append(
107
+ f"**Source {i}.{j}:**\n{content[:300]}{'...' if len(content) > 300 else ''}\n*From: {location}*\n"
108
+ )
109
+
110
  sources_text = "\n".join(sources_info) if sources_info else "No sources found."
111
+
112
  return generated_text, sources_text, "success"
113
+
114
  else: # retrieve only
 
115
  response = bedrock_agent.retrieve(
116
  knowledgeBaseId=KNOWLEDGE_BASE_ID,
117
  retrievalQuery={'text': query},
 
121
  }
122
  }
123
  )
124
+
125
  retrieval_results = response.get('retrievalResults', [])
126
  if not retrieval_results:
127
  return "No relevant sources found.", "", "warning"
128
+
129
  sources_info = []
130
  for i, result in enumerate(retrieval_results, 1):
131
  content = result.get('content', {}).get('text', 'No content available')
132
  score = result.get('score', 0)
133
  location = result.get('location', {}).get('s3Location', {}).get('uri', 'Unknown source')
134
+
135
  sources_info.append(
136
  f"**Source {i} (Confidence: {score:.2f}):**\n"
137
  f"{content[:400]}{'...' if len(content) > 400 else ''}\n"
138
  f"*From: {location}*\n"
139
  )
140
+
141
  sources_text = "\n".join(sources_info)
142
  response_text = f"Found {len(retrieval_results)} relevant sources from the ORU IT Knowledge Base:"
143
+
144
  return response_text, sources_text, "success"
145
+
146
  except ClientError as e:
147
  error_code = e.response['Error']['Code']
148
  error_message = e.response['Error']['Message']
149
  return f"❌ AWS Error ({error_code}): {error_message}", "", "error"
150
+
151
  except NoCredentialsError:
152
  return "❌ AWS credentials not found. Please configure your credentials in Spaces settings.", "", "error"
153
+
154
  except Exception as e:
155
  return f"❌ Unexpected error: {str(e)}", "", "error"
156
+
157
+
158
+ def format_response(query, search_type):
159
+ """Process the query and return formatted response"""
160
+
161
+ if not query.strip():
162
+ return (
163
+ "Please enter your IT question above and click 'Get AI Answer' or 'Show Sources'.",
164
+ "",
165
+ "Enter a question to get started!"
166
+ )
167
+
168
+ response_text, sources_text, status = search_knowledge_base(query, search_type)
169
+
170
+ if status == "demo":
171
+ formatted_response = response_text
172
+ status_msg = "🚧 Demo Mode - Configure AWS credentials to enable full functionality"
173
+ elif search_type == "generate":
174
+ if status == "success":
175
+ formatted_response = f"## πŸ€– AI Assistant Response\n\n{response_text}"
176
+ status_msg = "βœ… Response generated successfully from ORU IT Knowledge Base!"
177
+ else:
178
+ formatted_response = response_text
179
+ status_msg = "❌ Error generating response"
180
+ else:
181
+ if status == "success":
182
+ formatted_response = f"## πŸ“š Retrieved Sources\n\n{response_text}"
183
+ status_msg = "βœ… Sources retrieved successfully from ORU IT Knowledge Base!"
184
+ else:
185
+ formatted_response = response_text
186
+ status_msg = "❌ Error retrieving sources"
187
+
188
+ return formatted_response, sources_text, status_msg
189
+
190
+
191
+ # Sample queries
192
+ SAMPLE_QUERIES = [
193
+ "How do I change my student password?",
194
+ "My ORU app isn't showing the right tiles",
195
+ "Word is showing view only mode on my Mac",
196
+ "How do I set up multi-factor authentication?",
197
+ "I can't edit Microsoft Word documents",
198
+ "How do I connect to ORU WiFi network?",
199
+ "My ORU email isn't syncing to my phone",
200
+ "How do I access Vision portal from off-campus?",
201
+ "VPN connection keeps dropping",
202
+ "Can't print to campus printers from my laptop",
203
+ ]
204
+
205
+ # Build Gradio UI
206
+ with gr.Blocks(title="ORU IT Helpdesk Assistant") as app:
207
+ gr.Markdown("## πŸ›οΈ Oral Roberts University IT Helpdesk Assistant\nPowered by Amazon Bedrock Knowledge Bases & S3 Vectors")
208
+
209
+ with gr.Row():
210
+ with gr.Column(scale=2):
211
+ query_input = gr.Textbox(label="πŸ” Ask your IT question:")
212
+ with gr.Row():
213
+ search_btn = gr.Button("πŸ€– Get AI Answer", variant="primary")
214
+ retrieve_btn = gr.Button("πŸ“š Show Sources", variant="secondary")
215
+
216
+ with gr.Column():
217
+ for q in SAMPLE_QUERIES:
218
+ btn = gr.Button(q, size="sm")
219
+ btn.click(lambda x=q: x, outputs=query_input)
220
+
221
+ with gr.Column(scale=3):
222
+ status_output = gr.HTML()
223
+ response_output = gr.Markdown()
224
+ sources_output = gr.Markdown(visible=True)
225
+
226
+ search_btn.click(
227
+ fn=lambda query: format_response(query, "generate"),
228
+ inputs=[query_input],
229
+ outputs=[response_output, sources_output, status_output]
230
+ )
231
+ retrieve_btn.click(
232
+ fn=lambda query: format_response(query, "retrieve"),
233
+ inputs=[query_input],
234
+ outputs=[response_output, sources_output, status_output]
235
+ )
236
+ query_input.submit(
237
+ fn=lambda query: format_response(query, "generate"),
238
+ inputs=[query_input],
239
+ outputs=[response_output, sources_output, status_output]
240
+ )
241
+
242
+
243
+ # βœ… Always launch on Hugging Face
244
+ print("πŸ›οΈ Starting ORU IT Helpdesk Assistant...")
245
+ print(f"πŸ“š Knowledge Base ID: {KNOWLEDGE_BASE_ID}")
246
+ print(f"🌍 AWS Region: {AWS_REGION}")
247
+ print(f"🚧 Demo Mode: {'Active' if DEMO_MODE else 'Disabled'}")
248
+
249
+ app.launch(
250
+ server_name="0.0.0.0",
251
+ server_port=int(os.environ.get("PORT", 7860))
252
+ )