feat: init Go module with config and in-memory note store

This commit is contained in:
2026-05-05 11:23:04 +08:00
parent 184d775a7e
commit deffe14e9c
7 changed files with 177 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
OPENAI_API_KEY=sk-your-api-key-here
OPENAI_BASE_URL=https://api.openai.com/v1
OPENAI_MODEL=gpt-4o
OPENAI_EMBED_MODEL=text-embedding-3-small
DATA_DIR=./data
PORT=8080
+30
View File
@@ -0,0 +1,30 @@
package config
import "os"
type Config struct {
OpenAIAPIKey string
OpenAIBaseURL string
OpenAIModel string
OpenAIEmbedModel string
DataDir string
Port string
}
func Load() *Config {
return &Config{
OpenAIAPIKey: getEnv("OPENAI_API_KEY", ""),
OpenAIBaseURL: getEnv("OPENAI_BASE_URL", "https://api.openai.com/v1"),
OpenAIModel: getEnv("OPENAI_MODEL", "gpt-4o"),
OpenAIEmbedModel: getEnv("OPENAI_EMBED_MODEL", "text-embedding-3-small"),
DataDir: getEnv("DATA_DIR", "./data"),
Port: getEnv("PORT", "8080"),
}
}
func getEnv(key, fallback string) string {
if v := os.Getenv(key); v != "" {
return v
}
return fallback
}
+3
View File
@@ -0,0 +1,3 @@
module eino-test
go 1.23.6
+83
View File
@@ -0,0 +1,83 @@
package store
import (
"context"
"fmt"
"strings"
"sync"
)
type MemoryNoteStore struct {
mu sync.RWMutex
notes map[string]*Note
}
func NewMemoryNoteStore() *MemoryNoteStore {
return &MemoryNoteStore{
notes: make(map[string]*Note),
}
}
func (s *MemoryNoteStore) GetByID(_ context.Context, id string) (*Note, error) {
s.mu.RLock()
defer s.mu.RUnlock()
n, ok := s.notes[id]
if !ok {
return nil, fmt.Errorf("note not found: %s", id)
}
return n, nil
}
func (s *MemoryNoteStore) List(_ context.Context) ([]*Note, error) {
s.mu.RLock()
defer s.mu.RUnlock()
result := make([]*Note, 0, len(s.notes))
for _, n := range s.notes {
result = append(result, n)
}
return result, nil
}
func (s *MemoryNoteStore) Create(_ context.Context, note *Note) error {
s.mu.Lock()
defer s.mu.Unlock()
if _, exists := s.notes[note.ID]; exists {
return fmt.Errorf("note already exists: %s", note.ID)
}
s.notes[note.ID] = note
return nil
}
func (s *MemoryNoteStore) Update(_ context.Context, note *Note) error {
s.mu.Lock()
defer s.mu.Unlock()
if _, exists := s.notes[note.ID]; !exists {
return fmt.Errorf("note not found: %s", note.ID)
}
s.notes[note.ID] = note
return nil
}
func (s *MemoryNoteStore) Delete(_ context.Context, id string) error {
s.mu.Lock()
defer s.mu.Unlock()
if _, exists := s.notes[id]; !exists {
return fmt.Errorf("note not found: %s", id)
}
delete(s.notes, id)
return nil
}
func (s *MemoryNoteStore) SearchByKeyword(_ context.Context, keyword string) ([]*Note, error) {
s.mu.RLock()
defer s.mu.RUnlock()
keyword = strings.ToLower(keyword)
var result []*Note
for _, n := range s.notes {
if strings.Contains(strings.ToLower(n.Title), keyword) ||
strings.Contains(strings.ToLower(n.Content), keyword) {
result = append(result, n)
}
}
return result, nil
}
+25
View File
@@ -0,0 +1,25 @@
package store
import "time"
type Note struct {
ID string `json:"id"`
Title string `json:"title"`
Content string `json:"content"`
Tags []string `json:"tags"`
FilePath string `json:"file_path"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type Chunk struct {
NoteID string
Index int
Content string
Embedding []float64
}
type SearchResult struct {
Note *Note `json:"note"`
Score float64 `json:"score"`
}
+12
View File
@@ -0,0 +1,12 @@
package store
import "context"
type NoteStore interface {
GetByID(ctx context.Context, id string) (*Note, error)
List(ctx context.Context) ([]*Note, error)
Create(ctx context.Context, note *Note) error
Update(ctx context.Context, note *Note) error
Delete(ctx context.Context, id string) error
SearchByKeyword(ctx context.Context, keyword string) ([]*Note, error)
}
+18
View File
@@ -0,0 +1,18 @@
package main
import (
"fmt"
"log"
"eino-test/config"
"eino-test/internal/store"
)
func main() {
cfg := config.Load()
noteStore := store.NewMemoryNoteStore()
_ = noteStore
log.Printf("Server starting on port %s (data dir: %s)", cfg.Port, cfg.DataDir)
fmt.Println("Knowledge Assistant ready")
}