jesusvilela commited on
Commit
379da3c
·
verified ·
1 Parent(s): d5b56b0

Update web_ui.py

Browse files
Files changed (1) hide show
  1. web_ui.py +67 -226
web_ui.py CHANGED
@@ -11,18 +11,16 @@ from qwen_agent.llm.schema import CONTENT, FILE, IMAGE, NAME, ROLE, USER, Messag
11
  from qwen_agent.log import logger
12
  from qwen_agent.utils.utils import print_traceback
13
 
 
14
  class WebUI:
15
- """A Common chatbot application for agent."""
16
 
17
  def __init__(self, agent: Union[Agent, MultiAgentHub, List[Agent]], chatbot_config: Optional[dict] = None):
18
  """
19
- Initialization the chatbot.
20
-
21
  Args:
22
- agent: The agent or a list of agents,
23
- supports various types of agents such as Assistant, GroupChat, Router, etc.
24
- chatbot_config: The chatbot configuration.
25
- Set the configuration as {'user.name': '', 'user.avatar': '', 'agent.avatar': '', 'input.placeholder': '', 'prompt.suggestions': []}.
26
  """
27
  chatbot_config = chatbot_config or {}
28
 
@@ -36,7 +34,7 @@ class WebUI:
36
  self.agent_list = [agent]
37
  self.agent_hub = None
38
 
39
- user_name = chatbot_config.get('user.name', 'user')
40
  self.user_config = {
41
  'name': user_name,
42
  'avatar': chatbot_config.get(
@@ -49,21 +47,24 @@ class WebUI:
49
  'name': agent.name,
50
  'avatar': chatbot_config.get(
51
  'agent.avatar',
52
- os.path.join(os.path.dirname(__file__), 'assets/logo.jpeg'),
53
  ),
54
- 'description': agent.description or "I'm a helpful assistant.",
55
  } for agent in self.agent_list]
56
 
57
- self.input_placeholder = chatbot_config.get('input.placeholder', '跟我聊聊吧~')
58
  self.prompt_suggestions = chatbot_config.get('prompt.suggestions', [])
59
  self.verbose = chatbot_config.get('verbose', False)
60
 
61
- """
62
- Run the chatbot.
63
-
64
- Args:
65
- messages: The chat history.
66
- """
 
 
 
67
 
68
  def run(self,
69
  messages: List[Message] = None,
@@ -73,6 +74,11 @@ class WebUI:
73
  concurrency_limit: int = 80,
74
  enable_mention: bool = False,
75
  **kwargs):
 
 
 
 
 
76
  self.run_kwargs = kwargs
77
 
78
  from qwen_agent.gui.gradio import gr, mgr
@@ -82,287 +88,122 @@ class WebUI:
82
  radius_size=gr.themes.utils.sizes.radius_none,
83
  )
84
 
85
- with gr.Blocks(
86
- css=os.path.join(os.path.dirname(__file__), 'assets/appBot.css'),
87
- theme=customTheme,
88
- ) as demo:
89
  history = gr.State([])
90
 
91
  with gr.Row(elem_classes='container'):
92
  with gr.Column(scale=4):
93
- chatbot = mgr.Chatbot(value=convert_history_to_chatbot(messages=messages),
94
- avatar_images=[
95
- self.user_config,
96
- self.agent_config_list,
97
- ],
98
- height=850,
99
- avatar_image_width=80,
100
- flushing=False,
101
- show_copy_button=True,
102
- latex_delimiters=[{
103
- 'left': '\\(',
104
- 'right': '\\)',
105
- 'display': True
106
- }, {
107
- 'left': '\\begin{equation}',
108
- 'right': '\\end{equation}',
109
- 'display': True
110
- }, {
111
- 'left': '\\begin{align}',
112
- 'right': '\\end{align}',
113
- 'display': True
114
- }, {
115
- 'left': '\\begin{alignat}',
116
- 'right': '\\end{alignat}',
117
- 'display': True
118
- }, {
119
- 'left': '\\begin{gather}',
120
- 'right': '\\end{gather}',
121
- 'display': True
122
- }, {
123
- 'left': '\\begin{CD}',
124
- 'right': '\\end{CD}',
125
- 'display': True
126
- }, {
127
- 'left': '\\[',
128
- 'right': '\\]',
129
- 'display': True
130
- }])
131
-
132
- input = mgr.MultimodalInput(placeholder=self.input_placeholder, upload_button_props=dict(visible=False))
133
 
