ModelHubManager / components /version_control.py
S-Dreamer's picture
Upload 31 files
74dd3f1 verified
Raw
History Blame Contribute Delete
7.76 kB
import streamlit as st
import pandas as pd
from datetime import datetime
import difflib
import json
def fetch_model_versions(repo_id):
"""
Fetch model versions from the Hugging Face API.
In a real implementation, this would call the HF API to get version history.
For now, we'll use demo data.
"""
# In a production app, you would fetch this from the Hugging Face API
# For demo purposes, create some sample version data
versions = [
{
"version": "v1.0",
"commit_id": "abc123",
"timestamp": "2023-01-15T10:30:00Z",
"author": st.session_state.username,
"message": "Initial model release",
"files_changed": 5,
"performance": {"accuracy": 0.85, "f1": 0.82}
},
{
"version": "v1.1",
"commit_id": "def456",
"timestamp": "2023-02-20T14:45:00Z",
"author": st.session_state.username,
"message": "Improved tokenization",
"files_changed": 2,
"performance": {"accuracy": 0.87, "f1": 0.84}
},
{
"version": "v2.0",
"commit_id": "ghi789",
"timestamp": "2023-03-10T09:15:00Z",
"author": st.session_state.username,
"message": "Major model architecture upgrade",
"files_changed": 12,
"performance": {"accuracy": 0.92, "f1": 0.90}
}
]
return versions
def render_version_history(model_info):
"""Render the version history of a model"""
if not model_info:
st.error("Model information not found")
return
repo_id = model_info.modelId
st.subheader("๐Ÿ”„ Version History")
with st.spinner("Loading version history..."):
versions = fetch_model_versions(repo_id)
if not versions:
st.info("No version history found for this model.")
return
# Convert to DataFrame for easier display
df = pd.DataFrame(versions)
# Format timestamp
df["timestamp"] = pd.to_datetime(df["timestamp"]).dt.strftime("%Y-%m-%d %H:%M")
# Create a cleaner display version
display_df = df[["version", "timestamp", "author", "message", "files_changed"]]
display_df.columns = ["Version", "Date", "Author", "Commit Message", "Files Changed"]
# Show the version history
st.dataframe(display_df, use_container_width=True)
# Version comparison
st.subheader("Compare Versions")
col1, col2 = st.columns(2)
with col1:
base_version = st.selectbox(
"Base Version",
options=df["version"].tolist(),
index=0
)
with col2:
compare_version = st.selectbox(
"Compare Version",
options=[v for v in df["version"].tolist() if v != base_version],
index=0
)
if st.button("Compare", use_container_width=True):
with st.spinner("Generating comparison..."):
# In a real implementation, fetch the actual data from each version
# For demo, use the sample performance metrics
base_data = df[df["version"] == base_version].iloc[0]
compare_data = df[df["version"] == compare_version].iloc[0]
# Display comparison
col1, col2 = st.columns(2)
with col1:
st.markdown(f"### {base_version}")
st.markdown(f"**Commit:** {base_data['commit_id']}")
st.markdown(f"**Date:** {base_data['timestamp']}")
st.markdown(f"**Author:** {base_data['author']}")
st.markdown(f"**Message:** {base_data['message']}")
# Performance metrics
st.markdown("#### Performance Metrics")
for metric, value in base_data["performance"].items():
st.markdown(f"**{metric.capitalize()}:** {value:.4f}")
with col2:
st.markdown(f"### {compare_version}")
st.markdown(f"**Commit:** {compare_data['commit_id']}")
st.markdown(f"**Date:** {compare_data['timestamp']}")
st.markdown(f"**Author:** {compare_data['author']}")
st.markdown(f"**Message:** {compare_data['message']}")
# Performance metrics
st.markdown("#### Performance Metrics")
for metric, value in compare_data["performance"].items():
# Calculate change
base_value = base_data["performance"].get(metric, 0)
change = value - base_value
change_pct = (change / base_value * 100) if base_value != 0 else float('inf')
# Display with change indicator
if change > 0:
st.markdown(f"**{metric.capitalize()}:** {value:.4f} ๐Ÿ“ˆ **(+{change:.4f}, {change_pct:.2f}%)**")
elif change < 0:
st.markdown(f"**{metric.capitalize()}:** {value:.4f} ๐Ÿ“‰ **({change:.4f}, {change_pct:.2f}%)**")
else:
st.markdown(f"**{metric.capitalize()}:** {value:.4f} (no change)")
# Show visual diff of model config
st.subheader("Configuration Changes")
# Sample configs (in a real app, you'd fetch these from the API)
base_config = {
"hidden_size": 768,
"num_attention_heads": 12,
"num_hidden_layers": 6,
"vocab_size": 30000
}
compare_config = {
"hidden_size": 1024,
"num_attention_heads": 16,
"num_hidden_layers": 8,
"vocab_size": 30000
}
# Generate a formatted diff
base_str = json.dumps(base_config, indent=2).splitlines()
compare_str = json.dumps(compare_config, indent=2).splitlines()
diff = difflib.unified_diff(
base_str,
compare_str,
fromfile=f'config_{base_version}',
tofile=f'config_{compare_version}',
lineterm=''
)
diff_html = []
for line in diff:
if line.startswith('+'):
diff_html.append(f'<span style="color: green">{line}</span>')
elif line.startswith('-'):
diff_html.append(f'<span style="color: red">{line}</span>')
elif line.startswith('@@'):
diff_html.append(f'<span style="color: purple">{line}</span>')
else:
diff_html.append(line)
st.markdown('<div style="background-color: #f5f5f5; padding: 10px; border-radius: 5px; font-family: monospace; white-space: pre-wrap;">' + '<br>'.join(diff_html) + '</div>', unsafe_allow_html=True)
# Rollback functionality
st.subheader("Rollback to Previous Version")
rollback_version = st.selectbox(
"Select version to rollback to",
options=df["version"].tolist(),
index=len(df)-2 # Default to second-to-last version
)
if st.button("Rollback", use_container_width=True, type="primary"):
with st.spinner("Rolling back to version " + rollback_version):
# In a real implementation, this would call the HF API to perform the rollback
st.success(f"Successfully rolled back to {rollback_version}")
# Here you would update the model information and refresh the view