mirror of
https://github.com/BerriAI/litellm.git
synced 2025-04-25 02:34:29 +00:00
Revert "docs: initial commit adding api playground to docs"
This reverts commit 9d68008152
.
This commit is contained in:
parent
9d68008152
commit
032f459cbf
7 changed files with 19 additions and 1803 deletions
|
@ -1,9 +0,0 @@
|
||||||
---
|
|
||||||
title: Transform Request Playground
|
|
||||||
description: See how LiteLLM transforms your requests for different providers
|
|
||||||
hide_table_of_contents: true
|
|
||||||
---
|
|
||||||
|
|
||||||
import TransformRequestPlayground from '@site/src/components/TransformRequestPlayground';
|
|
||||||
|
|
||||||
<TransformRequestPlayground />
|
|
1215
docs/my-website/package-lock.json
generated
1215
docs/my-website/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -25,10 +25,7 @@
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"sharp": "^0.32.6",
|
"sharp": "^0.32.6",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1"
|
||||||
"antd": "^4.24.0",
|
|
||||||
"@ant-design/icons": "^4.8.0",
|
|
||||||
"@tremor/react": "^2.0.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@docusaurus/module-type-aliases": "2.4.1"
|
"@docusaurus/module-type-aliases": "2.4.1"
|
||||||
|
|
|
@ -519,13 +519,6 @@ const sidebars = {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"troubleshoot",
|
"troubleshoot",
|
||||||
{
|
|
||||||
type: 'category',
|
|
||||||
label: 'Playground',
|
|
||||||
items: [
|
|
||||||
'playground/transform_request',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,161 +0,0 @@
|
||||||
import React, { useState } from 'react';
|
|
||||||
import styles from './transform_request.module.css';
|
|
||||||
|
|
||||||
const DEFAULT_REQUEST = {
|
|
||||||
"model": "bedrock/gpt-4",
|
|
||||||
"messages": [
|
|
||||||
{
|
|
||||||
"role": "system",
|
|
||||||
"content": "You are a helpful assistant."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "user",
|
|
||||||
"content": "Explain quantum computing in simple terms"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"temperature": 0.7,
|
|
||||||
"max_tokens": 500,
|
|
||||||
"stream": true
|
|
||||||
};
|
|
||||||
|
|
||||||
type ViewMode = 'split' | 'request' | 'transformed';
|
|
||||||
|
|
||||||
const TransformRequestPlayground: React.FC = () => {
|
|
||||||
const [request, setRequest] = useState(JSON.stringify(DEFAULT_REQUEST, null, 2));
|
|
||||||
const [transformedRequest, setTransformedRequest] = useState('');
|
|
||||||
const [viewMode, setViewMode] = useState<ViewMode>('split');
|
|
||||||
|
|
||||||
const handleTransform = async () => {
|
|
||||||
try {
|
|
||||||
// Here you would make the actual API call to transform the request
|
|
||||||
// For now, we'll just set a sample response
|
|
||||||
const sampleResponse = `curl -X POST \\
|
|
||||||
https://api.openai.com/v1/chat/completions \\
|
|
||||||
-H 'Authorization: Bearer sk-xxx' \\
|
|
||||||
-H 'Content-Type: application/json' \\
|
|
||||||
-d '{
|
|
||||||
"model": "gpt-4",
|
|
||||||
"messages": [
|
|
||||||
{
|
|
||||||
"role": "system",
|
|
||||||
"content": "You are a helpful assistant."
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"temperature": 0.7
|
|
||||||
}'`;
|
|
||||||
setTransformedRequest(sampleResponse);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error transforming request:', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCopy = () => {
|
|
||||||
navigator.clipboard.writeText(transformedRequest);
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderContent = () => {
|
|
||||||
switch (viewMode) {
|
|
||||||
case 'request':
|
|
||||||
return (
|
|
||||||
<div className={styles.panel}>
|
|
||||||
<div className={styles['panel-header']}>
|
|
||||||
<h2>Original Request</h2>
|
|
||||||
<p>The request you would send to LiteLLM /chat/completions endpoint.</p>
|
|
||||||
</div>
|
|
||||||
<textarea
|
|
||||||
className={styles['code-input']}
|
|
||||||
value={request}
|
|
||||||
onChange={(e) => setRequest(e.target.value)}
|
|
||||||
spellCheck={false}
|
|
||||||
/>
|
|
||||||
<div className={styles['panel-footer']}>
|
|
||||||
<button className={styles['transform-button']} onClick={handleTransform}>
|
|
||||||
Transform →
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
case 'transformed':
|
|
||||||
return (
|
|
||||||
<div className={styles.panel}>
|
|
||||||
<div className={styles['panel-header']}>
|
|
||||||
<h2>Transformed Request</h2>
|
|
||||||
<p>How LiteLLM transforms your request for the specified provider.</p>
|
|
||||||
<p className={styles.note}>Note: Sensitive headers are not shown.</p>
|
|
||||||
</div>
|
|
||||||
<div className={styles['code-output-container']}>
|
|
||||||
<pre className={styles['code-output']}>{transformedRequest}</pre>
|
|
||||||
<button className={styles['copy-button']} onClick={handleCopy}>
|
|
||||||
Copy
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className={styles.panel}>
|
|
||||||
<div className={styles['panel-header']}>
|
|
||||||
<h2>Original Request</h2>
|
|
||||||
<p>The request you would send to LiteLLM /chat/completions endpoint.</p>
|
|
||||||
</div>
|
|
||||||
<textarea
|
|
||||||
className={styles['code-input']}
|
|
||||||
value={request}
|
|
||||||
onChange={(e) => setRequest(e.target.value)}
|
|
||||||
spellCheck={false}
|
|
||||||
/>
|
|
||||||
<div className={styles['panel-footer']}>
|
|
||||||
<button className={styles['transform-button']} onClick={handleTransform}>
|
|
||||||
Transform →
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={styles.panel}>
|
|
||||||
<div className={styles['panel-header']}>
|
|
||||||
<h2>Transformed Request</h2>
|
|
||||||
<p>How LiteLLM transforms your request for the specified provider.</p>
|
|
||||||
<p className={styles.note}>Note: Sensitive headers are not shown.</p>
|
|
||||||
</div>
|
|
||||||
<div className={styles['code-output-container']}>
|
|
||||||
<pre className={styles['code-output']}>{transformedRequest}</pre>
|
|
||||||
<button className={styles['copy-button']} onClick={handleCopy}>
|
|
||||||
Copy
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={styles['transform-playground']}>
|
|
||||||
<div className={styles['view-toggle']}>
|
|
||||||
<button
|
|
||||||
className={viewMode === 'split' ? styles.active : ''}
|
|
||||||
onClick={() => setViewMode('split')}
|
|
||||||
>
|
|
||||||
Split View
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className={viewMode === 'request' ? styles.active : ''}
|
|
||||||
onClick={() => setViewMode('request')}
|
|
||||||
>
|
|
||||||
Request
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className={viewMode === 'transformed' ? styles.active : ''}
|
|
||||||
onClick={() => setViewMode('transformed')}
|
|
||||||
>
|
|
||||||
Transformed
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div className={styles['playground-container']}>
|
|
||||||
{renderContent()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default TransformRequestPlayground;
|
|
|
@ -1,215 +0,0 @@
|
||||||
.transform-playground {
|
|
||||||
width: 100%;
|
|
||||||
margin: 0;
|
|
||||||
padding: 2rem;
|
|
||||||
background: var(--ifm-background-color);
|
|
||||||
min-height: calc(70vh - 42px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.playground-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 1.5rem;
|
|
||||||
width: 100%;
|
|
||||||
margin-top: 1rem;
|
|
||||||
min-height: calc(70vh - 140px);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
|
||||||
.playground-container {
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel {
|
|
||||||
padding: 2rem;
|
|
||||||
min-width: 45%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
background: var(--ifm-background-surface-color);
|
|
||||||
border: 1px solid var(--ifm-color-emphasis-300);
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 1.5rem;
|
|
||||||
min-height: calc(70vh - 140px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-header {
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-header h2 {
|
|
||||||
font-size: 1.25rem;
|
|
||||||
font-weight: 600;
|
|
||||||
margin: 0 0 0.5rem 0;
|
|
||||||
color: var(--ifm-heading-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-header p {
|
|
||||||
color: var(--ifm-color-emphasis-600);
|
|
||||||
margin: 0;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-header .note {
|
|
||||||
font-size: 0.75rem;
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
color: var(--ifm-color-emphasis-500);
|
|
||||||
}
|
|
||||||
|
|
||||||
.code-input {
|
|
||||||
flex: 1;
|
|
||||||
width: 100%;
|
|
||||||
padding: 1rem;
|
|
||||||
background: var(--ifm-background-color);
|
|
||||||
border: 1px solid var(--ifm-color-emphasis-300);
|
|
||||||
border-radius: 8px;
|
|
||||||
font-family: var(--ifm-font-family-monospace);
|
|
||||||
font-size: 0.875rem;
|
|
||||||
color: var(--ifm-color-content);
|
|
||||||
resize: none;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
min-height: calc(70vh - 245px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.code-output-container {
|
|
||||||
position: relative;
|
|
||||||
background: var(--ifm-background-color);
|
|
||||||
border: 1px solid var(--ifm-color-emphasis-300);
|
|
||||||
border-radius: 8px;
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
overflow: hidden;
|
|
||||||
min-height: calc(70vh - 245px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.code-output {
|
|
||||||
padding: 1rem;
|
|
||||||
font-family: var(--ifm-font-family-monospace);
|
|
||||||
font-size: 0.875rem;
|
|
||||||
margin: 0;
|
|
||||||
overflow: auto;
|
|
||||||
flex: 1;
|
|
||||||
color: var(--ifm-color-content);
|
|
||||||
white-space: pre-wrap;
|
|
||||||
word-break: break-word;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.code-output .string { color: #a8ff60; }
|
|
||||||
.code-output .number { color: #ff9d00; }
|
|
||||||
.code-output .boolean { color: #ff628c; }
|
|
||||||
.code-output .null { color: #ff628c; }
|
|
||||||
.code-output .key { color: #5ccfe6; }
|
|
||||||
|
|
||||||
.panel-footer {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
margin-top: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.transform-button {
|
|
||||||
display: inline-flex !important;
|
|
||||||
align-items: center !important;
|
|
||||||
gap: 0.5rem !important;
|
|
||||||
background: var(--ifm-color-primary) !important;
|
|
||||||
border: none !important;
|
|
||||||
color: white !important;
|
|
||||||
padding: 0.5rem 1rem !important;
|
|
||||||
border-radius: 6px !important;
|
|
||||||
cursor: pointer !important;
|
|
||||||
font-size: 0.875rem !important;
|
|
||||||
font-weight: 500 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.transform-button:hover {
|
|
||||||
background: var(--ifm-color-primary-darker) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.copy-button {
|
|
||||||
position: absolute !important;
|
|
||||||
right: 0.75rem !important;
|
|
||||||
top: 0.75rem !important;
|
|
||||||
color: var(--ifm-color-emphasis-600) !important;
|
|
||||||
background: transparent !important;
|
|
||||||
border: none !important;
|
|
||||||
cursor: pointer !important;
|
|
||||||
padding: 0.25rem !important;
|
|
||||||
border-radius: 4px !important;
|
|
||||||
display: flex !important;
|
|
||||||
align-items: center !important;
|
|
||||||
gap: 0.25rem !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.copy-button:hover {
|
|
||||||
color: var(--ifm-color-primary) !important;
|
|
||||||
background: var(--ifm-color-emphasis-200) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* View toggle styles */
|
|
||||||
.view-toggle {
|
|
||||||
display: flex;
|
|
||||||
gap: 0.5rem;
|
|
||||||
background: var(--ifm-color-emphasis-100);
|
|
||||||
padding: 0.25rem;
|
|
||||||
border-radius: 6px;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.view-toggle button {
|
|
||||||
padding: 0.5rem 1rem;
|
|
||||||
border-radius: 4px;
|
|
||||||
border: none;
|
|
||||||
background: transparent;
|
|
||||||
color: var(--ifm-color-emphasis-700);
|
|
||||||
font-size: 0.875rem;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.view-toggle button:hover {
|
|
||||||
background: var(--ifm-color-emphasis-200);
|
|
||||||
}
|
|
||||||
|
|
||||||
.view-toggle button.active {
|
|
||||||
background: var(--ifm-color-primary);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Responsive layout */
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.playground-container {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
text-align: right;
|
|
||||||
margin-top: 1.5rem;
|
|
||||||
padding: 0 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer p {
|
|
||||||
color: var(--ifm-color-emphasis-600);
|
|
||||||
font-size: 1rem;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer a {
|
|
||||||
color: var(--ifm-color-primary);
|
|
||||||
text-decoration: none;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer a:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
|
@ -1,210 +0,0 @@
|
||||||
import React, { useState } from 'react';
|
|
||||||
import { Button, message } from 'antd';
|
|
||||||
import { CopyOutlined } from '@ant-design/icons';
|
|
||||||
import styles from './transform_request.module.css';
|
|
||||||
|
|
||||||
interface TransformRequestPanelProps {
|
|
||||||
accessToken: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TransformResponse {
|
|
||||||
raw_request_api_base: string;
|
|
||||||
raw_request_body: Record<string, any>;
|
|
||||||
raw_request_headers: Record<string, string>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TransformRequestPanel: React.FC<TransformRequestPanelProps> = ({ accessToken }) => {
|
|
||||||
const [originalRequestJSON, setOriginalRequestJSON] = useState(`{
|
|
||||||
"model": "bedrock/gpt-4o",
|
|
||||||
"messages": [
|
|
||||||
{
|
|
||||||
"role": "system",
|
|
||||||
"content": "You are a helpful assistant."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "user",
|
|
||||||
"content": "Explain quantum computing in simple terms"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"temperature": 0.7,
|
|
||||||
"max_tokens": 500,
|
|
||||||
"stream": true
|
|
||||||
}`);
|
|
||||||
|
|
||||||
const [transformedResponse, setTransformedResponse] = useState('');
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
|
||||||
|
|
||||||
// Function to format curl command from API response parts
|
|
||||||
const formatCurlCommand = (apiBase: string, requestBody: Record<string, any>, requestHeaders: Record<string, string>) => {
|
|
||||||
// Format the request body as nicely indented JSON with 2 spaces
|
|
||||||
const formattedBody = JSON.stringify(requestBody, null, 2)
|
|
||||||
// Add additional indentation for the entire body
|
|
||||||
.split('\n')
|
|
||||||
.map(line => ` ${line}`)
|
|
||||||
.join('\n');
|
|
||||||
|
|
||||||
// Build headers string with consistent indentation
|
|
||||||
const headerString = Object.entries(requestHeaders)
|
|
||||||
.map(([key, value]) => `-H '${key}: ${value}'`)
|
|
||||||
.join(' \\\n ');
|
|
||||||
|
|
||||||
// Build the curl command with consistent indentation
|
|
||||||
return `curl -X POST \\
|
|
||||||
${apiBase} \\
|
|
||||||
${headerString ? `${headerString} \\\n ` : ''}-H 'Content-Type: application/json' \\
|
|
||||||
-d '{
|
|
||||||
${formattedBody}
|
|
||||||
}'`;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Function to handle the transform request
|
|
||||||
const handleTransform = async () => {
|
|
||||||
setIsLoading(true);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Parse the JSON from the textarea
|
|
||||||
let requestBody;
|
|
||||||
try {
|
|
||||||
requestBody = JSON.parse(originalRequestJSON);
|
|
||||||
} catch (e) {
|
|
||||||
message.error('Invalid JSON in request body');
|
|
||||||
setIsLoading(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the request payload
|
|
||||||
const payload = {
|
|
||||||
call_type: "completion",
|
|
||||||
request_body: requestBody
|
|
||||||
};
|
|
||||||
|
|
||||||
// Make the API call using fetch
|
|
||||||
const response = await fetch('http://0.0.0.0:4000/utils/transform_request', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Authorization': `Bearer ${accessToken}`,
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
body: JSON.stringify(payload)
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP error ${response.status}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the response as JSON
|
|
||||||
const data = await response.json();
|
|
||||||
console.log("API response:", data);
|
|
||||||
|
|
||||||
// Check if the response has the expected fields
|
|
||||||
if (data.raw_request_api_base && data.raw_request_body) {
|
|
||||||
// Format the curl command with the separate parts
|
|
||||||
const formattedCurl = formatCurlCommand(
|
|
||||||
data.raw_request_api_base,
|
|
||||||
data.raw_request_body,
|
|
||||||
data.raw_request_headers || {}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Update state with the formatted curl command
|
|
||||||
setTransformedResponse(formattedCurl);
|
|
||||||
message.success('Request transformed successfully');
|
|
||||||
} else {
|
|
||||||
// Handle the case where the API returns a different format
|
|
||||||
// Try to extract the parts from a string response if needed
|
|
||||||
const rawText = typeof data === 'string' ? data : JSON.stringify(data);
|
|
||||||
setTransformedResponse(rawText);
|
|
||||||
message.info('Transformed request received in unexpected format');
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Error transforming request:', err);
|
|
||||||
message.error('Failed to transform request');
|
|
||||||
} finally {
|
|
||||||
setIsLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add this handler function near your other handlers
|
|
||||||
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
|
||||||
if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {
|
|
||||||
e.preventDefault(); // Prevent default behavior
|
|
||||||
handleTransform();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={styles['transform-playground']}>
|
|
||||||
<div className={styles['playground-container']}>
|
|
||||||
{/* Original Request Panel */}
|
|
||||||
<div className={styles.panel}>
|
|
||||||
<div className={styles['panel-header']}>
|
|
||||||
<h2>Original Request</h2>
|
|
||||||
<p>The request you would send to LiteLLM /chat/completions endpoint.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<textarea
|
|
||||||
className={styles['code-input']}
|
|
||||||
value={originalRequestJSON}
|
|
||||||
onChange={(e) => setOriginalRequestJSON(e.target.value)}
|
|
||||||
onKeyDown={handleKeyDown}
|
|
||||||
placeholder="Press Cmd/Ctrl + Enter to transform"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className={styles['panel-footer']}>
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
onClick={handleTransform}
|
|
||||||
loading={isLoading}
|
|
||||||
className={styles['transform-button']}
|
|
||||||
>
|
|
||||||
<span>Transform</span>
|
|
||||||
<span>→</span>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Transformed Request Panel */}
|
|
||||||
<div className={styles.panel}>
|
|
||||||
<div className={styles['panel-header']}>
|
|
||||||
<h2>Transformed Request</h2>
|
|
||||||
<p>How LiteLLM transforms your request for the specified provider.</p>
|
|
||||||
<p className={styles.note}>Note: Sensitive headers are not shown.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles['code-output-container']}>
|
|
||||||
<pre className={styles['code-output']}>
|
|
||||||
{transformedResponse || `curl -X POST \\
|
|
||||||
https://api.openai.com/v1/chat/completions \\
|
|
||||||
-H 'Authorization: Bearer sk-xxx' \\
|
|
||||||
-H 'Content-Type: application/json' \\
|
|
||||||
-d '{
|
|
||||||
"model": "gpt-4",
|
|
||||||
"messages": [
|
|
||||||
{
|
|
||||||
"role": "system",
|
|
||||||
"content": "You are a helpful assistant."
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"temperature": 0.7
|
|
||||||
}'`}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
type="text"
|
|
||||||
icon={<CopyOutlined />}
|
|
||||||
className={styles['copy-button']}
|
|
||||||
onClick={() => {
|
|
||||||
navigator.clipboard.writeText(transformedResponse || '');
|
|
||||||
message.success('Copied to clipboard');
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={styles.footer}>
|
|
||||||
<p>Found an error? File an issue <a href="https://github.com/BerriAI/litellm/issues" target="_blank" rel="noopener noreferrer">here</a>.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default TransformRequestPanel;
|
|
Loading…
Add table
Add a link
Reference in a new issue