-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathmodels.go
208 lines (178 loc) · 5.58 KB
/
models.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
package main
import (
"database/sql/driver"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"sync"
"time"
"github.com/meinside/openai-go"
"github.com/tectiv3/awsnova-go"
tele "gopkg.in/telebot.v3"
"gorm.io/gorm"
)
// config struct for loading a configuration file
type config struct {
// telegram bot api
TelegramBotToken string `json:"telegram_bot_token"`
TelegramServerURL string `json:"telegram_server_url"`
// openai api
OpenAIAPIKey string `json:"openai_api_key"`
OpenAIOrganizationID string `json:"openai_org_id"`
OpenAILatestModel string `json:"openai_latest_model"`
OllamaURL string `json:"ollama_url"`
OllamaModel string `json:"ollama_model"`
OllamaEnabled bool `json:"ollama_enabled"`
GroqModel string `json:"groq_model"`
GroqAPIKey string `json:"groq_api_key"`
AWSAccessKeyID string `json:"aws_access_key_id"`
AWSSecretAccessKey string `json:"aws_secret_access_key"`
AWSModelID string `json:"aws_model_id"`
AWSRegion string `json:"aws_region"`
// other configurations
AllowedTelegramUsers []string `json:"allowed_telegram_users"`
Verbose bool `json:"verbose,omitempty"`
PiperDir string `json:"piper_dir"`
}
type Server struct {
sync.RWMutex
conf config
users []string
ai *openai.Client
nova *awsnova.Client
bot *tele.Bot
db *gorm.DB
}
type User struct {
gorm.Model
TelegramID *int64 `gorm:"nullable:true"`
Username string
ApiKey *string `gorm:"nullable:true"`
OrgID *string `gorm:"nullable:true"`
Threads []Chat
Roles []Role
State *State `json:"state,omitempty" gorm:"type:text"`
}
type Role struct {
gorm.Model
UserID uint `json:"user_id"`
Name string
Prompt string
}
type Chat struct {
gorm.Model
mutex sync.Mutex `gorm:"-"`
ChatID int64 `sql:"chat_id" json:"chat_id"`
UserID uint `json:"user_id" gorm:"nullable:false"`
RoleID *uint `json:"role_id" gorm:"nullable:true"`
MessageID *string `json:"last_message_id" gorm:"nullable:true"`
Lang string
History []ChatMessage
User User `gorm:"foreignKey:UserID;references:ID;fetch:join"`
Role Role `gorm:"foreignKey:RoleID;references:ID;fetch:join"`
Temperature float64
ModelName string
MasterPrompt string
Stream bool
QA bool
Voice bool
ConversationAge int64
TotalTokens int `json:"total_tokens"`
}
type ChatMessage struct {
ID uint `gorm:"primarykey"`
CreatedAt time.Time
UpdatedAt time.Time
ChatID int64 `sql:"chat_id" json:"chat_id"`
Role openai.ChatMessageRole `json:"role"`
ToolCallID *string `json:"tool_call_id,omitempty"`
Content *string `json:"content,omitempty"`
ImagePath *string `json:"image_path,omitempty"`
// for function call
ToolCalls ToolCalls `json:"tool_calls,omitempty" gorm:"type:text"` // when role == 'assistant'
}
// ToolCalls is a custom type that will allow us to implement
// the driver.Valuer and sql.Scanner interfaces on a slice of ToolCall.
type ToolCalls []ToolCall
type ToolCall struct {
ID string `json:"id"`
Type string `json:"type"` // == 'function'
Function openai.ToolCallFunction `json:"function"`
}
// Value implements the driver.Valuer interface, allowing
// for converting the ToolCalls to a JSON string for database storage.
func (tc ToolCalls) Value() (driver.Value, error) {
if tc == nil {
return nil, nil
}
return json.Marshal(tc)
}
// Scan implements the sql.Scanner interface, allowing for
// converting a JSON string from the database back into the ToolCalls slice.
func (tc *ToolCalls) Scan(value interface{}) error {
if value == nil {
*tc = nil
return nil
}
b, ok := value.([]byte)
if !ok {
return fmt.Errorf("type assertion to []byte failed")
}
return json.Unmarshal(b, &tc)
}
type GPTResponse interface {
Type() string // direct, array, image, audio, async
Value() interface{} // string, []string
CanReply() bool // if true replyMenu need to be shown
}
// WAV writer struct
type wavWriter struct {
w io.Writer
}
// WAV file header struct
type wavHeader struct {
RIFFID [4]byte // RIFF header
FileSize uint32 // file size - 8
WAVEID [4]byte // WAVE header
FMTID [4]byte // fmt header
Subchunk1Size uint32 // size of the fmt chunk
AudioFormat uint16 // audio format code
NumChannels uint16 // number of channels
SampleRate uint32 // sample rate
ByteRate uint32 // bytes per second
BlockAlign uint16 // block align
BitsPerSample uint16 // bits per sample
DataID [4]byte // data header
Subchunk2Size uint32 // size of the data chunk
}
// RestrictConfig defines config for Restrict middleware.
type RestrictConfig struct {
// Chats is a list of chats that are going to be affected
// by either In or Out function.
Usernames []string
// In defines a function that will be called if the chat
// of an update will be found in the Chats list.
In tele.HandlerFunc
// Out defines a function that will be called if the chat
// of an update will NOT be found in the Chats list.
Out tele.HandlerFunc
}
func in_array(needle string, haystack []string) bool {
for _, v := range haystack {
if needle == v {
return true
}
}
return false
}
type CoinCap struct {
Data struct {
Symbol string `json:"symbol"`
PriceUsd string `json:"priceUsd"`
} `json:"data"`
Timestamp int64 `json:"timestamp"`
}
func toBase64(b []byte) string {
return base64.StdEncoding.EncodeToString(b)
}