Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Model card creation #181

Merged
merged 35 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
c98e011
created popup component
Jun 6, 2024
886117d
adding popup component
Jun 6, 2024
e5fb666
added rendering code
Jun 6, 2024
2913ef3
updating popup component
Jun 7, 2024
c40f3c2
Added close and download button
Jun 7, 2024
0a11f80
Deleted cmf file
Jun 7, 2024
a513b6c
updating model_card
Jun 7, 2024
197a556
Merge branch 'model_card' of https://github.com/varkha-d-sharma/cmf i…
Jun 10, 2024
148c01e
Wrote an rest api for model card and axios interface
varkha-d-sharma Jun 11, 2024
f6fe3a2
model card api update
Jun 11, 2024
b89b544
json filename update
AyeshaSanadi Jun 11, 2024
0f669ba
readded popup
Jun 11, 2024
c3169fa
adding more changes required for model card creation
varkha-d-sharma Jun 11, 2024
838902c
added some json related changes to do some testing on popup side
varkha-d-sharma Jun 12, 2024
c3d0fbc
made some changes
varkha-d-sharma Jun 12, 2024
1f0236c
changes related to popup content
AyeshaSanadi Jun 12, 2024
ca80640
updated code for json filename
AyeshaSanadi Jun 12, 2024
4dc75ac
made some changes to display data properly in popup
varkha-d-sharma Jun 12, 2024
81e956c
Align items inside popup component to left
AyeshaSanadi Jun 12, 2024
d3d6b98
Made some changes in popup data fromat
varkha-d-sharma Jun 12, 2024
55a0dd7
Added table structure for artifact data
AyeshaSanadi Jun 12, 2024
434b8f2
added style to table
AyeshaSanadi Jun 12, 2024
b14ce89
adding some code for popup
varkha-d-sharma Jun 12, 2024
6976f7b
made changes in table code
AyeshaSanadi Jun 12, 2024
9b3a7ad
keeping old_index.jsx file
AyeshaSanadi Jun 13, 2024
018372c
converted table to model card
AyeshaSanadi Jun 13, 2024
216b133
Added the code to refine popup model card
varkha-d-sharma Jun 13, 2024
1a02682
Made changes regarding modelcard structure
AyeshaSanadi Jun 14, 2024
638d4a4
mistakenly commited wrong user name
varkha-d-sharma Jun 14, 2024
a83f06e
addressing review comments
varkha-d-sharma Jun 14, 2024
89e3389
Addressed review comments and commented on get_model_data function
AyeshaSanadi Jun 19, 2024
9a8953b
Updating supported versions from <=3.10 to <3.11. So that, all the ve…
AyeshaSanadi Jun 19, 2024
8b4d338
Made proper alignment of close and download button
AyeshaSanadi Jun 20, 2024
53b2852
Merge branch 'HewlettPackard:master' into model_card
varkha-d-sharma Jul 10, 2024
d84845b
Addressing review comments
varkha-d-sharma Jul 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ models and performance metrics) recorded by the framework are versioned and iden
## Installation

#### 1. Pre-Requisites:
* 3.9>= Python <=3.10
* 3.9>= Python <3.11
* Git latest version

