|
|
|
@@ -0,0 +1,232 @@ |
|
|
|
/* |
|
|
|
Copyright (C) 2025 QuantumNous |
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify |
|
|
|
it under the terms of the GNU Affero General Public License as |
|
|
|
published by the Free Software Foundation, either version 3 of the |
|
|
|
License, or (at your option) any later version. |
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, |
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
|
GNU Affero General Public License for more details. |
|
|
|
|
|
|
|
You should have received a copy of the GNU Affero General Public License |
|
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>. |
|
|
|
|
|
|
|
For commercial licensing, please contact support@quantumnous.com |
|
|
|
*/ |
|
|
|
|
|
|
|
import React, { useState, useMemo, useContext } from 'react'; |
|
|
|
import { |
|
|
|
Card, |
|
|
|
Avatar, |
|
|
|
Typography, |
|
|
|
RadioGroup, |
|
|
|
Radio, |
|
|
|
TextArea, |
|
|
|
Button, |
|
|
|
} from '@douyinfe/semi-ui'; |
|
|
|
import { IconCode } from '@douyinfe/semi-icons'; |
|
|
|
import { copy, showSuccess, showInfo } from '../../../../../helpers'; |
|
|
|
import { StatusContext } from '../../../../../context/Status'; |
|
|
|
|
|
|
|
const { Text } = Typography; |
|
|
|
|
|
|
|
const LANG_OPTIONS = [ |
|
|
|
{ value: 'python', label: 'Python' }, |
|
|
|
{ value: 'java', label: 'Java' }, |
|
|
|
{ value: 'go', label: 'Go' }, |
|
|
|
{ value: 'shell', label: 'Shell' }, |
|
|
|
]; |
|
|
|
|
|
|
|
// 四种语言的调用示例代码模板,使用 __MODEL_NAME__ 与 __BASE_URL__ 作为占位符 |
|
|
|
const getDefaultCodeByLang = () => ({ |
|
|
|
python: ` |
|
|
|
from openai import OpenAI |
|
|
|
|
|
|
|
client = OpenAI( |
|
|
|
api_key="<Your API Key>", |
|
|
|
base_url="__BASE_URL__" |
|
|
|
) |
|
|
|
|
|
|
|
response = client.chat.completions.create( |
|
|
|
model="__MODEL_NAME__", |
|
|
|
messages=[ |
|
|
|
{"role": "system", "content": "You are a helpful assistant."}, |
|
|
|
{"role": "user", "content": "Hello, how are you?"} |
|
|
|
], |
|
|
|
max_tokens=128000, |
|
|
|
temperature=0.7 |
|
|
|
) |
|
|
|
|
|
|
|
print(response.choices[0].message.content) |
|
|
|
`, |
|
|
|
java: ` |
|
|
|
import com.openai.OpenAI; |
|
|
|
import com.openai.models.*; |
|
|
|
|
|
|
|
OpenAI client = new OpenAI("<Your API Key>", "__BASE_URL__"); |
|
|
|
|
|
|
|
ChatCompletionRequest request = ChatCompletionRequest.builder() |
|
|
|
.model("__MODEL_NAME__") |
|
|
|
.messages(Arrays.asList( |
|
|
|
new ChatMessage("system", "You are a helpful assistant."), |
|
|
|
new ChatMessage("user", "Hello, how are you?") |
|
|
|
)) |
|
|
|
.maxTokens(1000) |
|
|
|
.temperature(0.7) |
|
|
|
.build(); |
|
|
|
|
|
|
|
ChatCompletion response = client.chatCompletions().create(request); |
|
|
|
System.out.println(response.getChoices().get(0).getMessage().getContent()); |
|
|
|
`, |
|
|
|
go: ` |
|
|
|
package main |
|
|
|
|
|
|
|
import ( |
|
|
|
"context" |
|
|
|
"fmt" |
|
|
|
"github.com/openai/openai-go" |
|
|
|
) |
|
|
|
|
|
|
|
func main() { |
|
|
|
client := openai.NewClient("<Your API Key>", "__BASE_URL__") |
|
|
|
|
|
|
|
messages := []openai.ChatMessage{ |
|
|
|
{Role: "system", Content: "You are a helpful assistant."}, |
|
|
|
{Role: "user", Content: "Hello, how are you?"}, |
|
|
|
} |
|
|
|
|
|
|
|
response, err := client.ChatCompletions.Create(context.Background(), openai.ChatCompletionRequest{ |
|
|
|
Model: "__MODEL_NAME__", |
|
|
|
Messages: messages, |
|
|
|
MaxTokens: 128000, |
|
|
|
Temperature: 0.7, |
|
|
|
}) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
panic(err) |
|
|
|
} |
|
|
|
|
|
|
|
fmt.Println(response.Choices[0].Message.Content) |
|
|
|
} |
|
|
|
`, |
|
|
|
shell: ` |
|
|
|
#!/bin/bash |
|
|
|
|
|
|
|
API_KEY="<Your API Key>" |
|
|
|
MODEL_ID="__MODEL_NAME__" |
|
|
|
BASE_URL="__BASE_URL__" |
|
|
|
|
|
|
|
curl -X POST "$BASE_URL/v1/chat/completions" \ |
|
|
|
-H "Content-Type: application/json" \ |
|
|
|
-H "Authorization: Bearer $API_KEY" \ |
|
|
|
-d '{ |
|
|
|
"model": "'$MODEL_ID'", |
|
|
|
"messages": [ |
|
|
|
{ |
|
|
|
"role": "system", |
|
|
|
"content": "You are a helpful assistant." |
|
|
|
}, |
|
|
|
{ |
|
|
|
"role": "user", |
|
|
|
"content": "Hello, how are you?" |
|
|
|
} |
|
|
|
], |
|
|
|
"max_tokens": 128000, |
|
|
|
"temperature": 0.7 |
|
|
|
}' |
|
|
|
`, |
|
|
|
}); |
|
|
|
|
|
|
|
const PLACEHOLDER_MODEL = '__MODEL_NAME__'; |
|
|
|
const PLACEHOLDER_BASE_URL = '__BASE_URL__'; |
|
|
|
|
|
|
|
const ModelCodeSnippet = ({ modelData, t }) => { |
|
|
|
const [statusState] = useContext(StatusContext); |
|
|
|
const serverAddress = |
|
|
|
statusState?.status?.server_address || (typeof window !== 'undefined' ? window.location.origin : ''); |
|
|
|
const [lang, setLang] = useState('python'); |
|
|
|
const codeByLang = useMemo(() => { |
|
|
|
const templates = getDefaultCodeByLang(); |
|
|
|
const modelName = modelData?.model_name || ''; |
|
|
|
const baseUrl = serverAddress || ''; |
|
|
|
return Object.fromEntries( |
|
|
|
Object.entries(templates).map(([key, code]) => { |
|
|
|
let result = code.replaceAll(PLACEHOLDER_BASE_URL, baseUrl); |
|
|
|
result = result.replaceAll(PLACEHOLDER_MODEL, modelName); |
|
|
|
return [key, result]; |
|
|
|
}), |
|
|
|
); |
|
|
|
}, [modelData?.model_name, serverAddress]); |
|
|
|
|
|
|
|
const currentCode = codeByLang[lang] || ''; |
|
|
|
|
|
|
|
const handleCopy = async () => { |
|
|
|
if (!currentCode || currentCode.trim() === '') { |
|
|
|
showInfo(t('当前语言暂无示例代码')); |
|
|
|
return; |
|
|
|
} |
|
|
|
const ok = await copy(currentCode); |
|
|
|
if (ok) { |
|
|
|
showSuccess(t('已复制到剪切板')); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
return ( |
|
|
|
<Card className='!rounded-2xl shadow-sm border-0 mb-6'> |
|
|
|
<div className='flex items-center mb-4'> |
|
|
|
<Avatar size='small' color='green' className='mr-2 shadow-md'> |
|
|
|
<IconCode size={16} /> |
|
|
|
</Avatar> |
|
|
|
<div> |
|
|
|
<Text className='text-lg font-medium'>{t('调用示例')}</Text> |
|
|
|
<div className='text-xs text-gray-600'> |
|
|
|
{t('使用 OpenAI 兼容接口调用该模型的示例代码')} |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div className='mb-3'> |
|
|
|
<Text className='text-sm text-semi-color-text-1 mb-2 block'> |
|
|
|
{t('选择语言')} |
|
|
|
</Text> |
|
|
|
<RadioGroup |
|
|
|
type='button' |
|
|
|
value={lang} |
|
|
|
onChange={(e) => setLang(e.target.value)} |
|
|
|
direction='horizontal' |
|
|
|
> |
|
|
|
{LANG_OPTIONS.map((opt) => ( |
|
|
|
<Radio key={opt.value} value={opt.value}> |
|
|
|
{opt.label} |
|
|
|
</Radio> |
|
|
|
))} |
|
|
|
</RadioGroup> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div className='mb-3'> |
|
|
|
<TextArea |
|
|
|
value={currentCode} |
|
|
|
readOnly |
|
|
|
placeholder={t('暂无该语言示例代码')} |
|
|
|
autosize={{ minRows: 8, maxRows: 16 }} |
|
|
|
className='font-mono text-sm' |
|
|
|
style={{ backgroundColor: 'var(--semi-color-fill-0)' }} |
|
|
|
/> |
|
|
|
</div> |
|
|
|
|
|
|
|
<Button |
|
|
|
theme='solid' |
|
|
|
type='primary' |
|
|
|
onClick={handleCopy} |
|
|
|
disabled={!currentCode || currentCode.trim() === ''} |
|
|
|
> |
|
|
|
{t('一键复制代码')} |
|
|
|
</Button> |
|
|
|
</Card> |
|
|
|
); |
|
|
|
}; |
|
|
|
|
|
|
|
export default ModelCodeSnippet; |