134
  with gr.Column(scale=1):
135
  if len(self.agent_list) > 1:
136
  agent_selector = gr.Dropdown(
137
  [(agent.name, i) for i, agent in enumerate(self.agent_list)],
138
- label='Agents',
139
- info='选择一个Agent',
140
  value=0,
141
  interactive=True,
142
  )
143
 
144
  agent_info_block = self._create_agent_info_block()
145
 
146
- # agent_plugins_block = self._create_agent_plugins_block()
147
-
148
  if self.prompt_suggestions:
149
  gr.Examples(
150
- label='推荐对话',
151
  examples=self.prompt_suggestions,
152
- inputs=[input],
153
  )
154
 
155
- if len(self.agent_list) > 1:
156
- agent_selector.change(
157
- fn=self.change_agent,
158
- inputs=[agent_selector],
159
- outputs=[agent_selector, agent_info_block, agent_plugins_block],
160
- queue=False,
161
- )
162
-
163
- input_promise = input.submit(
164
  fn=self.add_text,
165
- inputs=[input, chatbot, history],
166
- outputs=[input, chatbot, history],
167
  queue=False,
168
  )
169
 
170
- if len(self.agent_list) > 1 and enable_mention:
171
- input_promise = input_promise.then(
172
- self.add_mention,
173
- [chatbot, agent_selector],
174
- [chatbot, agent_selector],
175
- ).then(
176
- self.agent_run,
177
- [chatbot, history, agent_selector],
178
- [chatbot, history, agent_selector],
179
- )
180
- else:
181
- input_promise = input_promise.then(
182
- self.agent_run,
183
- [chatbot, history],
184
- [chatbot, history],
185
- )
186
 
187
- input_promise.then(self.flushed, None, [input])
188
-
189
- demo.load(None)
190
-
191
- demo.queue(default_concurrency_limit=concurrency_limit).launch(share=share,
192
- server_name=server_name,
193
- server_port=server_port)
194
-
195
- def change_agent(self, agent_selector):
196
- yield agent_selector, self._create_agent_info_block(agent_selector), self._create_agent_plugins_block(
197
- agent_selector)
198
 
199
  def add_text(self, _input, _chatbot, _history):
 
 
 
200
  from qwen_agent.gui.gradio import gr
201
  if _input.text == "/clear":
202
  _chatbot = []
203
  _history.clear()
204
  yield gr.update(interactive=False, value=""), _chatbot, _history
205
  return
206
-
207
- if _history:
208
- gr.Warning("Only the most recent query is retained because multi-turn conversations are not currently supported.", duration=5)
209
- _chatbot = []
210
- _history.clear()
211
 
212
  _history.append({
213
  ROLE: USER,
214
- CONTENT: [{
215
- 'text': _input.text
216
- }],
217
  })
218
 
219
  if self.user_config[NAME]:
220
  _history[-1][NAME] = self.user_config[NAME]
221
 
222
- if _input.files:
223
- for file in _input.files:
224
- if file.mime_type.startswith('image/'):
225
- _history[-1][CONTENT].append({IMAGE: 'file://' + file.path})
226
- else:
227
- _history[-1][CONTENT].append({FILE: file.path})
228
-
229
  _chatbot.append([_input, None])
230
 
231
  yield gr.update(interactive=False, value=None), _chatbot, _history
232
 
