feat: project setup

This commit is contained in:
darwincereska
2026-01-05 16:56:38 -05:00
parent b6107c7c06
commit 40f8a64a49
38 changed files with 350 additions and 0 deletions

0
CONSTITUTION.md Normal file
View File

0
CONTRIBUTING.md Normal file
View File

0
Dockerfile Normal file
View File

0
Makefile Normal file
View File

39
README.md Normal file
View File

@@ -0,0 +1,39 @@
# SpeakEasy: Know who's talking
## Client flow
1. Client uploads `EPUB`
2. Backend:
- Stores file
- Creates `book_id`
- Publishes job to RabbitMQ
3. Client subscribes:
- `GET /books/{book_id}/stream` via WebSocket
4. Backend:
- Authenticates user
- Remembers: `connection -> book_id`
5. Worker processes text:
- Calls Ollama
- Stores result in Postgres
- Emits "result ready" event
6. Backend:
- Receives event
- Pushes mathing results to the subscribed client
### Example WebSocket message to client
```json
{
"book_id": "book-abc",
"paragraph_id": "p-432",
"speaker": "Mary",
"confidence": 0.87
}
```
## Worker flow
1. Receives job from RabbitMQ
2. Loads paragraph text
3. Embeds paragraph
4. Queries vector DB (pgvector)
5. Builds prompt with retrieved content
6. Sends prompt to Ollama
7. Stores result

18
ai/AI.md Normal file
View File

@@ -0,0 +1,18 @@
# AI
## FILES
- **client** `AI Service Clients`
- client.go `Client Interface`
- ollama.go `Ollama HTTP Client`
- **detector** `Speaker Detection Logic`
- context.go `Context tracking for conversations`
- patterns.go `Rule-based Fallback Detection`
- speaker.go `Main Speaker Detection`
- **models** `Model Management`
- config.go `Model Configurations`
- manager.go `Model Downloading/Switching`
- registry.go `Available Models Registry`
- **prompts** `Prompt Templates`
- speaker_detection.go `Prompts for Speaker Identification`
- templates.go `Prompt Template Utilities`

2
ai/client/client.go Normal file
View File

@@ -0,0 +1,2 @@
package client

2
ai/client/ollama.go Normal file
View File

@@ -0,0 +1,2 @@
package client

2
ai/detector/context.go Normal file
View File

@@ -0,0 +1,2 @@
package detector

2
ai/detector/patterns.go Normal file
View File

@@ -0,0 +1,2 @@
package detector

2
ai/detector/speaker.go Normal file
View File

@@ -0,0 +1,2 @@
package detector

2
ai/models/config.go Normal file
View File

@@ -0,0 +1,2 @@
package models

2
ai/models/manager.go Normal file
View File

@@ -0,0 +1,2 @@
package models

2
ai/models/registry.go Normal file
View File

@@ -0,0 +1,2 @@
package models

View File

@@ -0,0 +1,2 @@
package prompts

2
ai/prompts/templates.go Normal file
View File

@@ -0,0 +1,2 @@
package prompts

10
app.go Normal file
View File

@@ -0,0 +1,10 @@
package main
import server_config "speakeasy/config/server"
func main() {
sc := server_config.CreateNewConfig()
sc.LoadConfig()
println(sc.SERVER_HOST)
println(sc.SERVER_PORT)
}

0
client/CLIENT.md Normal file
View File

8
config/CONFIG.md Normal file
View File

@@ -0,0 +1,8 @@
# CONFIG
- **server** `Server Configuration`
- config.go
- env.go
- **frontend** `Client Configuration`
- config.go
- env.go

View File

@@ -0,0 +1 @@
package frontend

1
config/frontend/env.go Normal file
View File

@@ -0,0 +1 @@
package frontend

62
config/server/config.go Normal file
View File

