Add files.
This commit is contained in:
98
thread/messages.go
Normal file
98
thread/messages.go
Normal 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
95
thread/thread.go
Normal 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
17
thread/thread_test.go
Normal 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)
|
||||
}
|
||||
Reference in New Issue
Block a user