fix: transform_request.tsx

don't hardcode to localhost
This commit is contained in:
Krrish Dholakia 2025-04-09 16:35:07 -07:00
parent 86bfb8cd66
commit a1433da4a7
3 changed files with 199 additions and 15 deletions

View file

@ -0,0 +1,161 @@
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;

View file

@ -1074,6 +1074,38 @@ export const organizationDeleteCall = async (
}
};
export const transformRequestCall = async (accessToken: String, request: object) => {
/**
* Transform request
*/
try {
let url = proxyBaseUrl ? `${proxyBaseUrl}/utils/transform_request` : `/utils/transform_request`;
const response = await fetch(url, {
method: "POST",
headers: {
[globalLitellmHeaderName]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(request),
});
if (!response.ok) {
const errorData = await response.text();
handleError(errorData);
throw new Error("Network response was not ok");
}
const data = await response.json();
return data;
} catch (error) {
console.error("Failed to create key:", error);
throw error;
}
}
export const userDailyActivityCall = async (accessToken: String, startTime: Date, endTime: Date, page: number = 1) => {
/**

View file

@ -2,7 +2,7 @@ import React, { useState } from 'react';
import { Button, Select, Tabs, message } from 'antd';
import { CopyOutlined } from '@ant-design/icons';
import { Title } from '@tremor/react';
import { transformRequestCall } from './networking';
interface TransformRequestPanelProps {
accessToken: string | null;
}
@ -79,22 +79,13 @@ ${formattedBody}
};
// 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}`);
if (!accessToken) {
message.error('No access token found');
setIsLoading(false);
return;
}
// Parse the response as JSON
const data = await response.json();
console.log("API response:", data);
const data = await transformRequestCall(accessToken, payload);
// Check if the response has the expected fields
if (data.raw_request_api_base && data.raw_request_body) {