233
- def add_mention(self, _chatbot, _agent_selector):
234
- if len(self.agent_list) == 1:
235
- yield _chatbot, _agent_selector
236
-
237
- query = _chatbot[-1][0].text
238
- match = re.search(r'@\w+\b', query)
239
- if match:
240
- _agent_selector = self._get_agent_index_by_name(match.group()[1:])
241
-
242
- agent_name = self.agent_list[_agent_selector].name
243
-
244
- if ('@' + agent_name) not in query and self.agent_hub is None:
245
- _chatbot[-1][0].text = '@' + agent_name + ' ' + query
246
-
247
- yield _chatbot, _agent_selector
248
-
249
  def agent_run(self, _chatbot, _history, _agent_selector=None):
 
 
 
250
  if not _history:
251
- if _agent_selector is not None:
252
- yield _chatbot, _history, _agent_selector
253
- else:
254
- yield _chatbot, _history
255
  return
256
 
257
-
258
  if self.verbose:
259
- logger.info('agent_run input:\n' + pprint.pformat(_history, indent=2))
260
-
261
- num_input_bubbles = len(_chatbot) - 1
262
- num_output_bubbles = 1
263
- _chatbot[-1][1] = [None for _ in range(len(self.agent_list))]
264
 
265
  agent_runner = self.agent_list[_agent_selector or 0]
266
- if self.agent_hub:
267
- agent_runner = self.agent_hub
268
  responses = []
269
  for responses in agent_runner.run(_history, **self.run_kwargs):
270
- # usage = responses.usage
271
- # responses = [Message(ASSISTANT, responses.output.choices[0].message.content)]
272
-
273
  if not responses:
274
  continue
275
- if responses[-1][CONTENT] == PENDING_USER_INPUT:
276
- logger.info('Interrupted. Waiting for user input!')
277
- break
278
 
279
  display_responses = convert_fncall_to_text(responses)
280
  if not display_responses:
281
  continue
282
- if display_responses[-1][CONTENT] is None:
283
- continue
284
 
285
- while len(display_responses) > num_output_bubbles:
286
- # Create a new chat bubble
287
- _chatbot.append([None, None])
288
- _chatbot[-1][1] = [None for _ in range(len(self.agent_list))]
289
- num_output_bubbles += 1
290
 
291
- assert num_output_bubbles == len(display_responses)
292
- assert num_input_bubbles + num_output_bubbles == len(_chatbot)
293
-
294
- for i, rsp in enumerate(display_responses):
295
- agent_index = self._get_agent_index_by_name(rsp[NAME])
296
- _chatbot[num_input_bubbles + i][1][agent_index] = rsp[CONTENT]
297
-
298
- if len(self.agent_list) > 1:
299
- _agent_selector = agent_index
300
-
301
- if _agent_selector is not None:
302
- yield _chatbot, _history, _agent_selector
303
- else:
304
- yield _chatbot, _history
305
-
306
- if responses:
307
- _history.extend([res for res in responses if res[CONTENT] != PENDING_USER_INPUT])
308
-
309
- if _agent_selector is not None:
310
- yield _chatbot, _history, _agent_selector
311
- else:
312
  yield _chatbot, _history
313
 
314
- if self.verbose:
315
- logger.info('agent_run response:\n' + pprint.pformat(responses, indent=2))
316
 
317
  def flushed(self):
318
  from qwen_agent.gui.gradio import gr
319
-
320
  return gr.update(interactive=True)
321
 
322
- def _get_agent_index_by_name(self, agent_name):
323
- if agent_name is None:
324
- return 0
325
-
326
- try:
327
- agent_name = agent_name.strip()
328
- for i, agent in enumerate(self.agent_list):
329
- if agent.name == agent_name:
330
- return i
331
- return 0
332
- except Exception:
333
- print_traceback()
334
- return 0
335
-
336
  def _create_agent_info_block(self, agent_index=0):
337
  from qwen_agent.gui.gradio import gr
338
 
