|
|
|
|
|
|
|
|
|
|
|
import React, { useState, useEffect } from "react"; |
|
import BudgetSettings from "./budget_settings"; |
|
import BudgetModal from "./budget_modal"; |
|
import EditBudgetModal from "./edit_budget_modal"; |
|
import { |
|
Table, |
|
TableBody, |
|
TableCell, |
|
TableFoot, |
|
TableHead, |
|
TableHeaderCell, |
|
TableRow, |
|
Card, |
|
Button, |
|
Icon, |
|
Text, |
|
Tab, |
|
TabGroup, |
|
TabList, |
|
TabPanel, |
|
TabPanels, |
|
Grid, |
|
} from "@tremor/react"; |
|
import { |
|
InformationCircleIcon, |
|
PencilAltIcon, |
|
PencilIcon, |
|
StatusOnlineIcon, |
|
TrashIcon, |
|
RefreshIcon, |
|
CheckCircleIcon, |
|
XCircleIcon, |
|
QuestionMarkCircleIcon, |
|
} from "@heroicons/react/outline"; |
|
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; |
|
import { getBudgetList, budgetDeleteCall } from "../networking"; |
|
import { message } from "antd"; |
|
interface BudgetSettingsPageProps { |
|
accessToken: string | null; |
|
} |
|
|
|
export interface budgetItem { |
|
budget_id: string; |
|
max_budget: string | null; |
|
rpm_limit: number | null; |
|
tpm_limit: number | null; |
|
updated_at: string; |
|
} |
|
|
|
const BudgetPanel: React.FC<BudgetSettingsPageProps> = ({ accessToken }) => { |
|
const [isModalVisible, setIsModalVisible] = useState(false); |
|
const [isEditModalVisible, setIsEditModalVisible] = useState(false); |
|
const [selectedBudget, setSelectedBudget] = useState<budgetItem | null>(null); |
|
const [budgetList, setBudgetList] = useState<budgetItem[]>([]); |
|
useEffect(() => { |
|
if (!accessToken) { |
|
return; |
|
} |
|
getBudgetList(accessToken).then((data) => { |
|
setBudgetList(data); |
|
}); |
|
}, [accessToken]); |
|
|
|
const handleEditCall = async (budget_id: string, index: number) => { |
|
console.log("budget_id", budget_id) |
|
if (accessToken == null) { |
|
return; |
|
} |
|
|
|
const budget = budgetList.find(budget => budget.budget_id === budget_id) || null; |
|
|
|
|
|
setSelectedBudget(budget); |
|
setIsEditModalVisible(true); |
|
}; |
|
|
|
const handleDeleteCall = async (budget_id: string, index: number) => { |
|
if (accessToken == null) { |
|
return; |
|
} |
|
|
|
message.info("Request made"); |
|
|
|
await budgetDeleteCall(accessToken, budget_id); |
|
|
|
const newBudgetList = [...budgetList]; |
|
newBudgetList.splice(index, 1); |
|
setBudgetList(newBudgetList); |
|
|
|
message.success("Budget Deleted."); |
|
}; |
|
|
|
const handleUpdateCall = async () => { |
|
if (accessToken == null) { |
|
return; |
|
} |
|
getBudgetList(accessToken).then((data) => { |
|
setBudgetList(data); |
|
}); |
|
} |
|
|
|
return ( |
|
<div className="w-full mx-auto flex-auto overflow-y-auto m-8 p-2"> |
|
<Button |
|
size="sm" |
|
variant="primary" |
|
className="mb-2" |
|
onClick={() => setIsModalVisible(true)} |
|
> |
|
+ Create Budget |
|
</Button> |
|
<BudgetModal |
|
accessToken={accessToken} |
|
isModalVisible={isModalVisible} |
|
setIsModalVisible={setIsModalVisible} |
|
setBudgetList={setBudgetList} |
|
/> |
|
{ |
|
selectedBudget && <EditBudgetModal |
|
accessToken={accessToken} |
|
isModalVisible={isEditModalVisible} |
|
setIsModalVisible={setIsEditModalVisible} |
|
setBudgetList={setBudgetList} |
|
existingBudget={selectedBudget} |
|
handleUpdateCall={handleUpdateCall} |
|
/> |
|
} |
|
<Card> |
|
<Text>Create a budget to assign to customers.</Text> |
|
<Table> |
|
<TableHead> |
|
<TableRow> |
|
<TableHeaderCell>Budget ID</TableHeaderCell> |
|
<TableHeaderCell>Max Budget</TableHeaderCell> |
|
<TableHeaderCell>TPM</TableHeaderCell> |
|
<TableHeaderCell>RPM</TableHeaderCell> |
|
</TableRow> |
|
</TableHead> |
|
|
|
<TableBody> |
|
{budgetList |
|
.slice() // Creates a shallow copy to avoid mutating the original array |
|
.sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime()) // Sort by updated_at in descending order |
|
.map((value: budgetItem, index: number) => ( |
|
<TableRow key={index}> |
|
<TableCell>{value.budget_id}</TableCell> |
|
<TableCell>{value.max_budget ? value.max_budget : "n/a"}</TableCell> |
|
<TableCell>{value.tpm_limit ? value.tpm_limit : "n/a"}</TableCell> |
|
<TableCell>{value.rpm_limit ? value.rpm_limit : "n/a"}</TableCell> |
|
<Icon |
|
icon={PencilAltIcon} |
|
size="sm" |
|
onClick={() => handleEditCall(value.budget_id, index)} |
|
/> |
|
<Icon |
|
icon={TrashIcon} |
|
size="sm" |
|
onClick={() => handleDeleteCall(value.budget_id, index)} |
|
/> |
|
</TableRow> |
|
))} |
|
</TableBody> |
|
</Table> |
|
</Card> |
|
<div className="mt-5"> |
|
<Text className="text-base">How to use budget id</Text> |
|
<TabGroup> |
|
<TabList> |
|
<Tab>Assign Budget to Customer</Tab> |
|
<Tab>Test it (Curl)</Tab> |
|
|
|
<Tab>Test it (OpenAI SDK)</Tab> |
|
</TabList> |
|
<TabPanels> |
|
<TabPanel> |
|
<SyntaxHighlighter language="bash"> |
|
{` |
|
curl -X POST --location '<your_proxy_base_url>/end_user/new' \ |
|
|
|
-H 'Authorization: Bearer <your-master-key>' \ |
|
|
|
-H 'Content-Type: application/json' \ |
|
|
|
-d '{"user_id": "my-customer-id', "budget_id": "<BUDGET_ID>"}' # π KEY CHANGE |
|
|
|
`} |
|
</SyntaxHighlighter> |
|
</TabPanel> |
|
<TabPanel> |
|
<SyntaxHighlighter language="bash"> |
|
{` |
|
curl -X POST --location '<your_proxy_base_url>/chat/completions' \ |
|
|
|
-H 'Authorization: Bearer <your-master-key>' \ |
|
|
|
-H 'Content-Type: application/json' \ |
|
|
|
-d '{ |
|
"model": "gpt-3.5-turbo', |
|
"messages":[{"role": "user", "content": "Hey, how's it going?"}], |
|
"user": "my-customer-id" |
|
}' # π KEY CHANGE |
|
|
|
`} |
|
</SyntaxHighlighter> |
|
</TabPanel> |
|
<TabPanel> |
|
<SyntaxHighlighter language="python"> |
|
{`from openai import OpenAI |
|
client = OpenAI( |
|
base_url="<your_proxy_base_url>", |
|
api_key="<your_proxy_key>" |
|
) |
|
|
|
completion = client.chat.completions.create( |
|
model="gpt-3.5-turbo", |
|
messages=[ |
|
{"role": "system", "content": "You are a helpful assistant."}, |
|
{"role": "user", "content": "Hello!"} |
|
], |
|
user="my-customer-id" |
|
) |
|
|
|
print(completion.choices[0].message)`} |
|
</SyntaxHighlighter> |
|
</TabPanel> |
|
</TabPanels> |
|
</TabGroup> |
|
</div> |
|
</div> |
|
); |
|
}; |
|
|
|
export default BudgetPanel; |
|
|