File size: 9,742 Bytes
014f597 1d0b9d1 89c9126 35aeee0 655dcc9 89c9126 44e58a6 c6542ed 6269c32 655dcc9 b421a2a 655dcc9 318bbdf 89c9126 318bbdf 89c9126 6bdfadb 35aeee0 89c9126 18c04d1 e4d45f0 89c9126 1d0b9d1 89c9126 18c04d1 014f597 6bdfadb 35aeee0 89c9126 18c04d1 89c9126 6bdfadb 35aeee0 6bdfadb 18c04d1 6bdfadb b139634 e4d45f0 6bdfadb c6542ed 35aeee0 c6542ed 18c04d1 c6542ed 18c04d1 c6542ed 18c04d1 c6542ed 6269c32 35aeee0 6269c32 0f5d5f3 6269c32 6bdfadb 95e43e2 0f5d5f3 95e43e2 d07810d d69ce5a 7a165bc 95e43e2 b421a2a 655dcc9 070bf41 655dcc9 070bf41 655dcc9 070bf41 655dcc9 070bf41 655dcc9 070bf41 655dcc9 070bf41 655dcc9 070bf41 655dcc9 d69ce5a 6bdfadb 97a44d4 b139634 44e58a6 b139634 c6542ed 6269c32 97a44d4 95e43e2 318bbdf 6bdfadb 89c9126 b139634 89c9126 1d0b9d1 89c9126 97a44d4 1d0b9d1 014f597 1d0b9d1 014f597 1d0b9d1 |
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 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
import gradio as gr
# Local modules
import fastf1_tools
import openf1_tools
from utils.constants import (
DRIVER_NAMES,
CONSTRUCTOR_NAMES,
CURRENT_YEAR,
DROPDOWN_SESSION_TYPES,
MARKDOWN_INTRODUCTION,
HTML_INTRODUCTION,
MARKDOWN_OPENF1_EXAMPLES,
OPENF1_TOOL_DESCRIPTION,
CONSTRUCTORS_PER_SEASON,
DRIVERS_PER_SEASON
)
with gr.Blocks() as iface_driver_championship_standings:
gr.Markdown("## World Driver Championship Standings\nGet the world driver championship standings for a specific driver. Note that the older data has gaps and may not be entirely complete.")
with gr.Row():
year_input = gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR)
driver_dropdown = gr.Dropdown(label="Driver", choices=DRIVERS_PER_SEASON.get(str(year_input.value), []))
output_text = gr.Textbox(label="Result")
submit_btn = gr.Button("Submit")
def update_drivers(year):
choices = DRIVERS_PER_SEASON.get(str(year), [])
return gr.update(choices=choices, value=(choices[0] if choices else None))
year_input.blur(
update_drivers,
inputs=year_input,
outputs=driver_dropdown
)
submit_btn.click(
fastf1_tools.driver_championship_standings,
inputs=[year_input, driver_dropdown],
outputs=output_text
)
with gr.Blocks() as iface_constructor_championship_standings:
gr.Markdown("## World Constructor Championship Standings\nGet the current/past world constructor championship standings for a specific constructor. Note that the older data has gaps and may not be entirely complete.")
with gr.Row():
year_input = gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR)
constructor_dropdown = gr.Dropdown(label="Constructor", choices=CONSTRUCTORS_PER_SEASON.get(str(year_input.value), []))
output_text = gr.Textbox(label="Result")
submit_btn = gr.Button("Submit")
def update_constructors(year):
choices = CONSTRUCTORS_PER_SEASON.get(str(year), [])
return gr.update(choices=choices, value=(choices[0] if choices else None))
year_input.blur(
update_constructors,
inputs=year_input,
outputs=constructor_dropdown
)
submit_btn.click(
fastf1_tools.constructor_championship_standings,
inputs=[year_input, constructor_dropdown],
outputs=output_text
)
iface_event_info = gr.Interface(
fn=fastf1_tools.get_event_info,
inputs=[
gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR),
gr.Textbox(label="Grand Prix", placeholder="Ex: Monaco", info="The name of the GP/country/location (Fuzzy matching supported) or round number"),
gr.Radio(["human", "LLM"], label="Display format", value="human", info="Toggle between human-readable (parsed) and LLM output (raw)")
],
outputs="text",
title="Event Info",
description="Get information about a specific Grand Prix event. Example: (2025,Monaco,human)"
)
iface_season_calendar = gr.Interface(
fn=fastf1_tools.get_season_calendar,
inputs=[
gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR),
],
outputs="text",
title="Season Calendar",
description="Get the season calendar for the given year"
)
iface_track_visualization = gr.Interface(
fn=fastf1_tools.track_visualization,
inputs=[
gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR),
gr.Textbox(label="Grand Prix", placeholder="Ex: Monaco", info="The name of the GP/country/location (Fuzzy matching supported) or round number"),
gr.Radio(["speed", "corners", "gear"], label="Visualization type", value="speed", info="What type of track visualization to generate"),
],
outputs="image",
title="Track Visualizations",
description="Get the track visualization (speed/corners/gear) for the fastest lap at the specific Grand Prix race. Example: (2025,Monaco,speed)"
)
iface_session_results = gr.Interface(
fn=fastf1_tools.get_session_results,
inputs=[
gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR),
gr.Textbox(label="Grand Prix", placeholder="Ex: Monaco", info="The name of the GP/country/location (Fuzzy matching supported) or round number"),
gr.Dropdown([session_type for session_type in DROPDOWN_SESSION_TYPES if "practice" not in session_type], label="Session type", value="race", info="The session type to get results for. Dataframe's columns vary depending on session type.")
],
outputs=gr.Dataframe(
headers=None, # Let it infer from returned DataFrame
row_count=(0, "dynamic"), # Start empty, allow it to grow
col_count=(0, "dynamic") # Let columns adjust too
),
title="Session Results",
description="Get the session results for the given Grand Prix. Example: (2025,Monaco,qualifying)"
)
iface_driver_info = gr.Interface(
fn=fastf1_tools.get_driver_info,
inputs=[
gr.Dropdown(label="Driver", choices=DRIVER_NAMES)
],
outputs="text",
title="Driver Info",
description="Get background information about a specific driver from the 2025 Formula 1 season"
)
iface_constructor_info = gr.Interface(
fn=fastf1_tools.get_constructor_info,
inputs=[
gr.Dropdown(label="Constructor", choices=CONSTRUCTOR_NAMES)
],
outputs="text",
title="Constructor Info",
description="Get background information about a specific constructor from the 2025 Formula 1 season"
)
# About introduction tab
with gr.Blocks() as markdown_tab:
gr.HTML(HTML_INTRODUCTION)
# OpenF1 tools tab
def openf1_tools_tab():
with gr.Blocks() as openf1_tools_tab:
gr.Markdown(OPENF1_TOOL_DESCRIPTION)
with gr.Accordion("get_api_endpoints()", open=False):
btn = gr.Button("Get all endpoints")
output = gr.JSON()
btn.click(openf1_tools.get_api_endpoints, outputs=output)
with gr.Accordion("get_api_endpoint(endpoint)", open=False):
endpoint_in = gr.Textbox(label="Endpoint", placeholder="e.g. sessions")
btn = gr.Button("Get endpoint info")
output = gr.JSON()
btn.click(openf1_tools.get_api_endpoint, inputs=endpoint_in, outputs=output)
with gr.Accordion("get_endpoint_info(endpoint)", open=False):
endpoint_in = gr.Textbox(label="Endpoint", placeholder="e.g. sessions")
btn = gr.Button("Get endpoint details")
output = gr.JSON()
btn.click(openf1_tools.get_endpoint_info, inputs=endpoint_in, outputs=output)
with gr.Accordion("get_filter_info(filter_name)", open=False):
filter_in = gr.Textbox(label="Filter name", placeholder="e.g. driver_number")
btn = gr.Button("Get filter info")
output = gr.JSON()
btn.click(openf1_tools.get_filter_info, inputs=filter_in, outputs=output)
with gr.Accordion("get_filter_string(filter_name, filter_value, operator)", open=False):
filter_name = gr.Textbox(label="Filter name", placeholder="e.g. driver_number")
filter_value = gr.Textbox(label="Filter value", placeholder="e.g. 16")
operator = gr.Dropdown(label="Operator", choices=["=", ">", "<", ">=", "<="], value="=")
btn = gr.Button("Get filter string")
output = gr.Textbox(label="Filter string", info="Example: driver_number=16&")
btn.click(openf1_tools.get_filter_string, inputs=[filter_name, filter_value, operator], outputs=output)
with gr.Accordion("apply_filters(api_string, *filters)", open=False):
api_string = gr.Textbox(label="Base API string", placeholder="e.g. https://api.openf1.org/v1/sessions?")
filters = gr.Textbox(label="Filters (comma-separated)", placeholder="e.g. driver_number=16&,session_key=123&")
btn = gr.Button("Apply filters")
output = gr.Textbox(label="Full API string")
btn.click(openf1_tools.apply_filters, inputs=[api_string, filters], outputs=output)
with gr.Accordion("send_request(api_string)", open=False):
with gr.Accordion("Example API requests (copy & paste into text box below)", open=False):
gr.Markdown(MARKDOWN_OPENF1_EXAMPLES)
api_string = gr.Textbox(label="Full API string", placeholder="e.g. https://api.openf1.org/v1/sessions?driver_number=16")
btn = gr.Button("Send API request")
output = gr.JSON()
btn.click(openf1_tools.send_request, inputs=api_string, outputs=output)
return openf1_tools_tab
# OpenF1 tabs
named_interfaces = {
"About": markdown_tab,
"Driver Championship Standings": iface_driver_championship_standings,
"Constructor Championship Standings": iface_constructor_championship_standings,
"Event Info": iface_event_info,
"Season Calendar": iface_season_calendar,
"Track Visualizations": iface_track_visualization,
"Session Results": iface_session_results,
"Driver Info": iface_driver_info,
"Constructor Info": iface_constructor_info,
"OpenF1 Tools": openf1_tools_tab()
}
# Tab names and interfaces
tab_names = list(named_interfaces.keys())
interface_list = list(named_interfaces.values())
# Combine all the interfaces into a single TabbedInterface
gradio_server = gr.TabbedInterface(
interface_list,
tab_names=tab_names,
title="๐ Formula 1 MCP server ๐๏ธ"
)
# Launch the interface and MCP server
if __name__ == "__main__":
gradio_server.launch(mcp_server=True) |