@@ -0,0 +1,62 @@
package server
import (
// "log"
"speakeasy/utils/env"
"time"
)
var (
VERSION = "dev"
BUILD_TIME = time.Now()
)
// ServerConfig is a configuration model for the backend
type ServerConfig struct {
PG_HOST string
PG_USER string
PG_PASSWORD string
RABBITMQ_HOST string
RABBITMQ_USER string
RABBITMQ_PASSWORD string
OLLAMA_HOST string
OLLAMA_MODEL_ACCURACY string
SERVER_HOST string
SERVER_PORT int
CLIENT_HOST string
CLIENT_PORT int
VERSION string
BUILD_TIME time.Time
}
// ModelAccuracy is a configuration option for the Ollama Model Manager
type ModelAccuracy string
const (
FAST ModelAccuracy = "FAST" // gemma:2b
BALANCED ModelAccuracy = "BALANCED" // phi3:mini
ACCURATE ModelAccuracy = "ACCURATE" // llama3.1:8b
)
// CreateNewConfig returns an empty server config
func CreateNewConfig() ServerConfig {
return ServerConfig{}
}
// LoadConfig loads config from environment variables
func (c *ServerConfig) LoadConfig() {
c.PG_HOST = env.GetString("PG_HOST", "localhost:8888")
c.PG_USER = env.GetString("PG_USER", "speakeasy")
c.PG_PASSWORD = env.GetString("PG_PASSWORD", "speakeasy")
c.RABBITMQ_HOST = env.GetString("RABBITMQ_HOST", "localhost:5672")
c.RABBITMQ_PASSWORD = env.GetString("RABBITMQ_PASSWORD", "speakeasy")
c.RABBITMQ_USER = env.GetString("RABBITMQ_USER", "speakeasy")
c.OLLAMA_HOST = env.GetString("OLLAMA_HOST", "localhost:11434")
c.OLLAMA_MODEL_ACCURACY = env.GetString("OLLAMA_MODEL_ACCURACY", "BALANCED")
c.SERVER_HOST = env.GetString("SERVER_HOST", "localhost")
c.SERVER_PORT = env.GetInt("SERVER_PORT", 3456)
c.CLIENT_HOST = env.GetString("CLIENT_HOST", "localhost")
c.CLIENT_PORT = env.GetInt("CLIENT_PORT", 3457)
c.VERSION = VERSION
c.BUILD_TIME = BUILD_TIME
}

1
config/server/env.go Normal file
View File

@@ -0,0 +1 @@
package server

54
docker-compose.yml Normal file
View File

@@ -0,0 +1,54 @@
services:
# Postgres with pgvector extension
db:
container_name: speakeasy_db
image: pgvector/pgvector:pg18
restart: unless-stopped
environment:
POSTGRES_USER: speakeasy
POSTGRES_PASSWORD: speakeasy
POSTGRES_DB: speakeasy
ports:
- "8888:5432"
volumes:
- pg_data:/var/lib/postgres
- ./init:/docker-entrypoint-initdb.d
networks:
- speakeasy_network
# RabbitMQ server
rabbitmq:
container_name: speakeasy_rabbitmq
image: rabbitmq:4.2.2-management-alpine
restart: unless-stopped
ports:
- "5672:5672" # Default port
- "15672:15672" # Management port
environment:
RABBITMQ_DEFAULT_USER: speakeasy
RABBITMQ_DEFAULT_PASS: speakeasy
volumes:
- rabbitmq_data:/var/lib/rabbitmq
networks:
- speakeasy_network
# Ollama server
ollama:
container_name: speakeasy_ollama
image: ollama/ollama:latest
restart: unless-stopped
ports:
- "11434:11434"
networks:
- speakeasy_network
volumes:
- ollama_data:/root/.ollama
volumes:
pg_data:
rabbitmq_data:
ollama_data:
networks:
speakeasy_network:

3
go.mod Normal file
View File

@@ -0,0 +1,3 @@
module speakeasy
go 1.25.5

1
init/init_pgvector.sql Normal file
View File

@@ -0,0 +1 @@
CREATE EXTENSION IF NOT EXISTS vector;

9
models/MODELS.md Normal file
View File

