Skip to content

Commit

Permalink
feat: support detail debugging (coaidev#118)
Browse files Browse the repository at this point in the history
  • Loading branch information
zmh-program committed Mar 15, 2024
1 parent 14dc100 commit 92fcbab
Show file tree
Hide file tree
Showing 12 changed files with 124 additions and 5 deletions.
2 changes: 1 addition & 1 deletion README_zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ _🚀 **Next Generation AI One-Stop Solution**_
- [x] Chat Completions (support *vision*, *tools_calling* and *function_calling*)
- [x] Image Generation
- [x] Azure OpenAI
- [x] Anthropic Claude (claude-2, claude-2.1, claude-instant)
- [x] Anthropic Claude (support *vision*)
- [x] Slack Claude (deprecated)
- [x] Sparkdesk (support *function_calling*)
- [x] Google Gemini (PaLM2)
Expand Down
2 changes: 2 additions & 0 deletions app/src/admin/api/system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export type GeneralState = {
docs: string;
file: string;
pwa_manifest: string;
debug_mode: boolean;
};

export type MailState = {
Expand Down Expand Up @@ -122,6 +123,7 @@ export const initialSystemState: SystemProps = {
docs: "",
file: "",
pwa_manifest: "",
debug_mode: false,
},
site: {
close_register: false,
Expand Down
2 changes: 2 additions & 0 deletions app/src/resources/i18n/cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,8 @@
"backend": "后端域名",
"backendTip": "后端域名(docker 安装默认路径为 /api),用于接收回调和存储等,默认为空",
"backendPlaceholder": "后端回调域名,默认为空,接受回调必填(如 {{backend}})",
"debugMode": "调试模式",
"debugModeTip": "调试模式,开启后日志将输出详细的请求参数等的日志,用于排查问题",
"mailHost": "发件域名",
"mailPort": "SMTP 端口",
"mailUser": "用户名",
Expand Down
4 changes: 3 additions & 1 deletion app/src/resources/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,9 @@
"image_storeTip": "Images generated by the OpenAI channel DALL-E will be stored on the server to prevent invalidation of the images",
"image_storeNoBackend": "No backend domain configured, cannot enable image storage",
"closeRelay": "Turn off Staging API",
"closeRelayTip": "Turn off the staging API, the staging API will not be available after turning off"
"closeRelayTip": "Turn off the staging API, the staging API will not be available after turning off",
"debugMode": "debugging mode",
"debugModeTip": "Debug mode, after turning on, the log will output detailed request parameters and other logs for troubleshooting"
},
"user": "Users",
"invitation-code": "Invitation Code",
Expand Down
4 changes: 3 additions & 1 deletion app/src/resources/i18n/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,9 @@
"image_storeTip": "OpenAIチャンネルDALL - Eによって生成された画像は、画像の無効化を防ぐためにサーバーに保存されます",
"image_storeNoBackend": "バックエンドドメインが設定されていません。画像ストレージを有効にできません",
"closeRelay": "ステージングAPIをオフにする",
"closeRelayTip": "ステージングAPIをオフにすると、オフにするとステージングAPIは使用できなくなります"
"closeRelayTip": "ステージングAPIをオフにすると、オフにするとステージングAPIは使用できなくなります",
"debugMode": "試験調整モード",
"debugModeTip": "デバッグモード、オンにすると、ログは詳細な要求パラメータとトラブルシューティングのための他のログを出力します"
},
"user": "ユーザー管理",
"invitation-code": "招待コード",
Expand Down
4 changes: 3 additions & 1 deletion app/src/resources/i18n/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,9 @@
"image_storeTip": "Изображения, сгенерированные каналом OpenAI DALL-E, будут храниться на сервере, чтобы предотвратить недействительность изображений",
"image_storeNoBackend": "Нет настроенного внутреннего домена, невозможно включить хранение изображений",
"closeRelay": "Отключить Staging API",
"closeRelayTip": "Отключите промежуточный API, промежуточный API будет недоступен после отключения"
"closeRelayTip": "Отключите промежуточный API, промежуточный API будет недоступен после отключения",
"debugMode": "Режим отладки",
"debugModeTip": "Режим отладки, после включения журнал выведет подробные параметры запроса и другие журналы для устранения неполадок"
},
"user": "Управление пользователями",
"invitation-code": "Код приглашения",
Expand Down
16 changes: 16 additions & 0 deletions app/src/routes/admin/System.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,22 @@ function General({ data, dispatch, onChange }: CompProps<GeneralState>) {
</Button>
</JSONEditorProvider>
</ParagraphItem>
<ParagraphItem>
<Label>
{t("admin.system.debugMode")}
<Tips
className={`inline-block`}
content={t("admin.system.debugModeTip")}
/>
</Label>
<Switch
checked={data.debug_mode}
onCheckedChange={(value) => {
dispatch({ type: "update:general.debug_mode", value });
}}
/>
</ParagraphItem>
<ParagraphSpace />
<ParagraphFooter>
<div className={`grow`} />
<RootDialog />
Expand Down
2 changes: 2 additions & 0 deletions channel/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type generalState struct {
File string `json:"file" mapstructure:"file"`
Docs string `json:"docs" mapstructure:"docs"`
PWAManifest string `json:"pwa_manifest" mapstructure:"pwamanifest"`
DebugMode bool `json:"debug_mode" mapstructure:"debugmode"`
}

type siteState struct {
Expand Down Expand Up @@ -94,6 +95,7 @@ func NewSystemConfig() *SystemConfig {

func (c *SystemConfig) Load() {
globals.NotifyUrl = c.GetBackend()
globals.DebugMode = c.General.DebugMode

globals.CloseRegistration = c.Site.CloseRegister
globals.CloseRelay = c.Site.CloseRelay
Expand Down
1 change: 1 addition & 0 deletions globals/variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const AnonymousMaxThread = 1

var AllowedOrigins []string

var DebugMode bool
var NotifyUrl = ""
var ArticlePermissionGroup []string
var GenerationPermissionGroup []string
Expand Down
60 changes: 60 additions & 0 deletions utils/net.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,44 +74,84 @@ func fillHeaders(req *http.Request, headers map[string]string) {
}

func Http(uri string, method string, ptr interface{}, headers map[string]string, body io.Reader, config []globals.ProxyConfig) (err error) {
if globals.DebugMode {
globals.Debug(fmt.Sprintf("[http] %s %s\nheaders: \n%s\nbody: \n%s", method, uri, Marshal(headers), Marshal(body)))
}

req, err := http.NewRequest(method, uri, body)
if err != nil {
if globals.DebugMode {
globals.Debug(fmt.Sprintf("[http] failed to create request: %s", err))
}

return err
}
fillHeaders(req, headers)

client := newClient(config)
resp, err := client.Do(req)
if err != nil {
if globals.DebugMode {
globals.Debug(fmt.Sprintf("[http] failed to send request: %s", err))
}

return err
}

defer resp.Body.Close()

if err = json.NewDecoder(resp.Body).Decode(ptr); err != nil {
if globals.DebugMode {
globals.Debug(fmt.Sprintf("[http] failed to decode response: %s\nresponse: %s", err, resp.Body))
}

return err
}

if globals.DebugMode {
globals.Debug(fmt.Sprintf("[http] response: %s", Marshal(ptr)))
}
return nil
}

func HttpRaw(uri string, method string, headers map[string]string, body io.Reader, config []globals.ProxyConfig) (data []byte, err error) {
if globals.DebugMode {
globals.Debug(fmt.Sprintf("[http] %s %s\nheaders: \n%s\nbody: \n%s", method, uri, Marshal(headers), Marshal(body)))
}

req, err := http.NewRequest(method, uri, body)
if err != nil {
if globals.DebugMode {
globals.Debug(fmt.Sprintf("[http] failed to create request: %s", err))
}

return nil, err
}
fillHeaders(req, headers)

client := newClient(config)
resp, err := client.Do(req)
if err != nil {
if globals.DebugMode {
globals.Debug(fmt.Sprintf("[http] failed to send request: %s", err))
}

return nil, err
}

defer resp.Body.Close()

if data, err = io.ReadAll(resp.Body); err != nil {
if globals.DebugMode {
globals.Debug(fmt.Sprintf("[http] failed to read response: %s", err))
}

return nil, err
}

if globals.DebugMode {
globals.Debug(fmt.Sprintf("[http] response: %s", string(data)))
}
return data, nil
}

Expand Down Expand Up @@ -159,22 +199,38 @@ func EventSource(method string, uri string, headers map[string]string, body inte

http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}

if globals.DebugMode {
globals.Debug(fmt.Sprintf("[http-stream] %s %s\nheaders: \n%s\nbody: \n%s", method, uri, Marshal(headers), Marshal(body)))
}

client := newClient(config)
req, err := http.NewRequest(method, uri, ConvertBody(body))
if err != nil {
if globals.DebugMode {
globals.Debug(fmt.Sprintf("[http-stream] failed to create request: %s", err))
}

return err
}

fillHeaders(req, headers)

res, err := client.Do(req)
if err != nil {
if globals.DebugMode {
globals.Debug(fmt.Sprintf("[http-stream] failed to send request: %s", err))
}

return err
}

defer res.Body.Close()

if res.StatusCode >= 400 {
if globals.DebugMode {
globals.Debug(fmt.Sprintf("[http-stream] request failed with status: %s\nresponse: %s", res.Status, res.Body))
}

if content, err := io.ReadAll(res.Body); err == nil {
if form, err := Unmarshal[map[string]interface{}](content); err == nil {
data := MarshalWithIndent(form, 2)
Expand All @@ -197,6 +253,10 @@ func EventSource(method string, uri string, headers map[string]string, body inte

data := string(buf[:n])
for _, item := range strings.Split(data, "\n") {
if globals.DebugMode {
globals.Debug(fmt.Sprintf("[http-stream] response: %s", item))
}

segment := strings.TrimSpace(item)
if len(segment) > 0 {
if err := callback(segment); err != nil {
Expand Down
24 changes: 23 additions & 1 deletion utils/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,26 +45,43 @@ func EventScanner(props *EventScannerProps, config ...globals.ProxyConfig) *Even
}
}()

if globals.DebugMode {
globals.Debug(fmt.Sprintf("[sse] event source: %s %s\nheaders: %v\nbody: %v", props.Method, props.Uri, Marshal(props.Headers), Marshal(props.Body)))
}

client := newClient(config)
req, err := http.NewRequest(props.Method, props.Uri, ConvertBody(props.Body))
if err != nil {
if globals.DebugMode {
globals.Debug(fmt.Sprintf("[sse] failed to create request: %s", err))
}

return &EventScannerError{Error: err}
}

fillHeaders(req, props.Headers)

resp, err := client.Do(req)
if err != nil {
if globals.DebugMode {
globals.Debug(fmt.Sprintf("[sse] failed to send request: %s", err))
}

return &EventScannerError{Error: err}
}

defer resp.Body.Close()

if resp.StatusCode >= 400 {
// for error response
body := getErrorBody(resp)
if globals.DebugMode {
globals.Debug(fmt.Sprintf("[sse] request failed with status: %s\nresponse: %s", resp.Status, body))
}

return &EventScannerError{
Error: fmt.Errorf("request failed with status code: %d", resp.StatusCode),
Body: getErrorBody(resp),
Body: body,
}
}

Expand All @@ -91,11 +108,16 @@ func EventScanner(props *EventScannerProps, config ...globals.ProxyConfig) *Even

for scanner.Scan() {
raw := scanner.Text()

if len(raw) <= 5 || !strings.HasPrefix(raw, "data:") {
// for only `data:` partial raw or unexpected chunk
continue
}

if globals.DebugMode {
globals.Debug(fmt.Sprintf("[sse] chunk: %s", raw))
}

chunk := strings.TrimSpace(strings.TrimPrefix(raw, "data:"))
if chunk == "[DONE]" || strings.HasPrefix(chunk, "[DONE]") {
// for done signal
Expand Down
8 changes: 8 additions & 0 deletions utils/tokenizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package utils

import (
"chat/globals"
"fmt"
"github.com/pkoukk/tiktoken-go"
"strings"
)
Expand Down Expand Up @@ -55,6 +56,9 @@ func NumTokensFromMessages(messages []globals.Message, model string) (tokens int
// return len([]rune(data)) * weight

// use the recall method instead (default encoder model is gpt-3.5-turbo-0613)
if globals.DebugMode {
globals.Debug(fmt.Sprintf("[tiktoken] error encoding messages: %s (model: %s), using default model instead", err, model))
}
return NumTokensFromMessages(messages, globals.GPT3Turbo0613)
}

Expand All @@ -65,6 +69,10 @@ func NumTokensFromMessages(messages []globals.Message, model string) (tokens int
tokensPerMessage
}
tokens += 3 // every reply is primed with <|start|>assistant<|message|>

if globals.DebugMode {
globals.Debug(fmt.Sprintf("[tiktoken] num tokens from messages: %d (tokens per message: %d, model: %s)", tokens, tokensPerMessage, model))
}
return tokens
}

Expand Down

0 comments on commit 92fcbab

Please sign in to comment.