Add files.

This commit is contained in:
2024-04-25 14:37:28 -07:00
parent 191b64e4c4
commit 1656c4cf55
8 changed files with 353 additions and 0 deletions

98
thread/messages.go Normal file
View File

@@ -0,0 +1,98 @@
package thread
import (
"encoding/json"
"fmt"
"io"
"log"
"os"
"path/filepath"
"strings"
"time"
"git.wntrmute.dev/kyle/goutils/die"
)
const timeFormat = "2006-01-02 15:04"
type Message struct {
ID string `json:"id"`
ThreadID string `json:"thread_id"`
Role string `json:"role"`
Status string `json:"status"`
Created int64 `json:"created"`
Updated int64 `json:"updated"`
Object string `json:"object"`
Content []struct {
Type string `json:"type"`
Text struct {
Value string `json:"value"`
Annotations []any `json:"annotations"`
} `json:"text"`
} `json:"content"`
}
func (m *Message) Date() time.Time {
return time.Unix(m.Created/1000, 0)
}
func (m *Message) Header() string {
role := m.Role
switch role {
case "user":
role = strings.ToTitle(os.Getenv("USER"))
case "assistant":
role = "LLM"
default:
// nothing
}
return fmt.Sprintf("[%s] **%s**\n", m.Date().Format(timeFormat), m.Role)
}
func (m *Message) Body() string {
content := []string{}
for _, contentItem := range m.Content {
// TODO: handle different content types
if contentItem.Type != "text" {
continue
}
if contentItem.Text.Annotations != nil {
log.Print("warning: annotation in content not supported")
}
content = append(content, contentItem.Text.Value)
}
return strings.Join(content, "\n\n")
}
func LoadMessages(path string) ([]*Message, error) {
messagesPath := filepath.Join(path, "messages.jsonl")
file, err := os.Open(messagesPath)
die.If(err)
defer file.Close()
jsonParser := json.NewDecoder(file)
var messages []*Message
for err == nil {
var message Message
err = jsonParser.Decode(&message)
if err == nil {
messages = append(messages, &message)
}
}
if err != io.EOF {
return nil, err
}
return messages, nil
}
func (m *Message) String() string {
return m.Header() + m.Body() + "\n"
}

95
thread/thread.go Normal file
View File

@@ -0,0 +1,95 @@
package thread
import (
"encoding/json"
"fmt"
"git.wntrmute.dev/kyle/goutils/die"
"os"
"path/filepath"
"strings"
"time"
)
type Thread struct {
ID string `json:"id"`
Object string `json:"object"`
Title string `json:"title"`
Assistants []struct {
AssistantID string `json:"assistant_id"`
AssistantName string `json:"assistant_name"`
Tools []struct {
Type string `json:"type"`
Enabled bool `json:"enabled"`
Settings struct {
TopK int `json:"top_k"`
ChunkSize int `json:"chunk_size"`
ChunkOverlap int `json:"chunk_overlap"`
RetrievalTemplate string `json:"retrieval_template"`
} `json:"settings"`
} `json:"tools"`
Model struct {
ID string `json:"id"`
Settings struct {
CtxLen int `json:"ctx_len"`
PromptTemplate string `json:"prompt_template"`
LlamaModelPath string `json:"llama_model_path"`
} `json:"settings"`
Parameters struct {
Temperature float64 `json:"temperature"`
TopP float64 `json:"top_p"`
Stream bool `json:"stream"`
MaxTokens int `json:"max_tokens"`
FrequencyPenalty int `json:"frequency_penalty"`
PresencePenalty int `json:"presence_penalty"`
} `json:"parameters"`
Engine string `json:"engine"`
} `json:"model"`
Instructions string `json:"instructions"`
} `json:"assistants"`
Created int64 `json:"created"`
Updated int64 `json:"updated"`
Metadata struct {
LastMessage string `json:"lastMessage"`
} `json:"metadata"`
Messages []*Message
}
func LoadThread(path string) (*Thread, error) {
realPath := filepath.Join(path, "thread.json")
file, err := os.Open(realPath)
die.If(err)
defer file.Close()
jsonParser := json.NewDecoder(file)
var thread Thread
err = jsonParser.Decode(&thread)
die.If(err)
thread.Messages, err = LoadMessages(path)
die.If(err)
return &thread, nil
}
func (t *Thread) Date() time.Time {
return time.Unix(int64(t.Created/1000), 0)
}
func (t *Thread) Header() string {
return fmt.Sprintf("# %s (%s)\n## %s\n", t.Title,
t.Assistants[0].Model.ID, t.Date().Format(timeFormat))
}
func (t *Thread) Body() string {
messages := []string{}
for _, m := range t.Messages {
messages = append(messages, m.String())
}
return strings.Join(messages, "\n")
}
func (t *Thread) String() string {
return t.Header() + "\n" + t.Body()
}

17
thread/thread_test.go Normal file
View File

@@ -0,0 +1,17 @@
package thread
import (
"fmt"
"testing"
)
const testThread = "testdata/thread"
func TestLoadThread(t *testing.T) {
thread, err := LoadThread(testThread)
if err != nil {
t.Fatal(err)
}
fmt.Println(thread)
}