339
- agent_config_interactive = self.agent_config_list[agent_index]
340
-
341
  return gr.HTML(
342
  format_cover_html(
343
- bot_name=agent_config_interactive['name'],
344
- bot_description=agent_config_interactive['description'],
345
- bot_avatar=agent_config_interactive['avatar'],
346
- ))
347
-
348
- def _create_agent_plugins_block(self, agent_index=0):
349
- from qwen_agent.gui.gradio import gr
350
-
351
- agent_interactive = self.agent_list[agent_index]
352
-
353
- if agent_interactive.function_map:
354
- capabilities = [key for key in agent_interactive.function_map.keys()]
355
- return gr.CheckboxGroup(
356
- label='插件',
357
- value=capabilities,
358
- choices=capabilities,
359
- interactive=False,
360
- )
361
-
362
- else:
363
- return gr.CheckboxGroup(
364
- label='插件',
365
- value=[],
366
- choices=[],
367
- interactive=False,
368
  )
 
 
11
  from qwen_agent.log import logger
12
  from qwen_agent.utils.utils import print_traceback
13
 
14
+
15
  class WebUI:
16
+ """A chatbot application for EV advantages."""
17
 
18
  def __init__(self, agent: Union[Agent, MultiAgentHub, List[Agent]], chatbot_config: Optional[dict] = None):
19
  """
20
+ Initialize the chatbot.
 
21
  Args:
22
+ agent: The agent or a list of agents (Assistant or MultiAgentHub).
23
+ chatbot_config: Configuration for the chatbot, including placeholder text and prompts.
 
 
24
  """
25
  chatbot_config = chatbot_config or {}
26
 
 
34
  self.agent_list = [agent]
35
  self.agent_hub = None
36
 
37
+ user_name = chatbot_config.get('user.name', 'User')
38
  self.user_config = {
39
  'name': user_name,
40
  'avatar': chatbot_config.get(
 
47
  'name': agent.name,
48
  'avatar': chatbot_config.get(
49
  'agent.avatar',
50
+ self._resolve_logo_path('logo.jpeg')
51
  ),
52
+ 'description': agent.description or "I'm here to help with EV advantages.",
53
  } for agent in self.agent_list]
54
 
55
+ self.input_placeholder = chatbot_config.get('input.placeholder', "Start your EV-related conversation here...")
56
  self.prompt_suggestions = chatbot_config.get('prompt.suggestions', [])
57
  self.verbose = chatbot_config.get('verbose', False)
58
 
59
+ def _resolve_logo_path(self, filename: str) -> str:
60
+ """
61
+ Resolve the avatar/logo path, falling back to a default if not found.
62
+ """
63
+ path = os.path.join('/home/user/app', filename)
64
+ if not os.path.exists(path):
65
+ logger.warning(f"Avatar file '{filename}' not found. Using placeholder.")
66
+ return os.path.join('/home/user/app', 'default_logo.jpeg')
67
+ return path
68
 
69
  def run(self,
70
  messages: List[Message] = None,
 
74
  concurrency_limit: int = 80,
75
  enable_mention: bool = False,
76
  **kwargs):
77
+ """
78
+ Run the chatbot interface.
79
+ Args:
80
+ messages: The initial chat history (if any).
81
+ """
82
  self.run_kwargs = kwargs
83
 
84
  from qwen_agent.gui.gradio import gr, mgr
 
88
  radius_size=gr.themes.utils.sizes.radius_none,
89
  )
90
 
91
+ with gr.Blocks(css=os.path.join(os.path.dirname(__file__), 'assets/appBot.css'), theme=customTheme) as demo:
 
 
 
92
  history = gr.State([])
93
 
94
  with gr.Row(elem_classes='container'):
95
  with gr.Column(scale=4):
96
+ chatbot = mgr.Chatbot(
97
+ value=convert_history_to_chatbot(messages=messages),
98
+ avatar_images=[self.user_config, self.agent_config_list],
99
+ height=850,
100
+ avatar_image_width=80,
101
+ flushing=False,
102
+ show_copy_button=True,
103
+ latex_delimiters=[{'left': '\\(', 'right': '\\)', 'display': True}]
104
+ )
105
+
106
+ input_box = mgr.MultimodalInput(placeholder=self.input_placeholder, upload_button_props=dict(visible=False))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
 
