145 lines
5.3 KiB
Go
145 lines
5.3 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,omitempty"`
|
|
ToolCalls []ToolCall `json:"tool_calls,omitempty"` // assistant message: tool calls initiated by the model
|
|
ToolCallID string `json:"tool_call_id,omitempty"` // tool role message: ID of the tool call this responds to
|
|
Name string `json:"name,omitempty"` // tool role message: name of the tool
|
|
}
|
|
|
|
// ToolCall represents a tool call requested by the LLM.
|
|
type ToolCall struct {
|
|
ID string `json:"id"`
|
|
Type string `json:"type"` // always "function"
|
|
Function ToolCallFunction `json:"function"`
|
|
}
|
|
|
|
// ToolCallFunction holds the function name and arguments for a tool call.
|
|
type ToolCallFunction struct {
|
|
Name string `json:"name"`
|
|
Arguments string `json:"arguments"` // JSON string of arguments
|
|
}
|
|
|
|
// 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"`
|
|
Dimensions int `json:"dimensions,omitempty"`
|
|
}
|
|
|
|
// 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"`
|
|
}
|