@@ -0,0 +1,9 @@
# MODELS
## FILES
- **book** `Interfaces for Elements of the Book`
- model.go `Structs`
- functions.go `Helper Functions`
- **citations** `Interfaces for Interacting With Citations`
- model.go `Structs`
- functions.go `Helper Functions`

8
models/book/functions.go Normal file
View File

@@ -0,0 +1,8 @@
package book
import "fmt"
// String helper method to convert dialogue struct into a string
func (d *Dialogue) String() string {
return fmt.Sprintf("%s", d.Content)
}

43
models/book/model.go Normal file
View File

@@ -0,0 +1,43 @@
package book
// Book is a model for storing chapters, author, title, and total pages
type Book struct {
Title string `json:"title"`
Chapters []Chapter `json:"chapters"`
TotalPages int `json:"total_pages"`
}
// Chapter is a model that holds chaper number and pages within that chapter
type Chapter struct {
Index int `json:"index"` // Chapter number
Pages []Page `json:"pages"`
}
// Page is model that stores page number and paragraphs
type Page struct {
Index int `json:"index"`
Paragraphs []Paragraph `json:"paragraphs"`
}
// Paragraph is a model that stores paragraph number and lines
type Paragraph struct {
Index int `json:"index"`
Lines []Line `json:"lines"`
}
// Line is an interface for storing the content of a line
type Line struct {
Index int `json:"index"`
Content any `json:"content"`
}
// Dialogue is a model that stores the speaker, and text
type Dialogue struct {
Speaker *string `json:"speaker,omitempty"`
Content string `json:"content"`
}
// Narration is a model that stores text that isnt dialogue
type Narration struct {
Content string `json:"content"`

View File

@@ -0,0 +1,13 @@
package citations
import "fmt"
// Method to return a MLA citation as a string
func (c *MLACitation) String() string {
return fmt.Sprintf(`"%s" (%s, %d)`, c.Content, c.LastName, c.PageNumber)
}
// Method to return a APA citation as a string
func (c *APACitation) String() string {
return fmt.Sprintf(`"%s" (%s, %d, p. %d)`, c.Content, c.LastName, c.Year, c.PageNumber)
}

17
models/citations/model.go Normal file
View File

@@ -0,0 +1,17 @@
package citations
// MLACitation is a model for creating an inline citation in the MLA format: (Doe 23)
type MLACitation struct {
Content string `json:"content"`
LastName string `json:"last_name"`
PageNumber int `json:"page_number"`
}
// APACitation is a model for creating an inline citation in the APA format: (Doe, 2020, p. 23)
type APACitation struct {
Content string `json:"content"`
LastName string `json:"last_name"`
Year int `json:"year"`
PageNumber int `json:"page_number"`
}

0
parser/PARSER.md Normal file
View File

0
rabbitmq/RABBITMQ.md Normal file
View File

0
rag/RAG.md Normal file
View File

BIN
speakeasy Executable file

Binary file not shown.

0
ui/UI.md Normal file
View File

1
utils/UTILS.md Normal file
View File

@@ -0,0 +1 @@

41
utils/env/loader.go vendored Normal file
View File

@@ -0,0 +1,41 @@
package env
import (
"os"
"strconv"
)
// GetStringOrNull retrieves a string environment variable or returns the default value if not set
func GetString(name string, defaultValue string) string {
value := os.Getenv(name)
if value == "" {
return defaultValue
}
return value
}
// GetIntOrNull retrieves an int environment variable or returns the default value if not set
func GetInt(name string, defaultValue int) int {
value := os.Getenv(name)
if value == "" {
return defaultValue
}
intValue, err := strconv.Atoi(value)
if err != nil {
return defaultValue
}
return intValue
}
// GetBoolOrNull retrieves a bool environment variable or returns the default value if not set
func GetBool(name string, defaultValue bool) bool {
value := os.Getenv(name)
if value == "" {
return defaultValue
}
boolValue, err := strconv.ParseBool(value)
if err != nil {
return defaultValue
}
return boolValue
}