Skip to content

Commit

Permalink
Support OpenAI organization for billing. v5.13.22
Browse files Browse the repository at this point in the history
  • Loading branch information
winlinvip committed Feb 2, 2024
1 parent 41f3d52 commit 97d0684
Show file tree
Hide file tree
Showing 10 changed files with 37 additions and 17 deletions.
3 changes: 2 additions & 1 deletion DEVELOPER.md
Original file line number Diff line number Diff line change
Expand Up @@ -1138,7 +1138,8 @@ The following are the update records for the SRS Stack server.
* Room: AI-Talk allow disable ASR/TTS, enable text. v5.13.19
* Room: AI-Talk support dictation mode. v5.13.20
* FFmpeg: Restart if time and speed abnormal. v5.13.21
* Transcript: Fix panic bug for sync goroutines. v5.13.21
* Transcript: Fix panic bug for sync goroutines. [v5.13.21](https://github.com/ossrs/srs-stack/releases/tag/v5.13.21)
* Support OpenAI organization for billing. v5.13.22
* v5.12
* Refine local variable name conf to config. v5.12.1
* Add forced exit on timeout for program termination. v5.12.1
Expand Down
6 changes: 3 additions & 3 deletions platform/ai-talk.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@ func (v *openaiChatService) RequestChat(ctx context.Context, sreq *StageRequest,

system := stage.prompt
system += fmt.Sprintf(" Keep your reply neat, limiting the reply to %v words.", stage.replyLimit)
logger.Tf(ctx, "AI system prompt: %v", system)
messages := []openai.ChatCompletionMessage{
{Role: openai.ChatMessageRoleSystem, Content: system},
}
Expand All @@ -189,8 +188,8 @@ func (v *openaiChatService) RequestChat(ctx context.Context, sreq *StageRequest,
model := stage.chatModel
maxTokens := 1024
temperature := float32(0.9)
logger.Tf(ctx, "AIChat is OPENAI_PROXY: %v, AIT_CHAT_MODEL: %v, AIT_MAX_TOKENS: %v, AIT_TEMPERATURE: %v, window=%v, histories=%v",
v.conf.BaseURL, model, maxTokens, temperature, stage.chatWindow, len(stage.histories))
logger.Tf(ctx, "AIChat is baseURL=%v, org=%v, model=%v, maxTokens=%v, temperature=%v, window=%v, histories=%v, system is %v",
v.conf.BaseURL, v.conf.OrgID, model, maxTokens, temperature, stage.chatWindow, len(stage.histories), system)

client := openai.NewClientWithConfig(v.conf)
gptChatStream, err := client.CreateChatCompletionStream(
Expand Down Expand Up @@ -973,6 +972,7 @@ func (v *Stage) UpdateFromRoom(room *SrsLiveRoom) {

// Initialize the AI services.
v.aiConfig = openai.DefaultConfig(room.AISecretKey)
v.aiConfig.OrgID = room.AIOrganization
v.aiConfig.BaseURL = room.AIBaseURL

// Bind stage to room.
Expand Down
2 changes: 2 additions & 0 deletions platform/live-room.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,8 @@ type SrsAssistant struct {
AIProvider string `json:"aiProvider"`
// The AI secret key.
AISecretKey string `json:"aiSecretKey"`
// The AI organization.
AIOrganization string `json:"aiOrganization"`
// The AI base URL.
AIBaseURL string `json:"aiBaseURL"`

Expand Down
6 changes: 4 additions & 2 deletions platform/transcript.go
Original file line number Diff line number Diff line change
Expand Up @@ -1014,13 +1014,15 @@ type TranscriptConfig struct {
SecretKey string `json:"secretKey"`
// The base URL for AI service.
BaseURL string `json:"baseURL"`
// The AI organization.
Organization string `json:"organization"`
// The language of the stream.
Language string `json:"lang"`
}

func (v TranscriptConfig) String() string {
return fmt.Sprintf("all=%v, key=%vB, base=%v, lang=%v",
v.All, len(v.SecretKey), v.BaseURL, v.Language)
return fmt.Sprintf("all=%v, key=%vB, organization=%v, base=%v, lang=%v",
v.All, len(v.SecretKey), v.Organization, v.BaseURL, v.Language)
}

func (v *TranscriptConfig) Load(ctx context.Context) error {
Expand Down
2 changes: 1 addition & 1 deletion scripts/setup-aapanel/info.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"title": "SRS Stack",
"name": "srs_stack",
"ps": "SRS Stack is an all-in-one, out-of-the-box, and open-source video solution for creating online video services, including live streaming and WebRTC, on the cloud or through self-hosting. Built with SRS, FFmpeg, and WebRTC, it supports various protocols and offers features like authentication, multi-platform streaming, recording, transcoding, virtual live events, transcription, automatic HTTPS, and HTTP Open API.",
"ps": "SRS Stack is an all-in-one, out-of-the-box, and open-source video solution for creating online video services, including live streaming and WebRTC, on the cloud or through self-hosting. Built with SRS, FFmpeg, and WebRTC, it supports various protocols and offers features like authentication, multi-platform streaming, recording, transcoding, virtual live events, transcription, AI assistant, automatic HTTPS, and HTTP Open API.",
"versions": "5.13.21",
"checks": "/www/server/panel/plugin/srs_stack",
"author": "Winlin",
Expand Down
2 changes: 1 addition & 1 deletion scripts/setup-bt/info.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"title": "SRS音视频服务器",
"name": "srs_stack",
"ps": "SRS Stack让你一键拥有自己的视频云解决方案,可以在云上或私有化部署,支持丰富的音视频协议,提供鉴权、私人直播间、多平台转播、录制、转码、虚拟直播、AI字幕、自动HTTPS、开放API等丰富功能,基于SRS、FFmpeg和WebRTC构建。",
"ps": "SRS Stack让你一键拥有自己的视频云解决方案,可以在云上或私有化部署,支持丰富的音视频协议,提供鉴权、私人直播间、多平台转播、录制、转码、虚拟直播、AI字幕、直播间AI助手、自动HTTPS、开放API等丰富功能,基于SRS、FFmpeg和WebRTC构建。",
"versions": "5.13.21",
"checks": "/www/server/panel/plugin/srs_stack",
"author": "Winlin",
Expand Down
8 changes: 7 additions & 1 deletion ui/src/components/OpenAISettings.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {Button, Form, Spinner} from "react-bootstrap";
import {useTranslation} from "react-i18next";
import {useErrorHandler} from "react-error-boundary";

export function OpenAISecretSettings({baseURL, setBaseURL, secretKey, setSecretKey}) {
export function OpenAISecretSettings({baseURL, setBaseURL, secretKey, setSecretKey, organization, setOrganization}) {
const {t} = useTranslation();
const handleError = useErrorHandler();

Expand Down Expand Up @@ -50,7 +50,13 @@ export function OpenAISecretSettings({baseURL, setBaseURL, secretKey, setSecretK
{t('transcript.test')}
</Button> &nbsp;
{checking && <Spinner animation="border" variant="success" style={{verticalAlign: 'middle'}} />}
<p></p>
</div>
<Form.Group className="mb-3">
<Form.Label>{t('transcript.org')}</Form.Label>
<Form.Text> * {t('transcript.org2')}, <a href='https://platform.openai.com/account/organization' target='_blank' rel='noreferrer'>{t('helper.link')}</a></Form.Text>
<Form.Control as="input" defaultValue={organization} onChange={(e) => setOrganization(e.target.value)} />
</Form.Group>
</React.Fragment>
);
}
7 changes: 4 additions & 3 deletions ui/src/pages/ScenarioLiveRoom.js
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ function LiveRoomAssistant({room, requesting, updateRoom}) {
const [aiName, setAiName] = React.useState(room.aiName);
const [aiProvider, setAiProvider] = React.useState(room.aiProvider || 'openai');
const [aiSecretKey, setAiSecretKey] = React.useState(room.aiSecretKey);
const [aiOrganization, setAiOrganization] = React.useState(room.aiOrganization);
const [aiBaseURL, setAiBaseURL] = React.useState(room.aiBaseURL || (language === 'zh' ? '' : 'https://api.openai.com/v1'));
const [aiAsrEnabled, setAiAsrEnabled] = React.useState(room.aiAsrEnabled);
const [aiChatEnabled, setAiChatEnabled] = React.useState(room.aiChatEnabled);
Expand All @@ -439,15 +440,15 @@ function LiveRoomAssistant({room, requesting, updateRoom}) {
e.preventDefault();
updateRoom({
...room, assistant: true,
aiName, aiProvider, aiSecretKey, aiBaseURL, aiAsrLanguage, aiChatModel,
aiName, aiProvider, aiSecretKey, aiOrganization, aiBaseURL, aiAsrLanguage, aiChatModel,
aiChatPrompt, aiChatMaxWindow: parseInt(aiChatMaxWindow),
aiChatMaxWords: parseInt(aiChatMaxWords), aiAsrEnabled: !!aiAsrEnabled,
aiChatEnabled: !!aiChatEnabled, aiTtsEnabled: !!aiTtsEnabled,
aiAsrPrompt,
})
}, [
updateRoom, room, aiName, aiProvider, aiSecretKey, aiBaseURL, aiAsrLanguage, aiChatModel, aiChatPrompt,
aiChatMaxWindow, aiChatMaxWords, aiAsrEnabled, aiChatEnabled, aiTtsEnabled, aiAsrPrompt
aiChatMaxWindow, aiChatMaxWords, aiAsrEnabled, aiChatEnabled, aiTtsEnabled, aiAsrPrompt, aiOrganization
]);

const onDisableRoom = React.useCallback((e) => {
Expand Down Expand Up @@ -538,7 +539,7 @@ function LiveRoomAssistant({room, requesting, updateRoom}) {
<OpenAISecretSettings {...{
baseURL: aiBaseURL, setBaseURL: setAiBaseURL,
secretKey: aiSecretKey, setSecretKey: setAiSecretKey,
targetLanguage: aiAsrLanguage, setTargetLanguage: setAiAsrLanguage
organization: aiOrganization, setOrganization: setAiOrganization,
}} />
<p></p>
<LiveRoomAssistantUpdateButtons {...{requesting, onUpdateRoom, onDisableRoom}} />
Expand Down
10 changes: 7 additions & 3 deletions ui/src/pages/ScenarioTranscript.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ function ScenarioTranscriptImpl({activeKey, defaultEnabled, defaultConf, default
const [refreshNow, setRefreshNow] = React.useState();
const [transcriptEnabled, setTranscriptEnabled] = React.useState(defaultEnabled);
const [secretKey, setSecretKey] = React.useState(defaultConf.secretKey);
const [organization, setOrganization] = React.useState(defaultConf.organization);
const [baseURL, setBaseURL] = React.useState(defaultConf.baseURL || (language === 'zh' ? '' : 'https://api.openai.com/v1'));
const [targetLanguage, setTargetLanguage] = React.useState(defaultConf.lang || language);

Expand Down Expand Up @@ -80,15 +81,15 @@ function ScenarioTranscriptImpl({activeKey, defaultEnabled, defaultConf, default
if (!baseURL) return alert(`Invalid base url ${baseURL}`);

axios.post('/terraform/v1/ai/transcript/apply', {
uuid, all: !!enabled, secretKey, baseURL, lang: targetLanguage,
uuid, all: !!enabled, secretKey, organization, baseURL, lang: targetLanguage,
}, {
headers: Token.loadBearerHeader(),
}).then(res => {
alert(t('helper.setOk'));
console.log(`Transcript: Apply config ok, uuid=${uuid}.`);
success && success();
}).catch(handleError);
}, [t, handleError, secretKey, baseURL, targetLanguage, uuid]);
}, [t, handleError, secretKey, baseURL, targetLanguage, uuid, organization]);

const resetTask = React.useCallback(() => {
setOperating(true);
Expand Down Expand Up @@ -280,7 +281,10 @@ function ScenarioTranscriptImpl({activeKey, defaultEnabled, defaultConf, default
<Accordion.Header>{t('transcript.service')}</Accordion.Header>
<Accordion.Body>
<Form>
<OpenAISecretSettings {...{baseURL, setBaseURL, secretKey, setSecretKey, targetLanguage, setTargetLanguage}} />
<OpenAISecretSettings {...{
baseURL, setBaseURL, secretKey, setSecretKey,
organization, setOrganization,
}} />
<p></p>
<Form.Group className="mb-3">
<Form.Label>{t('transcript.lang')}</Form.Label>
Expand Down
8 changes: 6 additions & 2 deletions ui/src/resources/locale.json
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,8 @@
"key2": "请输入访问AI服务的密钥",
"base": "OpenAI 服务接入地址",
"base2": "请输入访问AI服务的地址,可以设置为OpenAI的地址或者代理地址",
"org": "组织ID",
"org2": "(可选)请输入AI的组织信息,用于区分用户和账单",
"start": "开启AI字幕",
"stop": "关闭AI字幕",
"live": "直播切片队列",
Expand Down Expand Up @@ -479,7 +481,7 @@
"provider": "AI服务商",
"provider2": "请选择AI服务商",
"model": "AI模型",
"model2": "请输入AI模型名称,比如: gpt-3.5-turbo, gpt-3.5-turbo-1106, gpt-4-turbo-preview",
"model2": "请输入AI模型名称,比如: gpt-3.5-turbo, gpt-3.5-turbo-0125, gpt-4-turbo-preview",
"prompt": "提示词",
"prompt2": "这个助手做什么用的?应该具备什么行为?应该避免什么行为?",
"window": "AI上下文消息",
Expand Down Expand Up @@ -726,7 +728,7 @@
"window": "AI Context Window",
"prompt": "Instructions",
"prompt2": "What does this assistant do? How does it behave? What should it avoid being?",
"model2": "Please input AI model name, e.g. gpt-3.5-turbo, gpt-3.5-turbo-1106, gpt-4-turbo-preview",
"model2": "Please input AI model name, e.g. gpt-3.5-turbo, gpt-3.5-turbo-0125, gpt-4-turbo-preview",
"model": "AI Model Name",
"provider2": "Please select AI service provider",
"provider": "AI Provider",
Expand Down Expand Up @@ -821,6 +823,8 @@
"live": "Live Segments Queue",
"stop": "Stop Transcription",
"start": "Start Transcription",
"org": "Organization ID",
"org2": "(Optional) Please input the organization information of AI, used to distinguish users and bills",
"base2": "Please input the service base URL or proxy URL for AI service provider",
"base": "OpenAI Service Base URL",
"key2": "Please input the secret key for AI service provider",
Expand Down

0 comments on commit 97d0684

Please sign in to comment.