QuantAdminUser commited on
Commit
45be6ef
·
verified ·
1 Parent(s): 6dda2d9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +178 -4
app.py CHANGED
@@ -1,7 +1,181 @@
 
1
  import gradio as gr
 
 
 
 
 
 
2
 
3
- def greet(name):
4
- return "Hello " + name + "!!"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- demo = gr.Interface(fn=greet, inputs="text", outputs="text")
7
- demo.launch()
 
1
+ import os
2
  import gradio as gr
3
+ from docx import Document
4
+ from langchain_openai import ChatOpenAI
5
+ from langchain_core.prompts import ChatPromptTemplate, HumanMessagePromptTemplate, SystemMessagePromptTemplate, AIMessagePromptTemplate
6
+ from langchain_core.output_parsers import StrOutputParser
7
+ from langchain_core.runnables import RunnablePassthrough
8
+ from langchain_community.document_loaders import TextLoader, UnstructuredWordDocumentLoader
9
 
10
+ # Configuration
11
+ SECRET_KEY = "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" # Replace with your actual API key
12
+ RUNBOOK_DIR = "./runbooks"
13
+
14
+ # Initialize LLMs
15
+ llm = ChatOpenAI(model="gpt-4o", temperature=0.4, api_key=SECRET_KEY, streaming=True)
16
+ selector_llm = ChatOpenAI(model="gpt-4o", temperature=0, api_key=SECRET_KEY)
17
+ llm_recc = ChatOpenAI(api_key=SECRET_KEY, model="gpt-4o")
18
+ output_parser = StrOutputParser()
19
+ previous_selected_runbook = ""
20
+
21
+ # Load runbooks
22
+ def load_runbooks():
23
+ runbooks = {}
24
+ for file in os.listdir(RUNBOOK_DIR):
25
+ path = os.path.join(RUNBOOK_DIR, file)
26
+ if file.endswith(".txt"):
27
+ loader = TextLoader(path)
28
+ elif file.endswith(".docx"):
29
+ loader = UnstructuredWordDocumentLoader(path)
30
+ else:
31
+ continue
32
+ docs = loader.load()
33
+ runbooks[file] = "\n".join([doc.page_content for doc in docs])
34
+ return runbooks
35
+
36
+ RUNBOOKS = load_runbooks()
37
+ RUNBOOK_NAMES = list(RUNBOOKS.keys())
38
+
39
+ # Prompt templates with roles
40
+ system_prompt = SystemMessagePromptTemplate.from_template(
41
+ "You are an IT support assistant. Respond using only the immediate next step based strictly on the runbook content. Never provide multiple actions. Escalate only when the user explicitly asks."
42
+ )
43
+
44
+ user_prompt = HumanMessagePromptTemplate.from_template(
45
+ "Runbook Names:\n{runbook_names}\nRunbook Content:\n{runbook_contents}\nConversation History:\n{conversation_history}\nUser: {user_message}"
46
+ )
47
+
48
+ assistant_prompt = AIMessagePromptTemplate.from_template("Assistant:")
49
+
50
+ selector_prompt = ChatPromptTemplate.from_template("""
51
+ Choose the best runbook from:
52
+ {runbook_names}
53
+
54
+ User: {user_message}
55
+ Selected:
56
+ """)
57
+
58
+ recc_template = ChatPromptTemplate.from_template("""
59
+ You are a support agent assistant analyzing user cases. The test case shows what the user has talked with AI assistant so far.
60
+ Now the user wants to talk to a human. Based on the test case and runbook below,
61
+ suggest up to 3 recommendations which the human agent can ask the user to continue the conversation from the step where the user is stuck. For each recommendation:
62
+ 1. Reference specific steps from the runbook, the steps should be exactly present in the runbook
63
+ 2. Add confidence score (70-100% if directly supported by runbook, 50-69% if inferred)
64
+ 3. Prioritize most critical actions first
65
+ 4. Strictly do not output anything which is not present in the runbook.
66
+
67
+ Test Case: {test_case}
68
+ Case Description: {description}
69
+ Runbook Content: {runbook}
70
+
71
+ Generate upto 3 recommendations strictly in this format:
72
+ 1. [Action] (Confidence: X%) - [Reasoning]
73
+ 2. [Action] (Confidence: X%) - [Reasoning]
74
+ """)
75
+
76
+ # File readers
77
+ def read_test_case(file_path):
78
+ try:
79
+ with open(file_path, "r") as f:
80
+ return f.read()
81
+ except FileNotFoundError:
82
+ raise FileNotFoundError(f"Test case file not found at {file_path}")
83
+
84
+ def read_runbook(file_path):
85
+ try:
86
+ return Document(file_path)
87
+ except FileNotFoundError:
88
+ raise FileNotFoundError(f"Runbook file not found at {file_path}")
89
+
90
+ def get_recommendations(test_case, runbook_path):
91
+ runbook = read_runbook(runbook_path)
92
+ description = os.path.basename(runbook_path)
93
+ return
94
+
95
+ def respond(message, history):
96
+ global previous_selected_runbook
97
+ escalation_buffer = ""
98
+ buffer = ""
99
+ escalation_triggered = False
100
+
101
+ # Select runbook
102
+ if previous_selected_runbook:
103
+ selected_runbook = previous_selected_runbook
104
+ else:
105
+ selected = selector_llm.invoke(selector_prompt.format(
106
+ runbook_names="\n".join(RUNBOOK_NAMES),
107
+ user_message=message
108
+ )).content.strip()
109
+ selected_runbook = next((rb for rb in RUNBOOKS if rb in selected), "")
110
+ previous_selected_runbook = selected_runbook
111
+
112
+ runbook_content = "\n".join([f"--- {k} ---\n{v}" for k, v in RUNBOOKS.items()])
113
+ conversation_history = "\n".join([f"{turn[0]}: {turn[1]}" for turn in history])
114
+
115
+ if "human" in message and not escalation_triggered:
116
+ escalation_triggered = True
117
+ conversation_text = conversation_history + f"\nUser: {message}"
118
+ buffer = "Escalating to human agent..."
119
+ for token in llm_recc.stream(recc_template.format(
120
+ test_case=conversation_text,
121
+ description=os.path.basename(selected_runbook),
122
+ runbook=RUNBOOKS[selected_runbook])):
123
+ escalation_buffer += token.content
124
+ yield (buffer, escalation_buffer, selected_runbook)
125
+ return
126
+
127
+ full_prompt = ChatPromptTemplate.from_messages([
128
+ system_prompt,
129
+ user_prompt,
130
+ assistant_prompt
131
+ ])
132
+
133
+ for token in llm.stream(full_prompt.format(
134
+ runbook_names="\n".join(RUNBOOK_NAMES),
135
+ runbook_contents=runbook_content,
136
+ conversation_history=conversation_history,
137
+ user_message=message
138
+ )):
139
+ buffer += token.content
140
+ yield (buffer, escalation_buffer, selected_runbook)
141
+
142
+ # UI Setup
143
+ def clear_conversation():
144
+ return [], "", "", "No runbook selected"
145
+
146
+ with gr.Blocks() as demo:
147
+ gr.Markdown("# IT Support Assistant")
148
+
149
+ with gr.Row():
150
+ with gr.Column(scale=1):
151
+ gr.Markdown("### Available Runbooks")
152
+ gr.Markdown("\n".join([f"- **{name}**" for name in RUNBOOK_NAMES]))
153
+ selected_runbook_display = gr.Markdown("No runbook selected")
154
+
155
+ with gr.Row():
156
+ with gr.Column(scale=3):
157
+ chat = gr.ChatInterface(
158
+ respond,
159
+ additional_outputs=[
160
+ gr.Textbox(label="Escalation Recommendations", lines=5, value=""),
161
+ selected_runbook_display
162
+ ],
163
+ examples=["Increase Mail Size", "Outlook calendar not responding"],
164
+ cache_examples=False
165
+ )
166
+
167
+ with gr.Row():
168
+ clear_button = gr.Button("Clear Conversation")
169
+
170
+ clear_button.click(
171
+ clear_conversation,
172
+ outputs=[
173
+ chat.chatbot,
174
+ chat.additional_outputs[0],
175
+ chat.textbox,
176
+ selected_runbook_display
177
+ ]
178
+ )
179
+
180
+ demo.queue().launch()
181