Restructure the monorepo into clear top-level directories: - backend/: Go module root (cmd, internal, pkg, configs, migrations, docs/swagger, scripts, tests, go.mod, Makefile, .air.toml) - deploy/: Docker (Dockerfile, docker-compose*), quickstart, fluentd - docs/: project documentation + reports/ (moved from repo root) - AGENTS.md: new AI coding-agent guide at repo root Update all references to the new layout: - Dockerfile: COPY backend/go.mod, COPY backend/ (context = repo root) - docker-compose files: context ../.., dockerfile deploy/docker/Dockerfile, env_file ../../.env, volume mounts ../../backend:/app - deploy/quickstart/compose.yaml: dockerfile deploy/docker/Dockerfile - CI: working-directory: backend for go commands, file deploy/docker/Dockerfile, coverage path backend/coverage.out, health_check backend/scripts/ - backend/Makefile: docker target uses -f ../deploy/docker/Dockerfile ../ - README: architecture tree, quickstart, config paths updated Move root stray scripts (rename_models.*, run_m11_tests.sh, verify_build.sh, gorm_bool_main.go) to backend/scripts/legacy/. All moves via git mv to preserve history. Build, vet, SQLite tests, and docker compose config verified.
127 lines
4.6 KiB
Go
127 lines
4.6 KiB
Go
package llm
|
|
|
|
import "context"
|
|
|
|
// Provider defines the interface for LLM operations.
|
|
// Inspired by Chatwoot's CaptainAI which uses OpenAI API for:
|
|
// 1. Chat completion (copilot message suggestions)
|
|
// 2. Embedding generation (knowledge base document vectorization)
|
|
// 3. RAG Q&A (retrieve relevant documents via embedding then generate answers)
|
|
// 4. Streaming chat completion (SSE streaming for captain task endpoints)
|
|
type Provider interface {
|
|
// ChatCompletion sends a chat completion request and returns the response.
|
|
ChatCompletion(ctx context.Context, req ChatRequest) (*ChatResponse, error)
|
|
|
|
// CreateEmbedding generates embeddings for the given input texts.
|
|
CreateEmbedding(ctx context.Context, req EmbeddingRequest) (*EmbeddingResponse, error)
|
|
|
|
// ChatCompletionStream sends a streaming chat completion request.
|
|
// Chunks are delivered via the onChunk callback. Return nil when the
|
|
// stream completes naturally, or an error on failure. The caller is
|
|
// responsible for flushing/closing the downstream SSE connection.
|
|
ChatCompletionStream(ctx context.Context, req ChatRequest, onChunk func(StreamChunk) error) error
|
|
}
|
|
|
|
// StreamingProvider is a narrowed interface for contexts that only need
|
|
// streaming capability (e.g. SSE handler wiring in bootstrap). Providers
|
|
// that implement Provider automatically satisfy StreamingProvider since
|
|
// ChatCompletionStream is on the base interface.
|
|
type StreamingProvider interface {
|
|
ChatCompletionStream(ctx context.Context, req ChatRequest, onChunk func(StreamChunk) error) error
|
|
}
|
|
|
|
// ChatRequest represents a request to the chat completion API.
|
|
type ChatRequest struct {
|
|
Model string `json:"model"`
|
|
Messages []ChatMessage `json:"messages"`
|
|
Temperature float64 `json:"temperature,omitempty"`
|
|
MaxTokens int `json:"max_tokens,omitempty"`
|
|
Tools []ToolDefinition `json:"tools,omitempty"`
|
|
Stream bool `json:"stream,omitempty"`
|
|
}
|
|
|
|
// ChatMessage represents a single message in a chat conversation.
|
|
type ChatMessage struct {
|
|
Role string `json:"role"`
|
|
Content string `json:"content"`
|
|
}
|
|
|
|
// ToolDefinition represents a tool that the model can call.
|
|
type ToolDefinition struct {
|
|
Type string `json:"type"`
|
|
Function ToolFunction `json:"function"`
|
|
}
|
|
|
|
// ToolFunction describes a function tool definition.
|
|
type ToolFunction struct {
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
Parameters map[string]interface{} `json:"parameters"`
|
|
}
|
|
|
|
// ChatResponse represents the response from a chat completion API.
|
|
type ChatResponse struct {
|
|
ID string `json:"id"`
|
|
Object string `json:"object"`
|
|
Created int64 `json:"created"`
|
|
Model string `json:"model"`
|
|
Choices []ChatChoice `json:"choices"`
|
|
Usage TokenUsage `json:"usage"`
|
|
}
|
|
|
|
// ChatChoice represents a single choice in a chat completion response.
|
|
type ChatChoice struct {
|
|
Index int `json:"index"`
|
|
Message ChatMessage `json:"message"`
|
|
FinishReason string `json:"finish_reason"`
|
|
}
|
|
|
|
// TokenUsage represents token usage statistics.
|
|
type TokenUsage struct {
|
|
PromptTokens int `json:"prompt_tokens"`
|
|
CompletionTokens int `json:"completion_tokens"`
|
|
TotalTokens int `json:"total_tokens"`
|
|
}
|
|
|
|
// EmbeddingRequest represents a request to the embeddings API.
|
|
type EmbeddingRequest struct {
|
|
Model string `json:"model"`
|
|
Input []string `json:"input"`
|
|
}
|
|
|
|
// EmbeddingResponse represents the response from an embeddings API.
|
|
type EmbeddingResponse struct {
|
|
Object string `json:"object"`
|
|
Data []EmbeddingData `json:"data"`
|
|
Model string `json:"model"`
|
|
Usage TokenUsage `json:"usage"`
|
|
}
|
|
|
|
// EmbeddingData represents a single embedding result.
|
|
type EmbeddingData struct {
|
|
Object string `json:"object"`
|
|
Index int `json:"index"`
|
|
Embedding []float64 `json:"embedding"`
|
|
}
|
|
|
|
// StreamChunk represents a single chunk in a streaming response.
|
|
type StreamChunk struct {
|
|
ID string `json:"id"`
|
|
Object string `json:"object"`
|
|
Created int64 `json:"created"`
|
|
Model string `json:"model"`
|
|
Choices []StreamChoice `json:"choices"`
|
|
}
|
|
|
|
// StreamChoice represents a single choice in a streaming chunk.
|
|
type StreamChoice struct {
|
|
Index int `json:"index"`
|
|
Delta StreamDelta `json:"delta"`
|
|
FinishReason string `json:"finish_reason"`
|
|
}
|
|
|
|
// StreamDelta represents the delta content in a streaming chunk.
|
|
type StreamDelta struct {
|
|
Role string `json:"role,omitempty"`
|
|
Content string `json:"content,omitempty"`
|
|
} |