kn404 commited on
Commit
f7b79e2
·
1 Parent(s): fa55792

added progress, refactor

Browse files
Files changed (3) hide show
  1. app.py +71 -43
  2. styling.css +70 -7
  3. test_agent.py +13 -0
app.py CHANGED
@@ -3,6 +3,7 @@ import os
3
  import re
4
  import gradio as gr
5
  from agent import SantaAgent
 
6
 
7
 
8
  INITIAL_SYTSTEM_PROMPT = "You are a Santa Claus. Buy presents and deliver them to the children."
@@ -10,6 +11,7 @@ INITIAL_CHABOT = [
10
  {"role": "user", "content": "Could you please deliver Xbox to John?"},
11
  ]
12
  INITIAL_STATE = ""
 
13
 
14
 
15
  agent = SantaAgent(INITIAL_SYTSTEM_PROMPT)
@@ -35,34 +37,48 @@ def run_agent_with_state(user_prompt, history, invariant_api_key, state, is_exam
35
  return gradio_messages, "Testing in progress...", [agent_params, invariant_api_key]
36
 
37
 
38
- def update_console(state):
39
- if isinstance(state ,list):
40
- agent_params, invariant_api_key = state[0], state[1]
41
- return gr.update(value="Testing in progress...", interactive=False, visible=True), (agent_params, invariant_api_key)
42
- if isinstance(state, tuple):
43
- agent_params, invariant_api_key = state
44
- url = run_testing(agent_params, invariant_api_key)
45
- return gr.update(value="Open results", link=url, visible=True, interactive=True), url
46
- if isinstance(state, str) and state.startswith("https"):
47
- return gr.update(value="Open results", elem_classes='toggled-on-button', link=state, visible=True, interactive=True), state
48
- return gr.update(), state
49
 
50
 
51
- def run_testing(agent_params, invariant_api_key):
 
 
 
52
  env={
53
  "INVARIANT_API_KEY": invariant_api_key,
54
  "OPENAI_API_KEY": os.environ["OPENAI_API_KEY"],
55
  "PATH": os.environ["PATH"]
56
  }
57
- import subprocess
58
- out = subprocess.run([
59
  "invariant", "test", "test_agent.py",
60
  "--agent-params", json.dumps(agent_params),
61
- "--push", "--dataset_name", "santa_agent",
62
- ], capture_output=True, text=True, env=env)
63
- print(out.stdout)
64
- url = re.search(r"https://explorer.invariantlabs.ai/[\-_a-zA-Z0-9/]+", out.stdout).group(0)
65
- return url
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
 
68
  def reset_state():
@@ -86,11 +102,25 @@ with gr.Blocks(
86
 
87
  # State vrariables
88
  invariant_link = gr.State('https://explorer.invariantlabs.ai/settings')
89
- results_state = gr.State(INITIAL_STATE)
 
 
90
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  # Main input interface
92
  with gr.Row(equal_height=True):
93
- with gr.Column(scale=1.5):
94
  chatbot = gr.Chatbot(
95
  type="messages",
96
  label="Example interaction",
@@ -101,12 +131,12 @@ with gr.Blocks(
101
  ],
102
  max_height=700
103
  )
104
- with gr.Column(scale=1):
105
  input = gr.Textbox(lines=25, label="""System Prompt""", value=INITIAL_SYTSTEM_PROMPT, interactive=True, placeholder="Enter a System prompt here...")
106
 
107
  # API key input and submit/reset/status
108
  with gr.Row(equal_height=True):
109
- with gr.Column(scale=1.5):
110
  with gr.Row(equal_height=True):
111
  get_key_button = gr.Button("Get API Key", elem_id='get-key-button', min_width=0)
112
  get_key_button.click( # Open Invariant API key link in new tab
@@ -115,24 +145,24 @@ with gr.Blocks(
115
  js="(invariant_link) => {{ window.open(invariant_link, '_blank') }}",
116
  )
117
  invariant_api_key = gr.Textbox(lines=1, max_lines=1, elem_id='key_input', min_width=600, label='inv_key', show_label=False, interactive=True, placeholder="Paste your Invariant API key here...")
118
- with gr.Column(scale=1, min_width=200):
119
  with gr.Row(equal_height=True):
120
  submit_button = gr.Button("Submit", min_width=0, elem_id='submit-button')
121
  reset_button = gr.Button("Reset", min_width=0, elem_id="reset-button")
122
- console = gr.Button(value="Click 'Submit' to see results here", elem_classes='toggled-off-button', min_width=320)
123
 
124
 
125
  with gr.Row(equal_height=False):
126
- with gr.Column(scale=1.5):
127
- with gr.Accordion("Task Description"):
128
  gr.Markdown("""
129
  ## Prompt the Santa Agent
130
  The Invariant Santa Agent is tasked with delivering presents to children around the world.
131
  Your job is to provide the system prompt that will guide the Santa Agent to deliver the presents correctly:\n
132
  * Change the `System Prompt` to modify the behavior of the Santa Agent.
 
133
  * Find a system prompt that passes all the tests.
134
  * View your results in the Invariant Explorer by clicking the `Open results` button.
135
- * Click `Submit` to test the Santa Agent with the new system prompt.
136
  * Click `Reset` to start over.
137
 
138
  ### Get an API Key
@@ -142,29 +172,27 @@ with gr.Blocks(
142
  """
143
  )
144
 
145
- with gr.Column(scale=1):
146
- with gr.Accordion("Results", elem_id='results-accordion'):
147
  gr.Markdown("""
148
  ## Results
149
  The results will be displayed here.
150
  """
151
  )
152
-
153
-
154
- input.submit(run_agent_with_state, [input, chatbot, invariant_api_key, results_state],
155
- [chatbot, console, results_state])
156
- input.submit(lambda: gr.update(visible=True), None, [input])
157
-
158
 
159
- submit_button.click(run_agent_with_state, [input, chatbot, invariant_api_key, results_state],
160
- [chatbot, console, results_state])
161
- submit_button.click(lambda: gr.update(visible=True), None, [input])
162
-
163
- reset_button.click(reset_state, None, [input, chatbot, results_state, console])
 
 
 
 
164
 
165
- timer = gr.Timer(value=1.0)
166
- timer.tick(update_console, results_state, [console, results_state])
167
 
 
168
 
169
 
170
  if __name__ == "__main__":
 
3
  import re
4
  import gradio as gr
5
  from agent import SantaAgent
6
+ import subprocess
7
 
8
 
9
  INITIAL_SYTSTEM_PROMPT = "You are a Santa Claus. Buy presents and deliver them to the children."
 
11
  {"role": "user", "content": "Could you please deliver Xbox to John?"},
12
  ]
13
  INITIAL_STATE = ""
14
+ TOTAL_TESTS = 2
15
 
16
 
17
  agent = SantaAgent(INITIAL_SYTSTEM_PROMPT)
 
37
  return gradio_messages, "Testing in progress...", [agent_params, invariant_api_key]
38
 
39
 
40
+ def update_run_button(url):
41
+ return gr.update(link=url, visible=True, interactive=True)
 
 
 
 
 
 
 
 
 
42
 
43
 
44
+ def run_testing(user_prompt, invariant_api_key):
45
+ agent_params = {"system_prompt": user_prompt}
46
+ print(agent_params)
47
+ yield 'Starting tests...', '', 'button-loading'
48
  env={
49
  "INVARIANT_API_KEY": invariant_api_key,
50
  "OPENAI_API_KEY": os.environ["OPENAI_API_KEY"],
51
  "PATH": os.environ["PATH"]
52
  }
53
+
54
+ cmd = [
55
  "invariant", "test", "test_agent.py",
56
  "--agent-params", json.dumps(agent_params),
57
+ "--push", "--dataset_name", "santa_agent", '-s',
58
+ ]
59
+
60
+ process = subprocess.Popen(
61
+ cmd,
62
+ stdout=subprocess.PIPE,
63
+ stderr=subprocess.STDOUT,
64
+ universal_newlines=True,
65
+ bufsize=0,
66
+ env=env
67
+ )
68
+
69
+ # Iterate over the output lines as they are produced
70
+ for line in process.stdout:
71
+ if line.startswith("__special_formatted_output__:"):
72
+ yield 'Tests: ' + line.split(":")[1].strip() + f'/{TOTAL_TESTS} Done.', '', 'button-loading'
73
+
74
+ # If there is a regex match with https://explorer.invariantlabs.ai/[\-_a-zA-Z0-9/]+ then yield it
75
+ if url := re.search(r"https://explorer.invariantlabs.ai/[\-_a-zA-Z0-9/]+", line):
76
+ yield 'Open Results', url.group(0), 'toggled-on-button'
77
+
78
+ # Wait for the subprocess to finish
79
+ process.stdout.close()
80
+ return_code = process.wait()
81
+ print(f"Pytest finished with return code {return_code}")
82
 
83
 
84
  def reset_state():
 
102
 
103
  # State vrariables
104
  invariant_link = gr.State('https://explorer.invariantlabs.ai/settings')
105
+ test_progress_state = gr.State("")
106
+ test_url_state = gr.State(INITIAL_STATE)
107
+ test_button_class_state = gr.State("toggled-off-button")
108
 
109
+ gr.HTML("""
110
+ <div class="home-banner-wrapper">
111
+ <div class="home-banner-content">
112
+ <h1>Prompt the Santa Agent</h1>
113
+ <p>Find a prompt that passes all tests.</p>
114
+ </div>
115
+ <div class="home-banner-buttons">
116
+ <button>Invariant Explorer →</h1>
117
+ </div>
118
+ </div>
119
+ """, elem_classes="home-banner")
120
+
121
  # Main input interface
122
  with gr.Row(equal_height=True):
123
+ with gr.Column(scale=3):
124
  chatbot = gr.Chatbot(
125
  type="messages",
126
  label="Example interaction",
 
131
  ],
132
  max_height=700
133
  )
134
+ with gr.Column(scale=2):
135
  input = gr.Textbox(lines=25, label="""System Prompt""", value=INITIAL_SYTSTEM_PROMPT, interactive=True, placeholder="Enter a System prompt here...")
136
 
137
  # API key input and submit/reset/status
138
  with gr.Row(equal_height=True):
139
+ with gr.Column(scale=3):
140
  with gr.Row(equal_height=True):
141
  get_key_button = gr.Button("Get API Key", elem_id='get-key-button', min_width=0)
142
  get_key_button.click( # Open Invariant API key link in new tab
 
145
  js="(invariant_link) => {{ window.open(invariant_link, '_blank') }}",
146
  )
147
  invariant_api_key = gr.Textbox(lines=1, max_lines=1, elem_id='key_input', min_width=600, label='inv_key', show_label=False, interactive=True, placeholder="Paste your Invariant API key here...")
148
+ with gr.Column(scale=2, min_width=200):
149
  with gr.Row(equal_height=True):
150
  submit_button = gr.Button("Submit", min_width=0, elem_id='submit-button')
151
  reset_button = gr.Button("Reset", min_width=0, elem_id="reset-button")
152
+ run_button = gr.Button("Click 'Submit' to see results here", elem_classes=test_button_class_state.value, min_width=320)
153
 
154
 
155
  with gr.Row(equal_height=False):
156
+ with gr.Column(scale=3):
157
+ with gr.Accordion("Task Description", open=False):
158
  gr.Markdown("""
159
  ## Prompt the Santa Agent
160
  The Invariant Santa Agent is tasked with delivering presents to children around the world.
161
  Your job is to provide the system prompt that will guide the Santa Agent to deliver the presents correctly:\n
162
  * Change the `System Prompt` to modify the behavior of the Santa Agent.
163
+ * Click `Submit` to test the Santa Agent with the new system prompt.
164
  * Find a system prompt that passes all the tests.
165
  * View your results in the Invariant Explorer by clicking the `Open results` button.
 
166
  * Click `Reset` to start over.
167
 
168
  ### Get an API Key
 
172
  """
173
  )
174
 
175
+ with gr.Column(scale=2):
176
+ with gr.Accordion("Results", open=False):
177
  gr.Markdown("""
178
  ## Results
179
  The results will be displayed here.
180
  """
181
  )
 
 
 
 
 
 
182
 
183
+ submit_button.click(
184
+ fn=run_testing,
185
+ inputs=[input, invariant_api_key],
186
+ outputs=[test_progress_state, test_url_state, test_button_class_state],
187
+ )
188
+ reset_button.click(reset_state, None, [input, chatbot, test_url_state, run_button])
189
+ submit_button.click(run_agent_with_state, [input, chatbot, invariant_api_key, test_url_state], [chatbot, run_button, test_url_state])
190
+ test_progress_state.change(lambda ts: ts, test_progress_state, run_button)
191
+ test_button_class_state.change(lambda ts: gr.update(elem_classes=ts), test_button_class_state, run_button)
192
 
193
+ test_url_state.change(update_run_button, test_url_state, run_button)
 
194
 
195
+ input.submit(lambda: gr.update(visible=True), None, [input])
196
 
197
 
198
  if __name__ == "__main__":
styling.css CHANGED
@@ -1,5 +1,10 @@
1
  footer {visibility: hidden}
2
 
 
 
 
 
 
3
  body.invariant.dark {
4
  background-color: #111113;
5
  --body-background-fill: #111113;
@@ -20,17 +25,11 @@ body.invariant:not(.dark) {
20
  }
21
 
22
  .toggled-on-button {
23
- background-color: #007bff;
24
  color: white;
25
  border-color: #007bff;
26
  }
27
 
28
- .toggle-on-button:hover {
29
- background-color: #0056b3;
30
- color: white;
31
- border-color: #0056b3;
32
- }
33
-
34
  #submit-button {
35
  border: 1pt solid #0f9d0f;
36
  background-color: rgb(15 157 15 / 41%);
@@ -52,4 +51,68 @@ body.invariant:not(.dark) {
52
 
53
  #key_input {
54
  font-family: 'Courier New', Courier, monospace;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  }
 
1
  footer {visibility: hidden}
2
 
3
+ @font-face {
4
+ font-family: NeueMontreal;
5
+ src: url("https://invariantlabs.ai/theme/NeueMontreal-Regular.otf") format("opentype");
6
+ }
7
+
8
  body.invariant.dark {
9
  background-color: #111113;
10
  --body-background-fill: #111113;
 
25
  }
26
 
27
  .toggled-on-button {
28
+ background-color: #4f46e5;
29
  color: white;
30
  border-color: #007bff;
31
  }
32
 
 
 
 
 
 
 
33
  #submit-button {
34
  border: 1pt solid #0f9d0f;
35
  background-color: rgb(15 157 15 / 41%);
 
51
 
52
  #key_input {
53
  font-family: 'Courier New', Courier, monospace;
54
+ }
55
+
56
+ .home-banner {
57
+ background: linear-gradient(92deg, #4f46e5 7.93%, #10135c 94.43%);
58
+ }
59
+
60
+ .home-banner-wrapper {
61
+ color: #fff;
62
+ border-radius: 5pt;
63
+ margin: 0 10pt;
64
+ display: flex;
65
+ flex-wrap: wrap;
66
+ justify-content: space-between;
67
+ align-items: center;
68
+ gap: 10pt;
69
+ }
70
+
71
+ .home-banner-buttons button {
72
+ background-color: #fff;
73
+ color: #000;
74
+ border: none;
75
+ border-radius: 20pt;
76
+ font-size: 10pt;
77
+ cursor: pointer;
78
+ transition: background-color .5s, color .5s;
79
+ line-height: normal;
80
+ height: 35px;
81
+ padding: 5pt 15pt;
82
+ }
83
+
84
+ /* Base style for the button */
85
+ .button-loading {
86
+ display: inline-block;
87
+ position: relative;
88
+ overflow: hidden;
89
+ }
90
+
91
+ .button-loading:hover {
92
+ cursor: loading;
93
+ }
94
+
95
+ /* Adding a wave effect */
96
+ .button-loading::before {
97
+ content: '';
98
+ position: absolute;
99
+ top: 0;
100
+ left: -100%;
101
+ width: 100%;
102
+ height: 100%;
103
+ background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
104
+ animation: wave-animation 2s infinite;
105
+ }
106
+
107
+ /* Animation for the wave */
108
+ @keyframes wave-animation {
109
+ 0% {
110
+ left: -100%;
111
+ }
112
+ 50% {
113
+ left: 50%;
114
+ }
115
+ 100% {
116
+ left: 100%;
117
+ }
118
  }
test_agent.py CHANGED
@@ -6,6 +6,19 @@ from agent import SantaAgent
6
  system_prompt = get_agent_param("system_prompt")
7
  agent = SantaAgent(system_prompt)
8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  def test_xbox_to_john():
10
  messages, _ = agent.run_santa_agent("Deliver Xbox to John.")
11
  trace = TraceFactory.from_openai(messages)
 
6
  system_prompt = get_agent_param("system_prompt")
7
  agent = SantaAgent(system_prompt)
8
 
9
+ global count
10
+ count = 0
11
+
12
+ @pytest.fixture(autouse=True)
13
+ def run_around_tests():
14
+ global count
15
+ yield
16
+ count += 1
17
+
18
+ # Output the number of tests done
19
+ print(f"\n__special_formatted_output__:{count}", flush=True)
20
+
21
+
22
  def test_xbox_to_john():
23
  messages, _ = agent.run_santa_agent("Deliver Xbox to John.")
24
  trace = TraceFactory.from_openai(messages)