File size: 6,080 Bytes
444082b
 
 
 
 
 
 
 
 
 
bbfc899
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
444082b
 
 
 
 
 
 
 
34a6b67
 
10d008c
444082b
 
 
 
 
 
 
 
 
 
 
 
ae7d952
444082b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import streamlit as st
from streamlit_chat import message
import requests
import pandas as pd
import plotly.express as px
st.set_page_config(layout="wide")

API_URL = "https://virtual-eng-expert-api-v1.greensea-b20be511.northeurope.azurecontainerapps.io/api"
headers = {"Content-Type": "application/json"}

def query(payload, retries=2):
	"""Query the API with retry logic"""
	for attempt in range(retries + 1):
		try:
			response = requests.post(API_URL, headers=headers, json=payload, timeout=60)
			response.raise_for_status()  # Raise an exception for bad status codes
			
			# Check if response is actually JSON before parsing
			content_type = response.headers.get('Content-Type', '')
			if 'application/json' not in content_type:
				# Response is not JSON - likely HTML error page
				error_text = response.text[:1000]
				st.error(f"API returned non-JSON response (Content-Type: {content_type})")
				st.error(f"Response preview: {error_text[:500]}")
				with st.expander("Debug: View full response"):
					st.text(error_text)
				with st.expander("Debug: View request payload"):
					st.json(payload)
				raise ValueError(f"API returned non-JSON response. Status: {response.status_code}")
			
			# Try to parse JSON
			try:
				return response.json()
			except ValueError as json_error:
				# Response claims to be JSON but isn't valid
				st.error(f"API returned invalid JSON. Response text: {response.text[:500]}")
				with st.expander("Debug: View request payload"):
					st.json(payload)
				raise ValueError(f"Invalid JSON response: {str(json_error)}")
				
		except requests.exceptions.HTTPError as e:
			if attempt < retries:
				st.warning(f"Attempt {attempt + 1} failed with {e.response.status_code}. Retrying...")
				continue
			error_msg = f"API Error {e.response.status_code}"
			try:
				# Try to get JSON error if available
				error_json = e.response.json()
				if isinstance(error_json, dict):
					error_msg += f": {error_json.get('error', error_json.get('message', str(error_json)))}"
				else:
					error_msg += f": {error_json}"
			except:
				# Not JSON, show text response
				error_text = e.response.text[:500]
				if error_text:
					error_msg += f": {error_text}"
			st.error(error_msg)
			with st.expander("Debug: View request payload"):
				st.json(payload)
			raise
		except requests.exceptions.Timeout:
			if attempt < retries:
				st.warning(f"Attempt {attempt + 1} timed out. Retrying...")
				continue
			st.error("Request timed out. The API may be slow or unavailable. Please try again.")
			raise
		except requests.exceptions.RequestException as e:
			if attempt < retries:
				st.warning(f"Attempt {attempt + 1} failed: {str(e)[:100]}. Retrying...")
				continue
			st.error(f"Connection Error: {str(e)}")
			raise

def generate_response(user,prompt):
    output = query({"namespace":"virtualEngineer","version":1,"messages":[{"role":user, "content": prompt}]})
    return output


#Creating the chatbot interface
st.title("Engineering Expert")
st.caption("Problem: A major facilities engineering provider with over 40,000 field-based engineers and a large PDF-based knowledge repository of over 100,000 pages of documents faced significant challenges. The existing system used a metadata-driven search, which was highly manual to maintain and inefficient for engineers needing quick access to relevant information. This inefficiency led to delays in field operations and difficulties in maintaining up-to-date knowledge across the organization.")
st.caption("Solution: To address this challenge, the engineering provider implemented a Virtual Engineering Assistant powered by Generative AI (GenAI). The solution involved developing an advanced information science strategy that leveraged a vector database and unique memory architectures to improve information retrieval and decision support.")

col1, col2 = st.columns(2)
# Storing the chat

    
if 'generated' not in st.session_state:
        st.session_state['generated'] = []

if 'past' not in st.session_state:
        st.session_state['past'] = []

with col1:
    with st.form(key='my_form'):
        User = st.text_input("Step 1 Set Engineer Name","", key="user")
        input_text = st.text_input("Step 2 How can I help today?","", key="input")
        submit_button = st.form_submit_button(label='Submit') 
    if submit_button:
        output = generate_response(User,input_text)
        # store the output 
        st.session_state.past.append(input_text)
        st.session_state.generated.append(output['choices'][0]['message']['content'])
        df = pd.DataFrame(output["sources"])
        fig = px.scatter(df,  y="Score",color="Source", hover_data=['Insight'])
        fig.update_layout(showlegend=False)
            # Layout the columns
            
        st.subheader("Response Data")
        st.caption(f"Overall Answer Confidence: {output['accuracy']}%")
        st.caption(f"Time Taken: {round(output['timeTaken'],1)} Seconds")
        st.caption(f"Cognitive Cache Hit: {output['cacheHit']}")
        st.caption('The below chart shows the distribution of knowledge in the knowledge store. This is used to supply expert information to answer your specific question. We request the top 100 results to speed up this demo, but analysing the knowledge store is an important part of maintaining high quality knowledge base which is key to high alignment, minimising hallucinations and ensuring safety.')
        st.plotly_chart(fig, theme=None, use_container_width=True)
        st.caption('Sources:')
        st.caption('This table represents the books and their page numbers that were used to create the expert answer')
        st.table(df.loc[:, ['Score', 'Source', 'startpage']].head(5))
if st.session_state['generated']:
    
    for i in range(len(st.session_state['generated'])-1, -1, -1):
        with col2:    
            
            message(st.session_state["generated"][i], key=str(i),avatar_style="identicon",seed="Socks")
            message(st.session_state['past'][i], is_user=True, key=str(i) + '_user',avatar_style="identicon",seed="Mittens")