-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
375 additions
and
123 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import React, { useState } from 'react'; | ||
import { Spin, Pagination, Button } from 'antd'; | ||
import { ChartInformation } from '../openai'; | ||
|
||
const contentStyle: React.CSSProperties = { | ||
padding: 50, | ||
background: 'rgba(0, 0, 0, 0.05)', | ||
borderRadius: 4 | ||
}; | ||
const content = <div style={contentStyle} />; | ||
const Loading: React.FC = () => ( | ||
<Spin tip="Loading" size="large"> | ||
{content} | ||
</Spin> | ||
); | ||
|
||
export default function ChartChoices({ | ||
showCharts, | ||
responseList, | ||
handleCodeGeneration | ||
}: { | ||
showCharts: boolean; | ||
responseList: ChartInformation[]; | ||
handleCodeGeneration: (index: number) => void; | ||
}) { | ||
const [listIndex, setListIndex] = useState(0); | ||
const Page: React.FC = () => ( | ||
<Pagination | ||
defaultCurrent={listIndex + 1} | ||
total={responseList.length * 10} | ||
onChange={(page, pageSize) => { | ||
setListIndex(page - 1); | ||
}} | ||
/> | ||
); | ||
return ( | ||
<div className="container"> | ||
{showCharts ? ( | ||
<div className="chart-container"> | ||
<img | ||
className="chart-image" | ||
src={responseList[listIndex].src} | ||
alt={`Image ${listIndex}`} | ||
/> | ||
<h2>{responseList[listIndex].title}</h2> | ||
<p>{responseList[listIndex].description}</p> | ||
<div className="code-btn"> | ||
<Button | ||
type="primary" | ||
onClick={() => { | ||
handleCodeGeneration(responseList.length - listIndex - 1); | ||
}} | ||
> | ||
Show Code | ||
</Button> | ||
</div> | ||
<Page></Page> | ||
</div> | ||
) : ( | ||
<Loading></Loading> | ||
)} | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import { Button } from 'antd'; | ||
import FileUpload from './FileUpload'; | ||
import { TemperatureSelect } from './TemperatureSelect'; | ||
import React, { useState } from 'react'; | ||
import { UserPromptInupt } from './UserPromptInput'; | ||
import ChartChoices from './ChartChoices'; | ||
import { generateChart, ChartInformation } from '../openai'; | ||
import { eventCenter } from '../event'; | ||
|
||
export default function SidePanel() { | ||
let initialList: ChartInformation[] = []; | ||
const [uploadedFile, setUploadedFile] = useState<File | null>(null); | ||
const [generateClicked, setGenerateClicked] = useState(false); | ||
const [showCharts, setShowCharts] = useState(false); | ||
const [responseList, setResponseList] = useState(initialList); | ||
|
||
async function handleGenerateClick() { | ||
if (uploadedFile) { | ||
setGenerateClicked(true); | ||
let list = await generateChart(uploadedFile); | ||
setResponseList(list as ChartInformation[]); | ||
setShowCharts(true); | ||
} else { | ||
alert('No file uploaded.'); | ||
} | ||
} | ||
|
||
async function handleCodeGeneration(index: number) { | ||
setGenerateClicked(false); | ||
eventCenter.emit('addNewCell', index); | ||
} | ||
|
||
return ( | ||
<div className="container"> | ||
{generateClicked ? ( | ||
<ChartChoices | ||
showCharts={showCharts} | ||
responseList={responseList} | ||
handleCodeGeneration={handleCodeGeneration} | ||
/> | ||
) : ( | ||
<> | ||
<div className="upload"> | ||
<FileUpload setFile={setUploadedFile} /> | ||
</div> | ||
<div className="user-prompt"> | ||
<UserPromptInupt></UserPromptInupt> | ||
</div> | ||
<div className="temperature"> | ||
<TemperatureSelect></TemperatureSelect> | ||
</div> | ||
<div className="button-container"> | ||
<Button type="primary" onClick={handleGenerateClick}> | ||
Generate | ||
</Button> | ||
</div> | ||
</> | ||
)} | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
import file_analysis_extension from './file_analysis_extension'; | ||
import stderror_renderer from './stderror_render'; | ||
import { side_panel } from './SidePanel'; | ||
export default [file_analysis_extension, side_panel, stderror_renderer]; | ||
import fixError from './fixError'; | ||
import { smartVis } from './smartVis'; | ||
export default [smartVis, fixError]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
import OpenAI from 'openai'; | ||
import { | ||
TextContentBlock, | ||
ImageFileContentBlock | ||
} from 'openai/resources/beta/threads/messages'; | ||
import { | ||
extractTitleContent, | ||
extractDescriptionContent, | ||
extractPythonCode | ||
} from './util'; | ||
|
||
export interface ChartInformation { | ||
src: string; | ||
title: string; | ||
description: string; | ||
} | ||
|
||
let fileName = ''; | ||
|
||
const openai = new OpenAI({ | ||
apiKey: '', | ||
dangerouslyAllowBrowser: true | ||
}); | ||
|
||
const assistant = await openai.beta.assistants.retrieve( | ||
'asst_SBAKRxzUiVlQxJbHR6RHtkxN' | ||
); | ||
|
||
const thread = await openai.beta.threads.create(); | ||
|
||
export async function generateChart(csvFile: File) { | ||
fileName = csvFile.name; | ||
const file = await openai.files.create({ | ||
file: csvFile, | ||
purpose: 'assistants' | ||
}); | ||
|
||
const prompt = ` | ||
Step-1: Generate three different charts for data visualization based on the attached csv file. | ||
Step-2: After each chart is generated, output a short text description for it. The description should stick to the following format: | ||
<Title>Title of the chart</Title> | ||
<Description>This line charts shows......</Description> | ||
`; | ||
|
||
await openai.beta.threads.messages.create(thread.id, { | ||
role: 'user', | ||
content: prompt, | ||
attachments: [ | ||
{ | ||
file_id: file.id, | ||
tools: [{ type: 'code_interpreter' }] | ||
} | ||
] | ||
}); | ||
|
||
const run = await openai.beta.threads.runs.createAndPoll(thread.id, { | ||
assistant_id: assistant.id | ||
}); | ||
|
||
if (run.status === 'completed') { | ||
const messages = await openai.beta.threads.messages.list(run.thread_id); | ||
const responseArray: ChartInformation[] = []; | ||
for (let message of messages.data) { | ||
if (message.role === 'assistant' && message.content.length === 2) { | ||
// Get image src from the response | ||
const imageContent = <ImageFileContentBlock>message.content[0]; | ||
const src = await getSrcFromFileId(imageContent.image_file.file_id); | ||
|
||
// Get title and description from the response | ||
const textContent = <TextContentBlock>message.content[1]; | ||
const text = textContent.text.value; | ||
const title = extractTitleContent(text); | ||
const description = extractDescriptionContent(text); | ||
|
||
// Put the information together | ||
const response: ChartInformation = { | ||
src: src, | ||
title: title, | ||
description: description | ||
}; | ||
responseArray.push(response); | ||
} | ||
} | ||
return responseArray; | ||
} else { | ||
return run.status; | ||
} | ||
|
||
/** | ||
* Inputs OpenAI File object's id | ||
* Returns src needed in img label | ||
*/ | ||
async function getSrcFromFileId(id: string) { | ||
const imageFile = await openai.files.content(id); | ||
const imageData = await imageFile.arrayBuffer(); | ||
let binary = ''; | ||
let bytes = new Uint8Array(imageData); | ||
for (let i = 0; i < bytes.byteLength; i++) { | ||
binary += String.fromCharCode(bytes[i]); | ||
} | ||
return 'data:image/png;base64,' + window.btoa(binary); | ||
} | ||
} | ||
|
||
export async function generateCode(index: number) { | ||
const prompt = ` | ||
Please output the Python for generating the ${index + 1}-th$ chart. | ||
The Python code should contain necessary import like import pandas as pd. | ||
Also it should contain | ||
`; | ||
|
||
await openai.beta.threads.messages.create(thread.id, { | ||
role: 'user', | ||
content: prompt | ||
}); | ||
|
||
const run = await openai.beta.threads.runs.createAndPoll(thread.id, { | ||
assistant_id: assistant.id | ||
}); | ||
|
||
if (run.status === 'completed') { | ||
const messages = await openai.beta.threads.messages.list(run.thread_id); | ||
const message = messages.data[0]; | ||
const textContent = <TextContentBlock>message.content[0]; | ||
let code = textContent.text.value; | ||
code = extractPythonCode(code, fileName); | ||
return code; | ||
} else { | ||
return run.status; | ||
} | ||
} |
Oops, something went wrong.