Skip to content
This repository was archived by the owner on Jun 11, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
transformerviz.egg-info
node_modules/
dist/
env/
__pycache__
*.pyc

transformerviz/assets/app-build.js
transformerviz/assets/app.css

14 changes: 14 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Contributing

This project welcomes contributions and suggestions. Most contributions require you to
agree to a Contributor License Agreement (CLA) declaring that you have the right to,
and actually do, grant us the rights to use your contribution. For details, visit
https://cla.microsoft.com.

When you submit a pull request, a CLA-bot will automatically determine whether you need
to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the
instructions provided by the bot. You will only need to do this once across all repositories using our CLA.

This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
22 changes: 12 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
# Project
# Transformer Visualizations
Investigations on Transformer Visualizations by the Aether Prototyping and Incubation team.

> This repo has been populated by an initial template to help get you started. Please
> make sure to update the content to build a great experience for community-building.
## Getting Started

As the maintainer of this project, please make a few updates:
### Development Environment Setup
- `python -m pip install --upgrade pip`
- `pip install -r requirements.txt --cache-dir <path-to-pip-cache-dir>` (The `cache-dir` parameter is optional).
- `pip install -e .`
- `npm install`
- `npm run build`

- Improving this README.MD file to provide a great experience
- Updating SUPPORT.MD with content about this project's support experience
- Understanding the security reporting process in SECURITY.MD
- Remove this section from the README
### Running
`PERSPECTIVE_API_KEY=<perspective-api-key> GPT2_MODEL_VERSION=<gpt2-model-version> NUM_RETURN_SEQUENCES=<number-of-return-sequences> TRANSFORMERS_CACHE=<path-to-transformers-cache> FLASK_APP=transformerviz/server.py flask run --host 0.0.0.0 --port 5000` (The `TRANSFORMERS_CACHE` environment variable is optional).
- Point your browser to port 5000 of the server on which the app is running.

## Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
Expand All @@ -25,7 +28,6 @@ For more information see the [Code of Conduct FAQ](https://opensource.microsoft.
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.

## Trademarks

This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
trademarks or logos is subject to and must follow
[Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
Expand Down
25 changes: 0 additions & 25 deletions SUPPORT.md

This file was deleted.

27 changes: 27 additions & 0 deletions development/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!--
Copyright (c) Microsoft Corporation.
Licensed under the MIT License.
-->

<html>
<head>
<style>
</style>
</head>

<body>
<div id="app">
</div>
<script>
window.API_SERVICE_ENVIRONMENT = { port: 5000 };
window.APP_STATE = {
analysisResults: [],
selectedTextIds: [],
error: null,
isFolded: false,
loading: false
};
</script>
</body>

</html>
118 changes: 118 additions & 0 deletions frontend/MainContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import React, { useEffect, useState } from "react";
import { bindActionCreators } from "redux";
import { connect } from 'react-redux';
import {
requestGenerateText,
setGeneratedTextResults,
generateTextFailed,
generateText,
selectText,
submitEditText,
deleteEditText,
foldForm
} from './actions';
import TextGenerationControl from "./components/TextGenerationControl";
import TextGenerationResults from "./components/TextGenerationResults";
import TextDetailedAnalysis from "./components/TextDetailedAnalysis";
import TextRecord from "./models/TextRecord";

type ContainerProps = {
analysisResults: TextRecord[],
error: any,
loading: any,
isFolded: boolean,
selectedTextIds: Array<number>,
requestGenerateText: Function,
setGeneratedTextResults: Function,
generateTextFailed: any,
generateText: any
selectText: Function,
submitEditText: Function,
deleteEditText: Function,
foldForm: Function,
}

const Container: React.FunctionComponent<ContainerProps> = ({
analysisResults,
error,
loading,
isFolded,
selectedTextIds,
requestGenerateText,
setGeneratedTextResults,
generateTextFailed,
generateText,
selectText,
submitEditText,
deleteEditText,
foldForm
}) => {
const getDetailedAnalysisComponent = () => {
if (selectedTextIds.length == 0) {
return (<React.Fragment />);
} else {
const selectedText = selectedTextIds.map(id => analysisResults.find(item => id == item.id))
return (
<TextDetailedAnalysis
selectedText={selectedText}
submitEditText={submitEditText}
deleteEditText={deleteEditText}
/>
);
}
}

useEffect(() => {
const form = document.getElementById("text_gen_form");
const grid = document.getElementById("two_column_grid");
if (grid) {
grid.style.height = `calc(93.5vh - ${form?.offsetHeight}px)`
}
})

return (
<div className="m-4 font-sans">
<TextGenerationControl generateText={generateText} onFold={() => foldForm()} isFolded={isFolded} />
<div id="two_column_grid" className="two-column-grid gap-4">
<TextGenerationResults
analysisResults={analysisResults}
loading={loading}
error={error}
onSelectTextId={selectText}
selectedTextIds={selectedTextIds}
/>
{getDetailedAnalysisComponent()}
</div>
</div>
);
}

function mapStateToProps (state) {
return {
analysisResults: state.analysisResults,
error: state.error,
loading: state.loading,
selectedTextIds: state.selectedTextIds,
isFolded: state.isFolded
};
}

function mapDispatchToProps (dispatch) {
return bindActionCreators({
requestGenerateText: requestGenerateText,
setGeneratedTextResults: setGeneratedTextResults,
generateTextFailed: generateTextFailed,
generateText: generateText,
selectText: selectText,
submitEditText: submitEditText,
deleteEditText: deleteEditText,
foldForm: foldForm,
}, dispatch);
}

const MainContainer = connect(mapStateToProps, mapDispatchToProps)(Container)

export default MainContainer;
100 changes: 100 additions & 0 deletions frontend/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { makeGetCall, makePostCall } from "./api";


function requestGenerateText() {
return {
type: "REQUEST_GENERATE_TEXT"
}
}

function requestEditText(id) {
return {
type: "REQUEST_EDIT_TEXT",
id: id
}
}

function setGeneratedTextResults(generateTextResults) {
return {
type: "SET_GENERATED_TEXT_RESULTS",
text_generation_results: generateTextResults
}
}

function generateTextFailed(error) {
return {
type: "REQUEST_GENERATE_TEXT_FAILED",
error: error
}
}

function generateText(config) {
return function(dispatch) {
dispatch(requestGenerateText());
makePostCall("api/v1/generate_text", config)
.then(response => dispatch(setGeneratedTextResults(response.data.text_generation_results)))
.catch(error => dispatch(generateTextFailed(error)));
}
}

function foldForm() {
return {
type: "FOLD_FORM"
}
}

function selectText(id: number) {
return {
type: "SELECT_TEXT",
id: id
}
}

function setEditTextResults(id: number, text: string, analysis: any) {
return {
type: "EDIT_TEXT_SUCCEEDED",
id: id,
text: text,
analysis: analysis
}

}

function editTextFailed(id: number, error) {
return {
type: "EDIT_TEXT_FAILED",
id: id,
error: error
}
}

function submitEditText(id: number, text: string) {
return function(dispatch) {
dispatch(requestEditText(id));
makePostCall("api/v1/analyze_text", {text: text})
.then(response => dispatch(setEditTextResults(id, text, response.data.text_analysis_result)))
.catch(error => dispatch(editTextFailed(id, error)));
}
}

function deleteEditText(id: number) {
return {
type: "DELETE_EDIT_TEXT",
id: id
}
}


export {
requestGenerateText,
setGeneratedTextResults,
generateTextFailed,
generateText,
selectText,
submitEditText,
deleteEditText,
foldForm,
};
29 changes: 29 additions & 0 deletions frontend/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import axios from 'axios';

var apiServiceEnvironment = window["API_SERVICE_ENVIRONMENT"];
var port = apiServiceEnvironment.port;

/*
if (window.location.port != "") {
port = window.location.port;
}*/

var apiBaseUrl = `${window.location.protocol}//${window.location.hostname}:${port}`;


function makeGetCall(endpoint: string) {
return axios.get<any>(`${apiBaseUrl}/${endpoint}`);
}

function makePostCall(endpoint: string, payload: any) {
return axios.post(`${apiBaseUrl}/${endpoint}`, payload);
}

export {
apiBaseUrl,
makeGetCall,
makePostCall
};
Loading
Loading