[User] Show me the code for 'qwen_server\assistant_server.py' in Qwen-Agent.

[Assistant]
```python
# Copyright 2023 The Qwen team, Alibaba Group. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import json
import os
import time
from pathlib import Path

import jsonlines

try:
    import add_qwen_libs  # NOQA
except ImportError:
    pass

from qwen_agent.agents import Assistant
from qwen_agent.gui import gr
from qwen_agent.gui.utils import get_avatar_image
from qwen_agent.llm.base import ModelServiceError
from qwen_agent.log import logger
from qwen_server.schema import GlobalConfig
from qwen_server.utils import read_history, read_meta_data_by_condition, save_history

server_config_path = Path(__file__).resolve().parent / 'server_config.json'
with open(server_config_path, 'r') as f:
    server_config = json.load(f)
    server_config = GlobalConfig(**server_config)

llm_config = None

if hasattr(server_config.server, 'llm'):
    llm_config = {
        'model': server_config.server.llm,
        'api_key': server_config.server.api_key,
        'model_server': server_config.server.model_server
    }

assistant = Assistant(llm=llm_config)

with open(Path(__file__).resolve().parent / 'css/main.css', 'r') as f:
    css = f.read()
with open(Path(__file__).resolve().parent / 'js/main.js', 'r') as f:
    js = f.read()
cache_file_popup_url = os.path.join(server_config.path.work_space_root, 'popup_url.jsonl')
meta_file = os.path.join(server_config.path.work_space_root, 'meta_data.jsonl')
history_dir = os.path.join(server_config.path.work_space_root, 'history')

def add_text(history, text):
    history = history + [(text, None)]
    return history, gr.update(value='', interactive=False)

def rm_text(history):
    if not history:
        gr.Warning('No input content!')
    elif not history[-1][1]:
        return history, gr.update(value='', interactive=False)
    else:
        history = history[:-1] + [(history[-1][0], None)]
        return history, gr.update(value='', interactive=False)

def set_url():
    lines = []
    if not os.path.exists(cache_file_popup_url):
        # Only able to remind the situation of first browsing failure
        gr.Error('Oops, it seems that the page cannot be opened due to network issues.')

    for line in jsonlines.open(cache_file_popup_url):
        lines.append(line)
    logger.info('The current access page is: ' + lines[-1]['url'])
    return lines[-1]['url']

def bot(history):
    page_url = set_url()
    if not history:
        yield history
    else:
        messages = [{'role': 'user', 'content': [{'text': history[-1][0]}, {'file': page_url}]}]
        history[-1][1] = ''
        try:
            response = assistant.run(messages=messages, max_ref_token=server_config.server.max_ref_token)
            for rsp in response:
                if rsp:
                    history[-1][1] = rsp[-1]['content']
                    yield history
        except ModelServiceError as ex:
            history[-1][1] = str(ex)
            yield history
        except Exception as ex:
            raise ValueError(ex)

        save_history(history, page_url, history_dir)

def init_chatbot():
    time.sleep(1)
    page_url = set_url()
    response = read_meta_data_by_condition(meta_file, url=page_url)
    if not response:
        gr.Info(
            "Please add this page to Qwen's Reading List first! If you have already added it, please reopen later...")
    elif response == '[CACHING]':
        gr.Info('Please reopen later, Qwen is analyzing this page...')
    else:
        return read_history(page_url, history_dir)

def clear_session():
    page_url = set_url()
    save_history(None, page_url, history_dir)
    return None

with gr.Blocks(css=css, theme='soft') as demo:
    chatbot = gr.Chatbot([], elem_id='chatbot', height=480, avatar_images=(None, get_avatar_image('qwen')))
    with gr.Row():
        with gr.Column(scale=7):
            txt = gr.Textbox(show_label=False, placeholder='Chat with Qwen...', container=False)
        with gr.Column(scale=1, min_width=0):
            clr_bt = gr.Button('🧹', elem_classes='bt_small_font')
        with gr.Column(scale=1, min_width=0):
            stop_bt = gr.Button('🚫', elem_classes='bt_small_font')
        with gr.Column(scale=1, min_width=0):
            re_bt = gr.Button('🔁', elem_classes='bt_small_font')

    txt_msg = txt.submit(add_text, [chatbot, txt], [chatbot, txt], queue=False).then(bot, chatbot, chatbot)
    txt_msg.then(lambda: gr.update(interactive=True), None, [txt], queue=False)

    clr_bt.click(clear_session, None, chatbot, queue=False)
    re_txt_msg = re_bt.click(rm_text, [chatbot], [chatbot, txt], queue=False).then(bot, chatbot, chatbot)
    re_txt_msg.then(lambda: gr.update(interactive=True), None, [txt], queue=False)

    stop_bt.click(None, None, None, cancels=[txt_msg, re_txt_msg], queue=False)

    demo.load(init_chatbot, None, chatbot)

demo.queue().launch(server_name=server_config.server.server_host, server_port=server_config.server.app_in_browser_port)

```


[User] Show me the code for 'qwen_server\database_server.py' in Qwen-Agent.

