File size: 4,409 Bytes
6d8aa95
 
4facc97
390e1b0
107cced
390e1b0
 
 
107cced
 
 
06ffc6c
b57bc26
0ae4701
4facc97
 
107cced
7cc32e5
 
107cced
 
 
b57bc26
 
 
d366b45
107cced
 
4facc97
107cced
 
 
 
d366b45
107cced
 
 
7cc32e5
107cced
 
f97da2b
0ae4701
da09bef
0ae4701
7cc32e5
0ae4701
f97da2b
0ae4701
 
4facc97
 
 
7cc32e5
 
390e1b0
 
 
 
da09bef
390e1b0
 
7cc32e5
f97da2b
 
 
 
 
390e1b0
 
 
 
 
 
 
 
 
 
 
 
 
 
f97da2b
 
 
4facc97
390e1b0
 
 
 
 
 
 
 
 
 
d366b45
4facc97
d366b45
 
 
 
 
4facc97
107cced
da09bef
06ffc6c
 
 
 
da09bef
a28b1b4
53d2fb7
a28b1b4
d366b45
7cc32e5
 
 
 
53d2fb7
7cc32e5
d366b45
390e1b0
b57bc26
 
7cc32e5
 
b57bc26
4facc97
53d2fb7
4facc97
 
da09bef
4facc97
a28b1b4
4facc97
107cced
4facc97
d366b45
a28b1b4
d366b45
4facc97
 
 
f97da2b
390e1b0
 
 
f97da2b
107cced
7cc32e5
6d8aa95
107cced
5852238
d366b45
33412db
5852238
 
 
33412db
5852238
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
'''RSS MCP server demonstration client app.'''

import os
import asyncio
import logging
import time
import queue
from typing import Tuple
from pathlib import Path
from logging.handlers import RotatingFileHandler
import gradio as gr
import assets.html as html
import client.gradio_functions as gradio_funcs
import client.interface as interface
from client.mcp_client import MCPClientWrapper
from client.anthropic_bridge import AnthropicBridge

# Set-up root logger so we send logs from the MCP client,
# Gradio and the rest of the project to the same file.
# Make sure log directory exists
Path('logs').mkdir(parents=True, exist_ok=True)

# Clear old logs if present
gradio_funcs.delete_old_logs('logs', 'rss_client')

# Configure the root logger
logging.basicConfig(
    handlers=[RotatingFileHandler(
        'logs/rss_client.log',
        maxBytes=100000,
        backupCount=10,
        mode='w'
    )],
    level=logging.INFO,
    format='%(levelname)s - %(name)s - %(message)s'
)

# Get a logger
logger = logging.getLogger(__name__)

# Handle MCP server connection and interactions
RSS_CLIENT = MCPClientWrapper(
    'https://agents-mcp-hackathon-rss-mcp-server.hf.space/gradio_api/mcp/sse'
)
logger.info('Started MCP client')

# Handles Anthropic API I/O
BRIDGE = AnthropicBridge(
    RSS_CLIENT,
    api_key=os.environ['ANTHROPIC_API_KEY']
)

logger.info('Started Anthropic API bridge')

# Queue to return responses to user
OUTPUT_QUEUE = queue.Queue()
logger.info('Created response queue')


def user_message(message: str, history: list) -> Tuple[str, list]:
    '''Adds user message to conversation and returns for immediate posting.

    Args:
        message: the new message from the user as a string
        chat_history: list containing conversation history where each element is
            a dictionary with keys 'role' and 'content'

    Returns
        New chat history with user's message added.
    '''

    return '', history + [{'role': 'user', 'content': message}]


def send_message(chat_history: list):
    '''Submits chat history to agent, streams reply, one character at a time.
    
    Args:
        chat_history: list containing conversation history where each element is
            a dictionary with keys 'role' and 'content'

    Returns
        New chat history with model's response to user added.
    '''

    asyncio.run(interface.agent_input(BRIDGE, OUTPUT_QUEUE, chat_history))

    while True:
        response = OUTPUT_QUEUE.get()

        if response == 'bot-finished':
            break

        chat_history.append({'role': 'assistant', 'content': ''})

        if response is not None:

            for character in response:
                chat_history[-1]['content'] += character
                time.sleep(0.005)

                yield chat_history


with gr.Blocks(title='RASS agent') as demo:
    with gr.Row():
        gr.HTML(html.TITLE)

    gr.Markdown(html.DESCRIPTION)
    gr.Markdown(html.FEATURES_TOOLS)

    # MCP connection/tool dump
    connect_btn = gr.Button('Connect to MCP server')
    status = gr.Textbox(label='MCP server tool dump', interactive=False, lines=5, max_lines=5)
    connect_btn.click(# pylint: disable=no-member
        RSS_CLIENT.list_tools,
        outputs=status
    )

    # Dialog log output
    dialog_output = gr.Textbox(label='Internal dialog', lines=5, max_lines=5)
    timer = gr.Timer(0.5, active=True)

    timer.tick( # pylint: disable=no-member
        lambda: gradio_funcs.update_dialog(), # pylint: disable=unnecessary-lambda
        outputs=dialog_output
    )

    # Chat interface
    chatbot = gr.Chatbot(
        value=[],
        height=500,
        type='messages',
        show_copy_button=True
    )

    msg = gr.Textbox(
        'Are there any new posts on Slashdot?',
        label='Ask about content or articles on a site or platform',
        placeholder='Is there anything new on Slashdot?',
        scale=4
    )

    msg.submit( # pylint: disable=no-member
        user_message, [msg, chatbot], [msg, chatbot], queue=False
    ).then(
        send_message, chatbot, chatbot
    )


if __name__ == '__main__':

    current_directory = os.getcwd()
    logger.info(current_directory)

    if 'pyrite' in current_directory:
        logger.info('Starting RASS on LAN')
        demo.launch(server_name='0.0.0.0', server_port=7860)

    else:
        logger.info('Starting RASS')
        demo.launch()