Skip to content

Commit

Permalink
调整包结构
Browse files Browse the repository at this point in the history
  • Loading branch information
kkkunny committed Nov 23, 2024
1 parent 0272f57 commit 7f7b855
Show file tree
Hide file tree
Showing 34 changed files with 933 additions and 780 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ go.work

# IDE
.idea
config
config/cookies.json
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ FROM golang:1.22.2-alpine3.19 AS builder
#ENV GOPROXY=https://goproxy.cn,direct
WORKDIR /app
COPY . .
RUN go build -o bin/server -tags release .
RUN go build -o bin/server -tags release ./web


FROM alpine:3.19 AS final
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,18 @@ go 1.22.2

require (
github.com/imroc/req/v3 v3.48.0
github.com/kkkunny/stl v0.0.0-20241105013004-33daba72dee7
github.com/kkkunny/stl v0.0.0-20241116043033-308ffc3d1d79
github.com/labstack/echo/v4 v4.12.0
github.com/labstack/gommon v0.4.2
github.com/sashabaranov/go-openai v1.32.3
github.com/satori/go.uuid v1.2.0
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c
)

require (
github.com/andybalholm/brotli v1.1.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cloudflare/circl v1.5.0 // indirect
github.com/elastic/go-freelru v0.13.0 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/google/pprof v0.0.0-20241023014458-598669927662 // indirect
github.com/gookit/color v1.5.4 // indirect
Expand All @@ -40,5 +41,4 @@ require (
golang.org/x/sys v0.26.0 // indirect
golang.org/x/text v0.19.0 // indirect
golang.org/x/tools v0.26.0 // indirect
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 // indirect
)
8 changes: 2 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/imroc/req/v3 v3.48.0 h1:IYuMGetuwLzOOTzDCquDqs912WNwpsPK0TBXWPIvoqg=
github.com/imroc/req/v3 v3.48.0/go.mod h1:weam9gmyb00QnOtu6HXSnk44dNFkIUQb5QdMx13FeUU=
github.com/kkkunny/stl v0.0.0-20241105013004-33daba72dee7 h1:ZSSwBX8sWhRRTYgWLBWsSXwm5mpNm7WOGqFhDr2/MEc=
github.com/kkkunny/stl v0.0.0-20241105013004-33daba72dee7/go.mod h1:K0PMQJ5hIq9qCNhfTR9UTXUh2njVCbM/elaBT7GS2i8=
github.com/kkkunny/stl v0.0.0-20241116043033-308ffc3d1d79 h1:gWOspbg5H5N20hJ5k61XllkFJRFFKQYu7UO/ApsDAOY=
github.com/kkkunny/stl v0.0.0-20241116043033-308ffc3d1d79/go.mod h1:K0PMQJ5hIq9qCNhfTR9UTXUh2njVCbM/elaBT7GS2i8=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
Expand Down Expand Up @@ -56,8 +56,6 @@ github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B
github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
github.com/sashabaranov/go-openai v1.32.3 h1:6xZ393PbZFoJrgwveBXVZggmyH7zdp4joUdnCy7FFD8=
github.com/sashabaranov/go-openai v1.32.3/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
Expand Down Expand Up @@ -92,7 +90,5 @@ golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
181 changes: 181 additions & 0 deletions hugchat/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
package hugchat

import (
"context"
"encoding/json"
"errors"
"io"
"strings"

stlslices "github.com/kkkunny/stl/container/slices"
stlerr "github.com/kkkunny/stl/error"

"github.com/kkkunny/HuggingChatAPI/config"
"github.com/kkkunny/HuggingChatAPI/hugchat/dto"
"github.com/kkkunny/HuggingChatAPI/internal/api"
)

type Client struct {
tokenProvider TokenProvider
}

func NewClient(tokenProvider TokenProvider) *Client {
return &Client{
tokenProvider: tokenProvider,
}
}

// CheckLogin 检查并刷新登录
func (c *Client) CheckLogin(ctx context.Context) error {
token, err := c.tokenProvider.GetToken(ctx)
if err != nil {
return err
}
login, err := api.CheckLogin(ctx, token)
if err != nil {
return err
}
if login {
return nil
}

token, err = c.tokenProvider.RefreshToken(ctx)
if err != nil {
return err
}
login, err = api.CheckLogin(ctx, token)
if err != nil {
return err
} else if !login {
return stlerr.Errorf("not login")
}
return nil
}

// ListModels 列出模型
func (c *Client) ListModels(ctx context.Context) ([]*dto.ModelInfo, error) {
token, err := c.tokenProvider.GetToken(ctx)
if err != nil {
return nil, err
}
models, _, err := api.ListModelsAndConversations(ctx, token)
if err != nil {
return nil, err
}
return stlslices.Map(models, func(_ int, model *api.ModelInfo) *dto.ModelInfo {
return dto.NewModelInfoFromAPI(model)
}), nil
}

// ListConversations 列出会话
func (c *Client) ListConversations(ctx context.Context) ([]*dto.SimpleConversationInfo, error) {
token, err := c.tokenProvider.GetToken(ctx)
if err != nil {
return nil, err
}
_, convs, err := api.ListModelsAndConversations(ctx, token)
if err != nil {
return nil, err
}
return stlslices.Map(convs, func(_ int, conv *api.SimpleConversationInfo) *dto.SimpleConversationInfo {
return dto.NewSimpleConversationInfoFromAPI(conv)
}), nil
}

// ConversationInfo 获取会话信息
func (c *Client) ConversationInfo(ctx context.Context, convID string) (*dto.ConversationInfo, error) {
token, err := c.tokenProvider.GetToken(ctx)
if err != nil {
return nil, err
}
conv, err := api.ConversationInfo(ctx, token, convID)
return dto.NewConversationInfoFromAPI(conv), err
}

// CreateConversation 创建会话
func (c *Client) CreateConversation(ctx context.Context, model string, systemPrompt string) (*dto.ConversationInfo, error) {
token, err := c.tokenProvider.GetToken(ctx)
if err != nil {
return nil, err
}
createResp, err := api.CreateConversation(ctx, token, &api.CreateConversationRequest{
Model: model,
PrePrompt: systemPrompt,
})
if err != nil {
return nil, err
}

info, err := api.ConversationInfoAfterCreate(ctx, token, createResp.ConversationID)
return dto.NewConversationInfoFromAPI(info), err
}

// DeleteConversation 删除会话
func (c *Client) DeleteConversation(ctx context.Context, convID string) error {
token, err := c.tokenProvider.GetToken(ctx)
if err != nil {
return err
}
return api.DeleteConversation(ctx, token, convID)
}

type ChatConversationParams struct {
LastMsgID string
Inputs string
WebSearch bool
Tools []string
}

func (c *Client) ChatConversation(ctx context.Context, convID string, params *ChatConversationParams) (chan *dto.StreamMessage, error) {
token, err := c.tokenProvider.GetToken(ctx)
if err != nil {
return nil, err
}
msgDataChan, err := api.ChatConversation(ctx, token, &api.ChatConversationRequest{
ConversationID: convID,
ID: params.LastMsgID,
Inputs: params.Inputs,
WebSearch: params.WebSearch,
Tools: params.Tools,
})
if err != nil {
return nil, err
}

msgChan := make(chan *dto.StreamMessage)
go func() {
defer func() {
if err := recover(); err != nil {
_ = config.Logger.Error(err)
}
}()

defer func() {
close(msgChan)
}()

for msgData := range msgDataChan {
data, err := msgData.Unpack()
if err != nil && errors.Is(err, io.EOF) {
break
} else if err != nil {
msgChan <- &dto.StreamMessage{Type: dto.StreamMessageTypeError, Error: err}
break
}
data = strings.TrimSpace(data)
if data == "" {
continue
}

var msg dto.StreamMessage
err = stlerr.ErrorWrap(json.Unmarshal([]byte(data), &msg))
if err != nil {
msgChan <- &dto.StreamMessage{Type: dto.StreamMessageTypeError, Error: err}
break
}

msgChan <- &msg
}
}()
return msgChan, nil
}
28 changes: 18 additions & 10 deletions internal/api/cookie_cache.go → hugchat/cookie_cache.go
Original file line number Diff line number Diff line change
@@ -1,34 +1,36 @@
package api
package hugchat

import (
"encoding/json"
"errors"
"net/http"
"os"
"path/filepath"
"sync"

stlerr "github.com/kkkunny/stl/error"

"github.com/kkkunny/HuggingChatAPI/internal/config"
)

const cookieCachePath = "config/cookies.json"

var globalCookieCache *cookieCache

func init() {
globalCookieCache = newCookieCache()
stlerr.Must(globalCookieCache.Load())
stlerr.Must(globalCookieCache.load())
}

type cookieCache struct {
lock sync.RWMutex
data map[string][]*http.Cookie
}

func newCookieCache() *cookieCache {
return &cookieCache{data: make(map[string][]*http.Cookie)}
}

func (cache *cookieCache) Load() error {
data, err := stlerr.ErrorWith(os.ReadFile(config.CookieCachePath))
func (cache *cookieCache) load() error {
data, err := stlerr.ErrorWith(os.ReadFile(cookieCachePath))
if err != nil && errors.Is(err, os.ErrNotExist) {
return nil
} else if err != nil {
Expand All @@ -38,12 +40,12 @@ func (cache *cookieCache) Load() error {
return err
}

func (cache *cookieCache) Save() error {
err := stlerr.ErrorWrap(os.MkdirAll(filepath.Dir(config.CookieCachePath), 0750))
func (cache *cookieCache) save() error {
err := stlerr.ErrorWrap(os.MkdirAll(filepath.Dir(cookieCachePath), 0750))
if err != nil {
return err
}
file, err := stlerr.ErrorWith(os.OpenFile(config.CookieCachePath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666))
file, err := stlerr.ErrorWith(os.OpenFile(cookieCachePath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666))
if err != nil {
return err
}
Expand All @@ -58,10 +60,16 @@ func (cache *cookieCache) Save() error {
}

func (cache *cookieCache) Get(usr string) []*http.Cookie {
cache.lock.RLock()
defer cache.lock.RUnlock()

return cache.data[usr]
}

func (cache *cookieCache) Set(usr string, cookies []*http.Cookie) error {
cache.lock.Lock()
defer cache.lock.Unlock()

cache.data[usr] = cookies
return cache.Save()
return cache.save()
}
53 changes: 53 additions & 0 deletions hugchat/dto/conversation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package dto

import (
"time"

stlslices "github.com/kkkunny/stl/container/slices"

"github.com/kkkunny/HuggingChatAPI/internal/api"
)

// SimpleConversationInfo 会话简单信息
type SimpleConversationInfo struct {
ID string
Model string
Title string
UpdatedAt time.Time
}

func NewSimpleConversationInfoFromAPI(conv *api.SimpleConversationInfo) *SimpleConversationInfo {
if conv == nil {
return nil
}
return &SimpleConversationInfo{
ID: conv.ID,
Model: conv.Model,
Title: conv.Title,
UpdatedAt: conv.UpdatedAt,
}
}

// ConversationInfo 会话详细信息
type ConversationInfo struct {
ConversationID string
Model string
Title string
PrePrompt string
Messages []*Message
}

func NewConversationInfoFromAPI(conv *api.DetailConversationInfo) *ConversationInfo {
if conv == nil {
return nil
}
return &ConversationInfo{
ConversationID: conv.ConversationID,
Model: conv.Model,
Title: conv.Title,
PrePrompt: conv.PrePrompt,
Messages: stlslices.Map(conv.Messages, func(_ int, msg *api.Message) *Message {
return NewMessageFromAPI(msg)
}),
}
}
Loading

0 comments on commit 7f7b855

Please sign in to comment.