[Assistant]
```python
# Copyright 2023 The Qwen team, Alibaba Group. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import json
import multiprocessing
import os
from pathlib import Path

import jsonlines
import uvicorn
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles

try:
    import add_qwen_libs  # NOQA
except ImportError:
    pass

from qwen_agent.log import logger
from qwen_agent.memory import Memory
from qwen_agent.utils.utils import get_basename_from_url, get_file_type, get_local_ip, hash_sha256, save_text_to_file
from qwen_server.schema import GlobalConfig
from qwen_server.utils import rm_browsing_meta_data, save_browsing_meta_data, save_history

# Read config
with open(Path(__file__).resolve().parent / 'server_config.json', 'r') as f:
    server_config = json.load(f)
    server_config = GlobalConfig(**server_config)

# This APP only requires storage capacity, so using the memory module alone
mem = Memory()

app = FastAPI()

logger.info(get_local_ip())
origins = [
    'http://127.0.0.1:' + str(server_config.server.workstation_port),
    'http://localhost:' + str(server_config.server.workstation_port),
    'http://0.0.0.0:' + str(server_config.server.workstation_port),
    'http://' + get_local_ip() + ':' + str(server_config.server.workstation_port),
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=['*'],
    allow_headers=['*'],
)

app.mount('/static', StaticFiles(directory=server_config.path.code_interpreter_ws), name='static')

cache_file_popup_url = os.path.join(server_config.path.work_space_root, 'popup_url.jsonl')
meta_file = os.path.join(server_config.path.work_space_root, 'meta_data.jsonl')
history_dir = os.path.join(server_config.path.work_space_root, 'history')

def update_pop_url(url: str):
    if not get_file_type(url) in ['pdf', 'docx', 'pptx', 'txt']:
        url = os.path.join(server_config.path.download_root, hash_sha256(url), get_basename_from_url(url))
    new_line = {'url': url}

    with jsonlines.open(cache_file_popup_url, mode='w') as writer:
        writer.write(new_line)

    return 'Update URL'

def change_checkbox_state(key):
    with open(meta_file, 'r', encoding='utf-8') as file:
        meta_info = json.load(file)
    meta_info[key[3:]]['checked'] = (not meta_info[key[3:]]['checked'])
    with open(meta_file, 'w', encoding='utf-8') as file:
        json.dump(meta_info, file, indent=4)
    return {'result': 'changed'}

def cache_page(**kwargs):
    url = kwargs.get('url', '')

    page_content = kwargs.get('content', '')
    if page_content and not get_file_type(url) in ['pdf', 'docx', 'pptx', 'txt']:
        # map to local url
        os.makedirs(os.path.join(server_config.path.download_root, hash_sha256(url)), exist_ok=True)
        url = os.path.join(server_config.path.download_root, hash_sha256(url), get_basename_from_url(url))
        save_browsing_meta_data(url, '[CACHING]', meta_file)
        # rm history
        save_history(None, url, history_dir)
        save_text_to_file(url, page_content)
    else:
        save_browsing_meta_data(url, '[CACHING]', meta_file)
        # rm history
        save_history(None, url, history_dir)
    try:
        *_, last = mem.run([{'role': 'user', 'content': [{'file': url}]}])
        title = get_basename_from_url(url)
        save_browsing_meta_data(url, title, meta_file)
    except Exception:
        rm_browsing_meta_data(url, meta_file)

@app.post('/endpoint')
async def web_listening(request: Request):
    data = await request.json()
    msg_type = data['task']

    if msg_type == 'change_checkbox':
        rsp = change_checkbox_state(data['ckid'])
    elif msg_type == 'cache':
        cache_obj = multiprocessing.Process(target=cache_page, kwargs=data)
        cache_obj.start()
        # rsp = cache_data(data, cache_file)
        rsp = 'caching'
    elif msg_type == 'pop_url':
        # What a misleading name! pop_url actually means add_url. pop is referring to the pop_up ui.
        rsp = update_pop_url(data['url'])
    else:
        raise NotImplementedError

    return JSONResponse(content=rsp)

if __name__ == '__main__':
    uvicorn.run(app='database_server:app',
                host=server_config.server.server_host,
                port=server_config.server.fast_api_port)

```


[User] Show me the code for 'qwen_server\output_beautify.py' in Qwen-Agent.

[Assistant]
```python
# Copyright 2023 The Qwen team, Alibaba Group. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import json5

from qwen_agent.log import logger
from qwen_agent.utils.utils import extract_code, extract_urls, print_traceback

FN_NAME = 'Action'
FN_ARGS = 'Action Input'
FN_RESULT = 'Observation'
FN_EXIT = 'Response'

def extract_obs(text):
    k = text.rfind('\nObservation:')
    j = text.rfind('\nThought:')
    obs = text[k + len('\nObservation:'):j]
    return obs.strip()

def format_answer(text):
    if 'code_interpreter' in text:
        rsp = ''
        code = extract_code(text)
        rsp += ('\n```py\n' + code + '\n```\n')
        obs = extract_obs(text)
        if '![fig' in obs:
            rsp += obs
        return rsp
    elif 'image_gen' in text:
        # get url of FA
        # img_urls = URLExtract().find_urls(text.split("Final Answer:")[-1].strip())
        obs = text.split(f'{FN_RESULT}:')[-1].split(f'{FN_EXIT}:')[0].strip()
        img_urls = []
        if obs:
            logger.info(repr(obs))
            try:
                obs = json5.loads(obs)
                img_urls.append(obs['image_url'])
            except Exception:
                print_traceback()
                img_urls = []
        if not img_urls:
            img_urls = extract_urls(text.split(f'{FN_EXIT}:')[-1].strip())
        logger.info(img_urls)
        rsp = ''
        for x in img_urls:
            rsp += '\n![picture](' + x.strip() + ')'
        return rsp
    else:
        return text.split(f'{FN_EXIT}:')[-1].strip()

```


[User] Show me the code for 'qwen_server\schema.py' in Qwen-Agent.

[Assistant]
```python
# Copyright 2023 The Qwen team, Alibaba Group. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from pydantic import BaseModel

class PathConfig(BaseModel):
    work_space_root: str
    download_root: str
    code_interpreter_ws: str

class ServerConfig(BaseModel):
    server_host: str
    fast_api_port: int
    app_in_browser_port: int
    workstation_port: int
    model_server: str
    api_key: str
    llm: str
    max_ref_token: int
    max_days: int

    class Config:
        protected_namespaces = ()

class GlobalConfig(BaseModel):
    path: PathConfig
    server: ServerConfig

```


[User] Show me the code for 'qwen_server\utils.py' in Qwen-Agent.

