Migrate LLM client to OpenAI SDK and implement WebUI-specific fileID handling

This commit is contained in:
2026-03-10 17:54:50 +08:00
parent 49f6297631
commit 0e1a800646
23 changed files with 1162 additions and 8201 deletions

View File

@@ -18,9 +18,10 @@ import (
)
type IncomingMessage struct {
ChatID string
UserID string
Text string
ChatID string
UserID string
Text string
FileIDs []string
}
type ChatHandler func(context.Context, IncomingMessage) (string, error)
@@ -37,9 +38,41 @@ type Bot struct {
}
type chatRequest struct {
Text string `json:"text"`
SessionID string `json:"session_id"`
UserID string `json:"user_id"`
Text string `json:"text"`
SessionID string `json:"session_id"`
UserID string `json:"user_id"`
FileIDs []string `json:"file_ids"`
}
func (r *chatRequest) UnmarshalJSON(data []byte) error {
type rawChatRequest struct {
Text string `json:"text"`
SessionID string `json:"session_id"`
SessionIDCamel string `json:"sessionId"`
UserID string `json:"user_id"`
UserIDCamel string `json:"userId"`
FileIDs json.RawMessage `json:"file_ids"`
FileIDsCamel json.RawMessage `json:"fileIds"`
FileIDsFlat json.RawMessage `json:"fileids"`
FileID json.RawMessage `json:"file_id"`
}
var raw rawChatRequest
if err := json.Unmarshal(data, &raw); err != nil {
return err
}
r.Text = raw.Text
r.SessionID = firstNonEmpty(raw.SessionID, raw.SessionIDCamel)
r.UserID = firstNonEmpty(raw.UserID, raw.UserIDCamel)
rawIDs := firstNonEmptyRaw(raw.FileIDs, raw.FileIDsCamel, raw.FileIDsFlat, raw.FileID)
ids, err := decodeStringList(rawIDs)
if err != nil {
return err
}
r.FileIDs = ids
return nil
}
type chatResponse struct {
@@ -158,9 +191,10 @@ func (b *Bot) handleChat(w http.ResponseWriter, r *http.Request) {
userID := b.resolveID(req.UserID, "user")
reply, err := b.chatHandler(r.Context(), IncomingMessage{
ChatID: sessionID,
UserID: userID,
Text: req.Text,
ChatID: sessionID,
UserID: userID,
Text: req.Text,
FileIDs: req.FileIDs,
})
if err != nil {
if b.log != nil {
@@ -176,6 +210,65 @@ func (b *Bot) handleChat(w http.ResponseWriter, r *http.Request) {
})
}
func decodeStringList(raw json.RawMessage) ([]string, error) {
if len(raw) == 0 {
return nil, nil
}
var list []string
if err := json.Unmarshal(raw, &list); err == nil {
return nonEmptyIDs(list), nil
}
var single string
if err := json.Unmarshal(raw, &single); err == nil {
if strings.TrimSpace(single) == "" {
return nil, nil
}
return nonEmptyIDs(strings.Split(single, ",")), nil
}
return nil, fmt.Errorf("invalid file ids format")
}
func firstNonEmptyRaw(vals ...json.RawMessage) json.RawMessage {
for _, v := range vals {
if len(v) > 0 {
return v
}
}
return nil
}
func firstNonEmpty(vals ...string) string {
for _, v := range vals {
if strings.TrimSpace(v) != "" {
return v
}
}
return ""
}
func nonEmptyIDs(ids []string) []string {
if len(ids) == 0 {
return nil
}
out := make([]string, 0, len(ids))
seen := map[string]struct{}{}
for _, id := range ids {
id = strings.TrimSpace(id)
if id == "" {
continue
}
if _, ok := seen[id]; ok {
continue
}
seen[id] = struct{}{}
out = append(out, id)
}
return out
}
func (b *Bot) handleUpload(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
writeJSON(w, http.StatusMethodNotAllowed, errorResponse{Error: "method not allowed"})