chore: initial commit
This commit is contained in:
19
internal/memory/compress.go
Normal file
19
internal/memory/compress.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package memory
|
||||
|
||||
import "strings"
|
||||
|
||||
func CompressForPrompt(messages []Message, maxChars int) string {
|
||||
if maxChars <= 0 {
|
||||
maxChars = 8000
|
||||
}
|
||||
|
||||
builder := strings.Builder{}
|
||||
for _, msg := range messages {
|
||||
line := msg.Role + ": " + msg.Content + "\n"
|
||||
if builder.Len()+len(line) > maxChars {
|
||||
break
|
||||
}
|
||||
builder.WriteString(line)
|
||||
}
|
||||
return builder.String()
|
||||
}
|
||||
132
internal/memory/store_sqlite.go
Normal file
132
internal/memory/store_sqlite.go
Normal file
@@ -0,0 +1,132 @@
|
||||
package memory
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"laodingbot/internal/logger"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
type Message struct {
|
||||
ID int64
|
||||
ChatID string
|
||||
UserID string
|
||||
Role string
|
||||
Content string
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
type SQLiteStore struct {
|
||||
db *sql.DB
|
||||
log *logger.Logger
|
||||
}
|
||||
|
||||
func NewSQLiteStore(path string, log *logger.Logger) (*SQLiteStore, error) {
|
||||
abs, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Dir(abs), 0o755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
db, err := sql.Open("sqlite", abs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
store := &SQLiteStore{db: db, log: log}
|
||||
if err := store.migrate(); err != nil {
|
||||
_ = db.Close()
|
||||
return nil, err
|
||||
}
|
||||
if log != nil {
|
||||
log.Infof("sqlite store initialized path=%s", abs)
|
||||
}
|
||||
return store, nil
|
||||
}
|
||||
|
||||
func (s *SQLiteStore) Close() error {
|
||||
return s.db.Close()
|
||||
}
|
||||
|
||||
func (s *SQLiteStore) SaveMessage(chatID, userID, role, content string) error {
|
||||
if s.log != nil {
|
||||
s.log.Debugf("save message chat_id=%s role=%s content_len=%d", chatID, role, len(content))
|
||||
}
|
||||
_, err := s.db.Exec(`
|
||||
INSERT INTO messages(chat_id, user_id, role, content, created_at)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
`, chatID, userID, role, content, time.Now().UTC())
|
||||
if err != nil && s.log != nil {
|
||||
s.log.Errorf("save message failed chat_id=%s role=%s err=%v", chatID, role, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *SQLiteStore) LoadRecent(chatID string, limit int) ([]Message, error) {
|
||||
if limit <= 0 {
|
||||
limit = 20
|
||||
}
|
||||
rows, err := s.db.Query(`
|
||||
SELECT id, chat_id, user_id, role, content, created_at
|
||||
FROM messages
|
||||
WHERE chat_id = ?
|
||||
ORDER BY id DESC
|
||||
LIMIT ?
|
||||
`, chatID, limit)
|
||||
if err != nil {
|
||||
if s.log != nil {
|
||||
s.log.Errorf("load recent query failed chat_id=%s err=%v", chatID, err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
messages := make([]Message, 0, limit)
|
||||
for rows.Next() {
|
||||
var m Message
|
||||
if err := rows.Scan(&m.ID, &m.ChatID, &m.UserID, &m.Role, &m.Content, &m.CreatedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
messages = append(messages, m)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
if s.log != nil {
|
||||
s.log.Errorf("load recent row iteration failed chat_id=%s err=%v", chatID, err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for left, right := 0, len(messages)-1; left < right; left, right = left+1, right-1 {
|
||||
messages[left], messages[right] = messages[right], messages[left]
|
||||
}
|
||||
if s.log != nil {
|
||||
s.log.Debugf("load recent success chat_id=%s count=%d", chatID, len(messages))
|
||||
}
|
||||
return messages, nil
|
||||
}
|
||||
|
||||
func (s *SQLiteStore) migrate() error {
|
||||
stmt := `
|
||||
CREATE TABLE IF NOT EXISTS messages (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
chat_id TEXT NOT NULL,
|
||||
user_id TEXT NOT NULL,
|
||||
role TEXT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_messages_chat_id_id ON messages(chat_id, id);
|
||||
`
|
||||
if _, err := s.db.Exec(stmt); err != nil {
|
||||
return fmt.Errorf("migrate schema: %w", err)
|
||||
}
|
||||
if s.log != nil {
|
||||
s.log.Infof("sqlite schema migration completed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user