[Assistant]
```python
# Copyright 2023 The Qwen team, Alibaba Group. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import datetime
import json
import os

from qwen_agent.utils.utils import get_basename_from_url

def save_browsing_meta_data(url: str, title: str, meta_file: str):
    if os.path.exists(meta_file):
        with open(meta_file, 'r', encoding='utf-8') as file:
            meta_info = json.load(file)
    else:
        meta_info = {}
    now_time = str(datetime.date.today())
    meta_info[url] = {
        'url': url,
        'time': now_time,
        'title': title,
        'checked': True,
    }

    with open(meta_file, 'w', encoding='utf-8') as file:
        json.dump(meta_info, file, indent=4)

def rm_browsing_meta_data(url: str, meta_file: str):
    if os.path.exists(meta_file):
        with open(meta_file, 'r', encoding='utf-8') as file:
            meta_info = json.load(file)
    else:
        meta_info = {}

    if url in meta_info:
        meta_info.pop(url)
        with open(meta_file, 'w', encoding='utf-8') as file:
            json.dump(meta_info, file, indent=4)

def read_meta_data_by_condition(meta_file: str, **kwargs):
    if os.path.exists(meta_file):
        with open(meta_file, 'r', encoding='utf-8') as file:
            meta_info = json.load(file)
    else:
        meta_info = {}
        return []

    if 'url' in kwargs:
        if kwargs['url'] in meta_info:
            return meta_info[kwargs['url']]
        else:
            return ''

    records = meta_info.values()

    if 'time_limit' in kwargs:
        filter_records = []
        for x in records:
            if kwargs['time_limit'][0] <= x['time'] <= kwargs['time_limit'][1]:
                filter_records.append(x)
        records = filter_records
    if 'checked' in kwargs:
        filter_records = []
        for x in records:
            if x['checked']:
                filter_records.append(x)
        records = filter_records

    return records

def save_history(history, url, history_dir):
    history = history or []
    history_file = os.path.join(history_dir, get_basename_from_url(url) + '.json')
    if not os.path.exists(history_dir):
        os.makedirs(history_dir)
    with open(history_file, 'w', encoding='utf-8') as file:
        json.dump(history, file, indent=4)

def read_history(url, history_dir):
    history_file = os.path.join(history_dir, get_basename_from_url(url) + '.json')
    if os.path.exists(history_file):
        with open(history_file, 'r', encoding='utf-8') as file:
            data = json.load(file)
            if data:
                return data
            else:
                return []
    return []

```


[User] Show me the code for 'qwen_server\workstation_server.py' in Qwen-Agent.