108
  with gr.Column(scale=1):
109
  if len(self.agent_list) > 1:
110
  agent_selector = gr.Dropdown(
111
  [(agent.name, i) for i, agent in enumerate(self.agent_list)],
112
+ label='Select Agent',
113
+ info='Choose an Agent',
114
  value=0,
115
  interactive=True,
116
  )
117
 
118
  agent_info_block = self._create_agent_info_block()
119
 
 
 
120
  if self.prompt_suggestions:
121
  gr.Examples(
122
+ label='Suggested Conversations',
123
  examples=self.prompt_suggestions,
124
+ inputs=[input_box],
125
  )
126
 
127
+ input_promise = input_box.submit(
 
 
 
 
 
 
 
 
128
  fn=self.add_text,
129
+ inputs=[input_box, chatbot, history],
130
+ outputs=[input_box, chatbot, history],
131
  queue=False,
132
  )
133
 
134
+ input_promise.then(
135
+ self.agent_run,
136
+ [chatbot, history],
137
+ [chatbot, history],
138
+ ).then(self.flushed, None, [input_box])
 
 
 
 
 
 
 
 
 
 
 
139
 
140
+ demo.queue(default_concurrency_limit=concurrency_limit).launch(
141
+ share=share, server_name=server_name, server_port=server_port
142
+ )
 
 
 
 
 
 
 
 
143
 
144
  def add_text(self, _input, _chatbot, _history):
145
+ """
146
+ Process user input and update the chat history.
147
+ """
148
  from qwen_agent.gui.gradio import gr
149
  if _input.text == "/clear":
150
  _chatbot = []
151
  _history.clear()
152
  yield gr.update(interactive=False, value=""), _chatbot, _history
153
  return
 
 
 
 
 
154
 
155
  _history.append({
156
  ROLE: USER,
157
+ CONTENT: [{'text': _input.text}],
 
 
158
  })
159
 
160
  if self.user_config[NAME]:
161
  _history[-1][NAME] = self.user_config[NAME]
162
 
 
 
 
 
 
 
 
163
  _chatbot.append([_input, None])
164
 
165
  yield gr.update(interactive=False, value=None), _chatbot, _history
166
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  def agent_run(self, _chatbot, _history, _agent_selector=None):
168
+ """
169
+ Run the agent and generate responses.
170
+ """
171
  if not _history:
172
+ yield _chatbot, _history
 
 
 
173
  return
174
 
 
175
  if self.verbose:
176
+ logger.info('Agent run input:\n' + pprint.pformat(_history, indent=2))
 
 
 
 
177
 
178
  agent_runner = self.agent_list[_agent_selector or 0]
 
 
179
  responses = []
180
  for responses in agent_runner.run(_history, **self.run_kwargs):
 
 
 
181
  if not responses:
182
  continue
 
 
 
183
 
184
  display_responses = convert_fncall_to_text(responses)
185
  if not display_responses:
186
  continue
 
 
187
 
188
+ _chatbot[-1][1] = display_responses[-1][CONTENT]
 
 
 
 
189
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
  yield _chatbot, _history
191
 
192
+ if responses:
193
+ _history.extend([res for res in responses])
194
 
195
  def flushed(self):
196
  from qwen_agent.gui.gradio import gr
 
197
  return gr.update(interactive=True)
198
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  def _create_agent_info_block(self, agent_index=0):
200
  from qwen_agent.gui.gradio import gr
201
 
202
+ agent_config = self.agent_config_list[agent_index]
 
203
  return gr.HTML(
204
  format_cover_html(
205
+ bot_name=agent_config['name'],
206
+ bot_description=agent_config['description'],
207
+ bot_avatar=agent_config['avatar'],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  )
209
+ )