#### 2. Set up Python Virtual Environment:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ authors = [
]
description = "Track metadata for AI pipeline"
readme = "README.md"
requires-python = ">=3.9,<=3.10"
requires-python = ">=3.9,<3.11"
classifiers = [
"Programming Language :: Python :: 3",
"Operating System :: POSIX :: Linux",
Expand Down
69 changes: 69 additions & 0 deletions server/app/get_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,75 @@
from server.app.query_visualization_execution import query_visualization_execution
from fastapi.responses import FileResponse


async def get_model_data(mlmdfilepath, modelId):
'''
This function retrieves the necessary model data required for generating a model card.

Arguments:
mlmdfilepath (str): The file path to the metadata.
modelId (int): The ID of the model for which data is required.

Returns:
This function returns a tuple of DataFrames containing the following:

model_data_df (DataFrame): Metadata related to the model itself.
model_exe_df (DataFrame): Metadata of the executions in which the specified modelId was an input or output.
model_input_df (DataFrame): Metadata of input artifacts that led to the creation of the model.
model_output_df (DataFrame): Metadata of artifacts that used the model as an input.
The returned DataFrames provide comprehensive metadata for the specified model, aiding in the creation of detailed and accurate model cards.
'''
query = cmfquery.CmfQuery(mlmdfilepath)
pd.set_option('display.max_columns', None)
df = pd.DataFrame()
# get artifact info - we may remove this to remove redundancy as we can get from the input only
model_data_df = pd.DataFrame()
model_exe_df = pd.DataFrame()
model_input_df = pd.DataFrame()
model_output_df = pd.DataFrame()

# get name from id
modelName = ""
df = query.get_all_artifacts_by_ids_list([modelId])
modelType = df['type'].tolist()[0]
if modelType == "Model":
modelName = df['name'].tolist()[0]
if modelName == "":
return model_data_df, model_exe_df, model_input_df, model_output_df
else:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why two return statements here ?

return model_data_df, model_exe_df, model_input_df, model_output_df

# model's own data
model_data_df = query.get_artifact(modelName)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why two calls ..we should have got all this in the first call


# model's executions data with props and custom props
exe_df = query.get_all_executions_for_artifact(modelName)
exe_ids = []
if not exe_df.empty:
exe_df.drop(columns=['execution_type_name', 'execution_name'], inplace=True)
exe_ids = exe_df['execution_id'].tolist()


if not exe_ids:
return model_data_df, model_exe_df, model_input_df, model_output_df
model_exe_df = query.get_all_executions_by_ids_list(exe_ids)
model_exe_df.drop(columns=['Python_Env', 'Git_Start_Commit', 'Git_End_Commit'], inplace=True)

in_art_ids = []
# input artifacts
in_art_ids.extend(query._get_input_artifacts(exe_ids))
if modelId in in_art_ids:
in_art_ids.remove(modelId)
model_input_df = query.get_all_artifacts_by_ids_list(in_art_ids)

out_art_ids = []
# output artifacts
out_art_ids.extend(query._get_output_artifacts(exe_ids))
out_art_ids.remove(modelId)
model_output_df = query.get_all_artifacts_by_ids_list(out_art_ids)

return model_data_df, model_exe_df, model_input_df, model_output_df

async def get_executions_by_ids(mlmdfilepath, pipeline_name, exe_ids):
'''
Args:
Expand Down
40 changes: 35 additions & 5 deletions server/app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from fastapi.staticfiles import StaticFiles
from contextlib import asynccontextmanager
import pandas as pd
from typing import List, Dict, Any

from cmflib import cmfquery, cmf_merger
from server.app.get_data import (
Expand All @@ -15,7 +16,8 @@
get_artifact_types,
get_all_artifact_ids,
get_all_exe_ids,
get_executions_by_ids
get_executions_by_ids,
get_model_data
)
from server.app.query_visualization import query_visualization
from server.app.query_exec_lineage import query_exec_lineage
Expand Down Expand Up @@ -146,8 +148,7 @@ async def display_exec(
@app.get("/display_artifact_lineage/{pipeline_name}")
async def display_artifact_lineage(request: Request, pipeline_name: str):
'''
This api's returns dictionary of nodes and links for given
pipeline.
This api returns dictionary of nodes and links for given pipeline.
response = {
nodes: [{id:"",name:""}],
links: [{source:1,target:4},{}],
Expand All @@ -170,8 +171,7 @@ async def display_artifact_lineage(request: Request, pipeline_name: str):
@app.get("/get_execution_types/{pipeline_name}")
async def get_execution_types(request: Request, pipeline_name: str):
'''
This api's returns
list of execution types.
This api's returns list of execution types.

'''
# checks if mlmd file exists on server
Expand Down Expand Up @@ -304,6 +304,34 @@ async def upload_file(request:Request, pipeline_name: str = Query(..., descripti
except Exception as e:
return {"error": f"Failed to up load file: {e}"}

@app.get("/model-card")
async def model_card(request:Request, modelId: int, response_model=List[Dict[str, Any]]):
json_payload_1 = ""
json_payload_2 = ""
json_payload_3 = ""
json_payload_4 = ""
model_data_df = pd.DataFrame()
model_exe_df = pd.DataFrame()
model_input_art_df = pd.DataFrame()
model_output_art_df = pd.DataFrame()
df = pd.DataFrame()
# checks if mlmd file exists on server
if os.path.exists(server_store_path):
model_data_df, model_exe_df, model_input_art_df, model_output_art_df = await get_model_data(server_store_path, modelId)
if not model_data_df.empty:
result_1 = model_data_df.to_json(orient="records")
json_payload_1 = json.loads(result_1)
if not model_exe_df.empty:
result_2 = model_exe_df.to_json(orient="records")
json_payload_2 = json.loads(result_2)
if not model_input_art_df.empty:
result_3 = model_input_art_df.to_json(orient="records")
json_payload_3 = json.loads(result_3)
if not model_output_art_df.empty:
result_4 = model_output_art_df.to_json(orient="records")
json_payload_4 = json.loads(result_4)
return [json_payload_1, json_payload_2, json_payload_3, json_payload_4]

async def update_global_art_dict():
global dict_of_art_ids
output_dict = await get_all_artifact_ids(server_store_path)
Expand All @@ -316,3 +344,5 @@ async def update_global_exe_dict():
output_dict = await get_all_exe_ids(server_store_path)
dict_of_exe_ids = output_dict
return


13 changes: 13 additions & 0 deletions ui/src/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,19 @@ class FastAPIClient {
console.error(error);
}
}

async getModelCard(modelId) {
return this.apiClient.get(`/model-card`, {
params: {
modelId: modelId,
},
})
.then(({data}) => {
return data;
});
}

}


export default FastAPIClient;
41 changes: 37 additions & 4 deletions ui/src/components/ArtifactTable/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@
// ArtifactTable.jsx
import React, { useState, useEffect } from "react";
import "./index.css";
const ArtifactTable = ({ artifacts, onSort, onFilter }) => {
import Popup from "../../components/Popup";
import FastAPIClient from "../../client";
import config from "../../config";

const client = new FastAPIClient(config);

const ArtifactTable = ({ artifacts, ArtifactType, onSort, onFilter }) => {

// Default sorting order
const [sortOrder, setSortOrder] = useState("Context_Type");
Expand All @@ -27,9 +33,12 @@ const ArtifactTable = ({ artifacts, onSort, onFilter }) => {
const [filterValue, setFilterValue] = useState("");

const [expandedRow, setExpandedRow] = useState(null);
const [showPopup, setShowPopup] = useState(false);
const [popupData, setPopupData] = useState('');

const consistentColumns = [];


useEffect(() => {
// Set initial sorting order when component mounts
setSortOrder("asc");
Expand All @@ -55,6 +64,19 @@ const ArtifactTable = ({ artifacts, onSort, onFilter }) => {
}
};

const handleLinkClick = (model_id) => {
client.getModelCard(model_id).then((data) => {
console.log(data);
setPopupData(data);
setShowPopup(true);
});
};

const handleClosePopup = () => {
setShowPopup(false);
};


return (
<div className="container flex flex-col mx-auto p-6 mr-4">
<div className="flex flex-col items-end m-1">
Expand Down Expand Up @@ -83,7 +105,13 @@ const ArtifactTable = ({ artifacts, onSort, onFilter }) => {
name {sortOrder === "asc" && <span className="arrow">&#8593;</span>}
{sortOrder === "desc" && <span className="arrow">&#8595;</span>}
</th>
<th scope="col" className="exe_uuid px-6 py-3">
{ArtifactType === "Model" && (
<th scope="col" className="model_card px-6 py-3">
Model_Card
</th>
)}

<th scope="col" className="exe_uuid px-6 py-3">
execution_type_name
</th>
<th scope="col" className="url px-6 py-3">
Expand All @@ -105,14 +133,19 @@ const ArtifactTable = ({ artifacts, onSort, onFilter }) => {
<React.Fragment key={index}>
<tr
key={index}
onClick={() => toggleRow(index)}
className="text-sm font-medium text-gray-800"
>
<td className="px-6 py-4">
<td className="px-6 py-4" onClick={() => toggleRow(index)}>
{expandedRow === index ? "-" : "+"}
</td>
<td className="px-6 py-4">{data.id}</td>
<td className="px-6 py-4">{data.name}</td>
{ArtifactType === "Model" && (
<td className="px-6 py-4">
<a href="#" onClick={(e) => { e.preventDefault(); handleLinkClick(data.id); }}>Open Model Card</a>
<Popup show={showPopup} model_data={popupData} onClose={handleClosePopup} />
</td>
)}
<td className="px-6 py-4">{data.execution_type_name}</td>
<td className="px-6 py-4">{data.url}</td>
<td className="px-6 py-4">{data.uri}</td>
Expand Down
Loading