[Assistant]
```python
# Copyright 2023 The Qwen team, Alibaba Group. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import datetime
import json
import os
from pathlib import Path

try:
    import add_qwen_libs  # NOQA
except ImportError:
    pass
from qwen_agent.agents import ArticleAgent, Assistant, ReActChat
from qwen_agent.gui import gr, mgr, ms
from qwen_agent.gui.utils import get_avatar_image
from qwen_agent.llm import get_chat_model
from qwen_agent.llm.base import ModelServiceError
from qwen_agent.memory import Memory
from qwen_agent.tools.simple_doc_parser import PARSER_SUPPORTED_FILE_TYPES
from qwen_agent.utils.utils import get_basename_from_url, get_file_type, has_chinese_chars, save_text_to_file
from qwen_server import output_beautify
from qwen_server.schema import GlobalConfig
from qwen_server.utils import read_meta_data_by_condition, save_browsing_meta_data

# Read config
with open(Path(__file__).resolve().parent / 'server_config.json', 'r') as f:
    server_config = json.load(f)
    server_config = GlobalConfig(**server_config)
llm_config = None

if hasattr(server_config.server, 'llm'):
    llm_config = {
        'model': server_config.server.llm,
        'api_key': server_config.server.api_key,
        'model_server': server_config.server.model_server
    }

app_global_para = {
    'time': [str(datetime.date.today()), str(datetime.date.today())],
    'messages': [],
    'last_turn_msg_id': [],
    'is_first_upload': True,
    'uploaded_ci_file': '',
    'pure_messages': [],
    'pure_last_turn_msg_id': [],
}

DOC_OPTION = 'Document QA'
CI_OPTION = 'Code Interpreter'
CODE_FLAG = '/code'
PLUGIN_FLAG = '/plug'
TITLE_FLAG = '/title'

with open(Path(__file__).resolve().parent / 'css/main.css', 'r') as f:
    css = f.read()
with open(Path(__file__).resolve().parent / 'js/main.js', 'r') as f:
    js = f.read()

meta_file = os.path.join(server_config.path.work_space_root, 'meta_data.jsonl')

def add_text(history, text):
    history = history + [(text, None)]
    app_global_para['last_turn_msg_id'] = []
    return history, gr.update(value='', interactive=False)

def pure_add_text(history, text):
    history = history + [(text, None)]
    app_global_para['pure_last_turn_msg_id'] = []
    return history, gr.update(value='', interactive=False)

def rm_text(history):
    if not history:
        gr.Warning('No input content!')
    elif not history[-1][1]:
        return history, gr.update(value='', interactive=False)
    else:
        history = history[:-1] + [(history[-1][0].text, None)]
        return history, gr.update(value='', interactive=False)

def chat_clear():
    app_global_para['messages'] = []
    return None, None

def chat_clear_pure():
    app_global_para['pure_messages'] = []
    return []

def chat_clear_last():
    for index in app_global_para['last_turn_msg_id'][::-1]:
        del app_global_para['messages'][index]
    app_global_para['last_turn_msg_id'] = []

def pure_chat_clear_last():
    for index in app_global_para['pure_last_turn_msg_id'][::-1]:
        del app_global_para['pure_messages'][index]
    app_global_para['pure_last_turn_msg_id'] = []

def add_file(file, chosen_plug):
    display_path = get_basename_from_url(file.name)

    if chosen_plug == CI_OPTION:
        app_global_para['uploaded_ci_file'] = file.name
        app_global_para['is_first_upload'] = True
        return display_path
    f_type = get_file_type(file)
    if f_type not in PARSER_SUPPORTED_FILE_TYPES:
        display_path = (
            f'Upload failed: only adding {", ".join(PARSER_SUPPORTED_FILE_TYPES)} as references is supported!')
    else:
        # cache file
        try:
            mem = Memory()
            *_, last = mem.run([{'role': 'user', 'content': [{'file': file.name}]}])
            title = display_path
            save_browsing_meta_data(file.name, title, meta_file)

        except Exception as ex:
            raise ValueError(ex)

    return display_path

def update_app_global_para(date1, date2):
    app_global_para['time'][0] = date1
    app_global_para['time'][1] = date2

def refresh_date():
    option = [str(datetime.date.today() - datetime.timedelta(days=i)) for i in range(server_config.server.max_days)]
    return (gr.update(choices=option,
                      value=str(datetime.date.today())), gr.update(choices=option, value=str(datetime.date.today())))

def update_browser_list():
    br_list = read_meta_data_by_condition(meta_file, time_limit=app_global_para['time'])
    if not br_list:
        return 'No browsing records'

    br_list = [[line['url'], line['title'], line['checked']] for line in br_list]

    res = '<ol>{bl}</ol>'
    bl = ''
    for i, x in enumerate(br_list):
        ck = '<input type="checkbox" class="custom-checkbox" id="ck-' + x[0] + '" '
        if x[2]:
            ck += 'checked>'
        else:
            ck += '>'
        bl += '<li>{checkbox}{title}<a href="{url}"> [url]</a></li>'.format(checkbox=ck, url=x[0], title=x[1])
    res = res.format(bl=bl)
    return res

def layout_to_right(text):
    return text, text

def download_text(text):
    now = datetime.datetime.now()
    current_time = now.strftime('%Y-%m-%d_%H-%M-%S')
    filename = f'file_{current_time}.md'
    save_path = os.path.join(server_config.path.download_root, filename)
    try:
        save_text_to_file(save_path, text)
        gr.Info(f'Saved to {save_path}')
    except Exception as ex:
        gr.Error(f'Failed to save this file.\n {str(ex)}')

def choose_plugin(chosen_plugin):
    if chosen_plugin == CI_OPTION:
        gr.Info('Code execution is NOT sandboxed. Do NOT ask Qwen to perform dangerous tasks.')
    if chosen_plugin == CI_OPTION or chosen_plugin == DOC_OPTION:
        return gr.update(interactive=True), None
    else:
        return gr.update(interactive=False), None

def pure_bot(history):
    if not history:
        yield history
    else:
        history[-1][1] = ''
        message = [{'role': 'user', 'content': history[-1][0].text, 'name': 'pure_chat_user'}]
        try:
            llm = get_chat_model(llm_config)
            response = llm.chat(messages=app_global_para['pure_messages'] + message)
            rsp = []
            for rsp in response:
                if rsp:
                    history[-1][1] = rsp[-1]['content']
                    yield history

            # Record the conversation history when the conversation succeeds
            app_global_para['pure_last_turn_msg_id'].append(len(app_global_para['pure_messages']))
            app_global_para['pure_messages'].extend(message)  # New user message
            app_global_para['pure_last_turn_msg_id'].append(len(app_global_para['pure_messages']))
            app_global_para['pure_messages'].extend(rsp)  # The response

        except ModelServiceError as ex:
            history[-1][1] = str(ex)
            yield history
        except Exception as ex:
            raise ValueError(ex)

def keep_only_files_for_name(messages, name):
    new_messages = []
    for message in messages:
        if message['role'] == 'user' and ('name' not in message or message['name'] != name):
            # rm files
            if isinstance(message['content'], list):
                new_content = []
                for item in message['content']:
                    for k, v in item.items():
                        if k != 'file':  # rm files
                            new_content.append(item)
                new_messages.append({'role': message['role'], 'content': new_content})
            else:
                new_messages.append(message)
        else:
            new_messages.append(message)
    return new_messages

def bot(history, chosen_plug):
    if not history:
        yield history
    else:
        history[-1][1] = ''
        if chosen_plug == CI_OPTION:  # use code interpreter
            if app_global_para['uploaded_ci_file'] and app_global_para['is_first_upload']:
                app_global_para['is_first_upload'] = False  # only send file when first upload
                message = [{
                    'role': 'user',
                    'content': [{
                        'text': history[-1][0].text
                    }, {
                        'file': app_global_para['uploaded_ci_file']
                    }],
                    'name': 'ci'
                }]
            else:
                message = [{'role': 'user', 'content': history[-1][0].text, 'name': 'ci'}]
            messages = keep_only_files_for_name(app_global_para['messages'], 'ci') + message
            func_assistant = ReActChat(function_list=['code_interpreter'], llm=llm_config)
            try:
                response = func_assistant.run(messages=messages)
                rsp = []
                for rsp in response:
                    if rsp:
                        history[-1][1] = rsp[-1]['content']
                        yield history
                # append message
                app_global_para['last_turn_msg_id'].append(len(app_global_para['messages']))
                app_global_para['messages'].extend(message)
                app_global_para['last_turn_msg_id'].append(len(app_global_para['messages']))
                app_global_para['messages'].extend(rsp)
            except ModelServiceError as ex:
                history[-1][1] = str(ex)
                yield history
            except Exception as ex:
                raise ValueError(ex)
        else:
            try:
                content = [{'text': history[-1][0].text}]
                # checked files
                for record in read_meta_data_by_condition(meta_file, time_limit=app_global_para['time'], checked=True):
                    content.append({'file': record['url']})
                qa_assistant = Assistant(llm=llm_config)
                message = [{'role': 'user', 'content': content}]
                # rm all files of history
                messages = keep_only_files_for_name(app_global_para['messages'], 'None') + message
                response = qa_assistant.run(messages=messages, max_ref_token=server_config.server.max_ref_token)
                rsp = []
                for rsp in response:
                    if rsp:
                        history[-1][1] = rsp[-1]['content']
                        yield history
                # append message
                app_global_para['last_turn_msg_id'].append(len(app_global_para['messages']))
                app_global_para['messages'].extend(message)
                app_global_para['last_turn_msg_id'].append(len(app_global_para['messages']))
                app_global_para['messages'].extend(rsp)

            except ModelServiceError as ex:
                history[-1][1] = str(ex)
                yield history
            except Exception as ex:
                raise ValueError(ex)

def get_last_one_line_context(text):
    lines = text.split('\n')
    n = len(lines)
    res = ''
    for i in range(n - 1, -1, -1):
        if lines[i].strip():
            res = lines[i]
            break
    return res

def generate(context):
    sp_query = get_last_one_line_context(context)
    if CODE_FLAG in sp_query:  # router to code interpreter
        sp_query = sp_query.split(CODE_FLAG)[-1]
        if has_chinese_chars(sp_query):
            sp_query += ', 必须使用code_interpreter工具'
        else:
            sp_query += ' (Please use code_interpreter.)'

        func_assistant = ReActChat(function_list=['code_interpreter'], llm=llm_config)
        try:
            response = func_assistant.run(messages=[{'role': 'user', 'content': sp_query}])
            for rsp in response:
                if rsp:
                    yield rsp[-1]['content']
        except ModelServiceError as ex:
            yield str(ex)
        except Exception as ex:
            raise ValueError(ex)

    elif PLUGIN_FLAG in sp_query:  # router to plugin
        sp_query = sp_query.split(PLUGIN_FLAG)[-1]
        func_assistant = ReActChat(function_list=['code_interpreter', 'image_gen'], llm=llm_config)
        try:
            response = func_assistant.run(messages=[{'role': 'user', 'content': sp_query}])
            for rsp in response:
                if rsp:
                    yield rsp[-1]['content']
        except ModelServiceError as ex:
            yield str(ex)
        except Exception as ex:
            raise ValueError(ex)

    else:  # router to continue writing
        sp_query_no_title = context
        if TITLE_FLAG in sp_query:  # /title
            sp_query_no_title = sp_query.split(TITLE_FLAG)[-1]

        full_article = False
        if TITLE_FLAG in sp_query:  # /title
            full_article = True
        try:
            writing_assistant = ArticleAgent(llm=llm_config)

            content = [{'text': sp_query_no_title}]
            # checked files
            for record in read_meta_data_by_condition(meta_file, time_limit=app_global_para['time'], checked=True):
                content.append({'file': record['url']})

            response = writing_assistant.run(messages=[{
                'role': 'user',
                'content': content
            }],
                                             max_ref_token=server_config.server.max_ref_token,
                                             full_article=full_article)
            for rsp in response:
                if rsp:
                    yield '\n'.join([x['content'] for x in rsp])
        except ModelServiceError as ex:
            yield str(ex)
        except Exception as ex:
            raise ValueError(ex)

def format_generate(edit, context):
    res = edit
    yield res
    if '> Writing Text:' in context:
        text = context.split('> Writing Text:')[-1].strip()
        res += '\n'
        res += text
        yield res
    elif 'Answer:' in context:
        response = output_beautify.format_answer(context)
        res += '\n'
        res += response
        yield res
    else:
        res += context
        yield res

with gr.Blocks(css=css, js=js, theme='soft') as demo:
    title = gr.Markdown('Qwen Agent: BrowserQwen', elem_classes='title')
    desc = gr.Markdown(
        'This is the editing workstation of BrowserQwen, where Qwen has collected the browsing history. Qwen can assist you in completing your creative work!',
        elem_classes='desc',
    )

    with gr.Row():
        with gr.Column():
            rec = gr.Markdown('Browsing History', elem_classes='rec')
            with gr.Row():
                with gr.Column(scale=3, min_width=0):
                    date1 = gr.Dropdown(
                        [
                            str(datetime.date.today() - datetime.timedelta(days=i))
                            for i in range(server_config.server.max_days)
                        ],
                        value=str(datetime.date.today()),
                        label='Start Date',
                    )
                    date2 = gr.Dropdown(
                        [
                            str(datetime.date.today() - datetime.timedelta(days=i))
                            for i in range(server_config.server.max_days)
                        ],
                        value=str(datetime.date.today()),
                        label='End Date',
                    )
                with gr.Column(scale=7, min_width=0):
                    browser_list = gr.HTML(
                        value='',
                        label='browser_list',
                        elem_classes=['div_tmp', 'add_scrollbar'],
                    )

    with gr.Tab('Editor', elem_id='default-tab'):
        with gr.Row():
            with gr.Column():
                with gr.Row():
                    edit_area = gr.Textbox(
                        value='',
                        elem_classes=['textbox_default', 'add_scrollbar'],
                        lines=30,
                        label='Input',
                        show_copy_button=True,
                    )
                    # token_count = gr.HTML(value='<span>0</span>',
                    #                       elem_classes=[
                    #                           'token-counter',
                    #                           'default-token-counter'
                    #                       ])

                with gr.Row():
                    ctn_bt = gr.Button('Continue', variant='primary')
                    stop_bt = gr.Button('Stop')
                    clr_bt = gr.Button('Clear')
                    dld_bt = gr.Button('Download')

                # with gr.Row():
                #     layout_bt = gr.Button('👉', variant='primary')

            with gr.Column():
                cmd_area = gr.Textbox(lines=10, max_lines=10, label="Qwen's Inner Thought", elem_id='cmd')
                with gr.Tab('Markdown'):
                    # md_out_bt = gr.Button('Render')
                    md_out_area = gr.Markdown(elem_classes=['md_tmp', 'add_scrollbar'])

                with gr.Tab('HTML'):
                    html_out_area = gr.HTML()

                with gr.Tab('Raw'):
                    text_out_area = gr.Textbox(
                        lines=20,
                        label='',
                        elem_classes=['textbox_default_output', 'add_scrollbar'],
                        show_copy_button=True,
                    )
        clk_ctn_bt = ctn_bt.click(generate, edit_area, cmd_area)
        clk_ctn_bt.then(format_generate, [edit_area, cmd_area], edit_area)

        edit_area_change = edit_area.change(layout_to_right, edit_area, [text_out_area, md_out_area])

        stop_bt.click(lambda: None, cancels=[clk_ctn_bt], queue=False)
        clr_bt.click(
            lambda: [None, None, None],
            None,
            [edit_area, cmd_area, md_out_area],
            queue=False,
        )
        dld_bt.click(download_text, edit_area, None)

        # layout_bt.click(layout_to_right,
        #                 edit_area, [text_out_area, md_out_area],
        #                 queue=False)
        gr.Markdown("""
    ### Usage Tips:
    - Browsing History:
        - Start Date/End Date: Selecting the browsed materials for the desired time period, including the start and end dates
        - The browsed materials list: supporting the selection or removal of specific browsing content
    - Editor: In the editing area, you can directly input content or special instructions, and then click the ```Continue``` button to have Qwen assist in completing the editing work:
        - After inputting the content, directly click the ```Continue``` button: Qwen will begin to continue writing based on the browsing information
        - Using special instructions:
            - /title + content: Qwen enables the built-in planning process and writes a complete manuscript
            - /code + content: Qwen enables the code interpreter plugin, writes and runs Python code, and generates replies
            - /plug + content: Qwen enables plugin and select appropriate plugin to generate reply
    - Chat: Interactive area. Qwen generates replies based on given reference materials. Selecting Code Interpreter will enable the code interpreter plugin

        """)

    with gr.Tab('Chat', elem_id='chat-tab'):
        with ms.Application():
            with gr.Column():
                chatbot = mgr.Chatbot(
                    elem_id='chatbot',
                    height=680,
                    show_copy_button=True,
                    avatar_images=[None, get_avatar_image('qwen')],
                    flushing=False,
                )
                with gr.Row():
                    with gr.Column(scale=1, min_width=0):
                        file_btn = gr.UploadButton('Upload', file_types=['file'])

                    with gr.Column(scale=13):
                        chat_txt = gr.Textbox(
                            show_label=False,
                            placeholder='Chat with Qwen...',
                            container=False,
                        )
                    with gr.Column(scale=1, min_width=0):
                        chat_clr_bt = gr.Button('Clear')

                    with gr.Column(scale=1, min_width=0):
                        chat_stop_bt = gr.Button('Stop')
                    with gr.Column(scale=1, min_width=0):
                        chat_re_bt = gr.Button('Again')
                with gr.Row():
                    with gr.Column(scale=2, min_width=0):
                        plug_bt = gr.Dropdown(
                            [CI_OPTION, DOC_OPTION],
                            label='Plugin',
                            info='',
                            value=DOC_OPTION,
                        )
                    with gr.Column(scale=8, min_width=0):
                        hidden_file_path = gr.Textbox(interactive=False, label='The uploaded file is displayed here')

                txt_msg = chat_txt.submit(add_text, [chatbot, chat_txt], [chatbot, chat_txt],
                                          queue=False).then(bot, [chatbot, plug_bt], chatbot)
                txt_msg.then(lambda: gr.update(interactive=True), None, [chat_txt], queue=False)

                re_txt_msg = (chat_re_bt.click(rm_text, [chatbot], [chatbot, chat_txt],
                                               queue=False).then(chat_clear_last, None,
                                                                 None).then(bot, [chatbot, plug_bt], chatbot))
                re_txt_msg.then(lambda: gr.update(interactive=True), None, [chat_txt], queue=False)

                file_msg = file_btn.upload(add_file, [file_btn, plug_bt], [hidden_file_path], queue=False)
                file_msg.then(update_browser_list, None, browser_list)

                chat_clr_bt.click(chat_clear, None, [chatbot, hidden_file_path], queue=False)
                # re_bt.click(re_bot, chatbot, chatbot)
                chat_stop_bt.click(chat_clear_last, None, None, cancels=[txt_msg, re_txt_msg], queue=False)

                plug_bt.change(choose_plugin, plug_bt, [file_btn, hidden_file_path])

    with gr.Tab('Pure Chat', elem_id='pure-chat-tab'):
        gr.Markdown('Note: The chat box on this tab will not use any browsing history!')
        with ms.Application():
            with gr.Column():
                pure_chatbot = mgr.Chatbot(
                    elem_id='pure_chatbot',
                    height=680,
                    show_copy_button=True,
                    avatar_images=[None, get_avatar_image('qwen')],
                    flushing=False,
                )
                with gr.Row():
                    with gr.Column(scale=13):
                        chat_txt = gr.Textbox(
                            show_label=False,
                            placeholder='Chat with Qwen...',
                            container=False,
                        )
                    with gr.Column(scale=1, min_width=0):
                        chat_clr_bt = gr.Button('Clear')
                    with gr.Column(scale=1, min_width=0):
                        chat_stop_bt = gr.Button('Stop')
                    with gr.Column(scale=1, min_width=0):
                        chat_re_bt = gr.Button('Again')

                txt_msg = chat_txt.submit(pure_add_text, [pure_chatbot, chat_txt], [pure_chatbot, chat_txt],
                                          queue=False).then(pure_bot, pure_chatbot, pure_chatbot)
                txt_msg.then(lambda: gr.update(interactive=True), None, [chat_txt], queue=False)

                re_txt_msg = chat_re_bt.click(rm_text, [pure_chatbot], [pure_chatbot, chat_txt],
                                              queue=False).then(pure_chat_clear_last, None,
                                                                None).then(pure_bot, pure_chatbot, pure_chatbot)
                re_txt_msg.then(lambda: gr.update(interactive=True), None, [chat_txt], queue=False)

                chat_clr_bt.click(chat_clear_pure, None, pure_chatbot, queue=False)

                chat_stop_bt.click(pure_chat_clear_last, None, None, cancels=[txt_msg, re_txt_msg], queue=False)

    date1.change(update_app_global_para, [date1, date2],
                 None).then(update_browser_list, None, browser_list).then(chat_clear, None, [chatbot, hidden_file_path])
    date2.change(update_app_global_para, [date1, date2],
                 None).then(update_browser_list, None, browser_list).then(chat_clear, None, [chatbot, hidden_file_path])

    demo.load(update_app_global_para, [date1, date2],
              None).then(refresh_date, None,
                         [date1, date2]).then(update_browser_list, None,
                                              browser_list).then(chat_clear, None, [chatbot, hidden_file_path])

demo.queue().launch(server_name=server_config.server.server_host, server_port=server_config.server.workstation_port)

```


[User] Show me the code for 'qwen_server\__init__.py' in Qwen-Agent.

[Assistant]
```python
# Copyright 2023 The Qwen team, Alibaba Group. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

```


[User] Provide a comprehensive overview of AI Agents: Concepts, Applications, and Frameworks.

[Assistant]
Comprehensive Overview of AI Agents: Concepts,
Applications, and Frameworks
AI agents are autonomous systems that perceive, reason, act, and learn to achieve
goals without constant human oversight.
They differ from traditional AI by their goal-driven behavior, adaptability, and ability
to perform complex multi-step tasks.
AI agents are categorized into types such as simple reflex, model-based, goalbased, utility-based, and learning agents, each with distinct use cases.
Modern AI agent architectures integrate perception, decision-making, memory, and
action execution, often leveraging large language models (LLMs) for advanced
reasoning.
Open-source frameworks like LangChain, CrewAI, AutoGen, and Qwen-Agent
provide tools to develop AI agents with features including multi-agent collaboration,
memory, and tool use.
Introduction to AI Agents
AI agents represent a significant evolution beyond traditional AI systems. Unlike conventional
AI, which executes predefined instructions, AI agents are autonomous entities capable of
perceiving their environment, reasoning about it, making decisions, and taking actions to
achieve specific goals. This autonomy allows them to adapt to dynamic and unpredictable
scenarios, making them powerful tools for complex problem-solving and workflow automation.
AI agents are characterized by several core traits:
Autonomy: They operate independently, making decisions without human intervention.
Reactivity: They perceive and respond to environmental stimuli in real-time.
Proactiveness: They initiate actions to achieve goals rather than merely reacting to
inputs.
Social Ability: They can collaborate with other agents or humans, communicating and
coordinating to solve problems collectively.
Learning and Adaptation: They improve over time by learning from outcomes and
adjusting strategies accordingly.
These characteristics enable AI agents to handle complex, multi-step tasks such as managing
schedules, optimizing logistics, providing customer support, or conducting research.
Real-World Examples
A logistics AI agent optimizes delivery routes in real-time, balancing speed, cost, and
fuel consumption.
•
•
•
•
•
•
•
•
•
•
•
1/6
A customer service agent autonomously resolves user queries by understanding natural
language and accessing relevant databases.
A multi-agent system simulates human social interactions for training or entertainment
applications.
Types of AI Agents
AI agents can be classified based on their architecture and behavior:
Agent
Type
Description Use Cases Limitations
Simple
Reflex
Agents
React directly to environmental stimuli without
internal state or memory.
Basic automation,
sensor-based tasks
Limited adaptability,
no learning
ModelBased
Reflex
Agents
Use a model of the world to interpret stimuli and
respond.
Navigation, robotics
Requires accurate
world models
GoalBased
Agents
Act to achieve specific goals, planning sequences
of actions.
Task automation,
workflow
management
May struggle with
dynamic
environments
UtilityBased
Agents
Make decisions based on utility functions that
quantify outcomes.
Resource allocation,
optimization
Requires welldefined utility
metrics
Learning
Agents
Improve performance over time by learning from
experience or feedback.
Adaptive systems,
personalization
Needs training data
and computational
resources
Emerging categories include:
Multi-Agent Systems: Collaborative agents that interact to solve complex problems or
simulate social dynamics.
Hierarchical Agents: Agents organized in layers with different levels of abstraction and
responsibility.
Hybrid Agents: Combine reactive and deliberative components for flexible behavior.
Architecture of AI Agents
AI agents typically comprise several modular components:
Perception Module: Gathers data from the environment via sensors, APIs, or user
inputs.
•
•
•
•
•
•
2/6
Decision-Making Engine: Employs reasoning, planning, and reinforcement learning to
determine actions.
Memory System: Maintains short-term and long-term memory to retain context and
learn from past interactions.
Action Execution Mechanism: Performs actions in the environment, such as sending
messages, running code, or controlling hardware.
Architectural Patterns
BDI (Belief-Desire-Intention): Agents maintain beliefs about the world, desires (goals),
and intentions (plans), enabling human-like reasoning.
Reactive-Deliberative Hybrids: Combine fast reactive responses with slower
deliberative planning for balanced behavior.
Graph-Based Orchestration (e.g., LangGraph): Agents and tasks are nodes in a
directed graph, enabling complex workflows and multi-agent coordination.
Role of Large Language Models (LLMs)
LLMs serve as the “brain” of modern AI agents, enabling natural language understanding,
reasoning, and generation. They integrate with agent architectures to:
Interpret user queries and environmental data.
Generate plans and decisions based on context.
Facilitate tool use and API interactions via function calling.
Support memory and learning by processing and storing textual information.
Comparative Table of AI Agent Frameworks
Framework
Developer/
Org
Language Key Features Use Cases License
GitHub
Link
Dependencies
Maturity
Level
UniqueSellingPointsLangChain
LangChain
Community
Python
Modular
components,
multi-agent
support,
memory, RAG
integration,
LangGraph for
orchestration
Document
processing,
RAG,
workflow
automation
MIT GitHub
OpenAI API,
Pinecone,
ChromaDB
Productionready
HighlyflexibleextensecosysCrewAI
CrewAI
Team
Python
Role-based
agents, layered
memory,
human-in-theCollaborative
workflows,
content
creation
MIT GitHub
OpenAI API,
ChromaDB,
SQLite
Early
production
Simplifmulti-adevelo•
•
•
•
•
•
•
•
•
•
3/6
Framework
Developer/
Org
Language Key Features Use Cases License
GitHub
Link
Dependencies
Maturity
Level
UniqueSellingPointsloop, task
delegation
AutoGen Microsoft Python
Multi-agent
orchestration,
asynchronous
communication,
human-in-theloop
Research,
prototyping,
collaborative
workflows
MIT GitHub
OpenAI API,
various LLMs
Productionready
Strong agent
coordinSuperAGI
SuperAGI
Team
Python
Multi-agent
chat, function
calling,
simulation of
social
dynamics
Enterprise
LLM
orchestration
Apache
2.0
GitHub
OpenAI API,
various LLMs
Productionready
ExtenssuppormultiplmodelsOpenAI
Swarm
OpenAI Python
Single-agent
control loop,
routine-based
task execution,
tool usage via
docstrings
Prototyping,
single-agent
workflows
Proprietary N/A OpenAI API Experimental
FlexiblegeneraworkfloQwenAgent
Alibaba
Cloud
Python
Function
calling, MCP
support, code
interpreter,
RAG, multiagent
collaboration
Multimodal
tasks, ultralong input
handling
Apache
2.0
GitHub
Qwen3 model,
vLLM, SGLang
Productionready
Handletokenstool
integraAutoGPT Community Python
Autonomous
task execution,
memory, tool
use, multimodal
pipelines
Real-world
automation,
prototyping
MIT GitHub
OpenAI API,
various LLMs
Productionready
Optimizfor longrunningtasks
BabyAGI Community Python
Lightweight,
recursive task
creation,
adaptive
workflows
Education,
prototyping,
cognitive
task loops
MIT GitHub
OpenAI API,
LLaMA
Experimental
Minimadesigndynamgenera4/6
Challenges and Limitations of AI Agents
Hallucination and Reliability: AI agents may generate incorrect or inconsistent outputs,
especially in complex or ambiguous scenarios.
Scalability: Multi-agent systems can become difficult to manage and debug as the
number of agents grows.
Ethical and Safety Risks: Autonomous decision-making raises concerns about
accountability, bias, and misuse in high-stakes domains.
Computational Demands: Advanced agents require significant resources, limiting
accessibility for smaller organizations.
Evaluation Metrics: Measuring agent performance is complex, requiring metrics for task
success, adaptability, and alignment with human values.
Emerging Trends and Future Directions
Foundation Models: Integration of large foundation models (e.g., GPT-4, Llama)
enhances agent capabilities in reasoning and multimodal interaction.
Agent Swarms and Collective Intelligence: Research into multi-agent systems that
collaborate at scale to solve complex problems.
Regulatory Efforts: Initiatives like the EU AI Act aim to establish standards for
autonomous agents, emphasizing safety and ethical use.
Industry Adoption: AI agents are increasingly deployed in healthcare, finance, logistics,
and customer service, driving productivity and innovation.
Edge Deployment: Advances in model architectures (e.g., Mixture of Experts) enable
efficient deployment on edge devices.
Resources for Further Learning
Research Papers
“Modelling Social Action for AI Agents” (Castelfranchi, 2024) – Explores social
interactions and goal dynamics in multi-agent systems.
“Visibility into AI Agents” (Kapoor et al., 2024) – Discusses transparency and
accountability mechanisms for autonomous agents.
“Artificial Intelligence and Virtual Worlds” (Laird, 2024) – Examines AI agents as a path
toward human-level intelligence.
“Intelligent Agents: Theory and Practice” (Wooldridge, 2024) – Covers agent theories,
architectures, and programming languages.
“TPTU: Task Planning and Tool Usage of Large Language Model-based AI Agents”
(Zhou et al., 2024) – Evaluates LLM agents’ ability to plan and use tools effectively.
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
5/6
Books and Surveys
“Artificial Intelligence: A Modern Approach” (Russell & Norvig) – Comprehensive
introduction to AI agents and their architectures.
“Multiagent Systems: Algorithmic, Game-Theoretic, and Logical Foundations” (Shoham &
Leyton-Brown) – In-depth coverage of multi-agent systems.
Recent survey papers on LLM-based agents and context-aware multi-agent systems
provide up-to-date insights.
Online Courses and Tutorials
Coursera: “Building AI Agents and Agentic Workflows” – Hands-on training with
frameworks like CrewAI and AutoGen.
Analytics Vidhya: “Agentic AI Learning Path” – Structured curriculum covering
fundamentals to advanced agent development.
Microsoft Learn: “Develop AI Agents on Azure” – Focuses on Microsoft’s agent
frameworks and cloud deployment.
Codecademy: “Learn How to Build AI Agents” – Practical introduction to agentic
workflows.
Communities and Conferences
AAMAS (International Conference on Autonomous Agents and Multiagent Systems) –
Leading venue for agent research.
NeurIPS Workshops on Agents – Covers cutting-edge developments in AI agents.
Reddit: r/LLMDevs – Community discussions on AI agents and frameworks.
GitHub repositories of major frameworks (LangChain, AutoGen, CrewAI) – Access to
code, documentation, and community contributions.
This report synthesizes current knowledge on AI agents, providing a structured foundation for
educating an LLM about their concepts, architectures, frameworks, and future directions. The
included resources and comparative framework table enable deep understanding and
practical exploration of AI agent technologies.