ai

package module
v0.6.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 20, 2026 License: MIT Imports: 19 Imported by: 0

README ¶

GoREST AI Plugin

Production-ready AI API abstraction layer plugin for GoREST with unified support for multiple AI providers.

Features

🤖 Multiple AI Providers
  • Anthropic (Claude) - Claude 3.5 Sonnet, Claude 3 Opus, Claude 3 Haiku
  • OpenAI (ChatGPT) - GPT-4, GPT-3.5 Turbo
  • Google (Gemini) - Gemini Pro, Gemini Ultra
  • Mistral AI - Mistral Large, Mistral Medium, Mistral Tiny
🚀 Production Features
  • ✅ Provider Abstraction - Unified interface for all AI providers
  • ✅ Intelligent Caching - SHA256-based caching with configurable TTL
  • ✅ Automatic Fallback - Priority-based failover between providers
  • ✅ Quota Management - Per-user request and token limits
  • ✅ Cost Tracking - Token-based cost calculation and analytics
  • ✅ Rate Limiting - Token bucket algorithm with configurable limits
  • ✅ Streaming Support - Server-Sent Events (SSE) for real-time responses
  • ✅ Audit Logging - Complete request/response tracking
  • ✅ Multi-Database - PostgreSQL, MySQL, SQLite support
  • ✅ OpenAPI Integration - Automatic API documentation

Installation

go get github.com/nicolasbonnici/gorest-ai

Quick Start

1. Register the Plugin
package main

import (
    "github.com/nicolasbonnici/gorest"
    "github.com/nicolasbonnici/gorest/pluginloader"
    ai "github.com/nicolasbonnici/gorest-ai"
)

func init() {
    pluginloader.RegisterPluginFactory("ai", ai.NewPlugin)
}

func main() {
    cfg := gorest.Config{
        ConfigPath: ".",
    }
    gorest.Start(cfg)
}
2. Configure in gorest.yaml
database:
  url: "${DATABASE_URL}"

plugins:
  - name: ai
    enabled: true
    config:
      default_provider: "anthropic"
      enabled_providers:
        - anthropic
        - openai
        - gemini
        - mistral

      # API Keys
      anthropic_api_key: "${ANTHROPIC_API_KEY}"
      openai_api_key: "${OPENAI_API_KEY}"
      gemini_api_key: "${GEMINI_API_KEY}"
      mistral_api_key: "${MISTRAL_API_KEY}"

      # Features
      enable_cache: true
      cache_ttl: 3600
      enable_fallback: true
      enable_quota: true

      # Limits
      max_tokens: 4096
      default_temperature: 0.7
      rate_limit_per_min: 60
      request_timeout: 30
3. Use the API
curl -X POST http://localhost:8000/api/ai/chat \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "anthropic",
    "messages": [
      {"role": "user", "content": "Explain quantum computing"}
    ],
    "use_cache": true
  }'

Auto-Translation

The plugin can automatically translate content stored in gorest-translatable's translations table whenever a resource is created or updated. It is fully generic — no field configuration needed. Any JSON object stored in the content column is translated key-by-key.

Setup
  1. Implement LocaleProvider (or use TranslatableService which already implements it):
type LocaleProvider interface {
    DefaultLocale() string   // source locale
    TargetLocales() []string // locales to translate into
}
  1. In your application entry point, wire the translatable plugin as the locale provider:
func registerRoutes(..., pluginRegistry *plugin.PluginRegistry) {
    aiPlug, _ := pluginRegistry.Get("ai")
    translatablePlug, _ := pluginRegistry.Get("translatable")

    if ai, ok := aiPlug.(*aiplugin.Plugin); ok {
        if tr, ok := translatablePlug.(*translatableplugin.TranslatablePlugin); ok {
            ai.SetLocaleProvider(tr.GetService())
        }
    }
}
  1. Enable in gorest.yaml:
- name: ai
  config:
    auto_translate: true
    allowed_resource_types: [post]  # empty = all types
How it works
  • On POST /ai/translate/:resource/:resource_id: reads the source locale translation, batches all target locales into one AI call, writes results back to the translations table.
  • Hash-based deduplication: if the source content hasn't changed since the last translation, that locale is skipped (ai_translation_log table).
  • Falls back to per-locale calls if the batch response is missing locales.
  • TranslateAsync fires a goroutine — safe to call from hooks.
HTTP Endpoint
POST /ai/translate/:resource/:resource_id

Response:

{
  "translated": ["fr", "es", "de"],
  "skipped":    ["it"],
  "failed":     []
}

API Endpoints

Chat Endpoints
POST /api/ai/chat

Send a chat completion request.

Request:

{
  "provider": "anthropic",
  "model": "claude-3-5-sonnet-20241022",
  "messages": [
    {"role": "system", "content": "You are a helpful assistant"},
    {"role": "user", "content": "Hello, how are you?"}
  ],
  "temperature": 0.7,
  "max_tokens": 1000,
  "use_cache": true
}

Response:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "provider": "anthropic",
  "model": "claude-3-5-sonnet-20241022",
  "content": "Hello! I'm doing well, thank you...",
  "prompt_tokens": 15,
  "completion_tokens": 42,
  "total_tokens": 57,
  "cost": 0.000171,
  "duration_ms": 1234,
  "cached": false,
  "created_at": "2024-01-15T10:30:00Z"
}
POST /api/ai/chat/stream

Send a streaming chat request (SSE).

Provider Management (Admin)
POST /api/ai/providers

Create a provider configuration.

GET /api/ai/providers/:id

Get provider by ID.

GET /api/ai/providers

List all providers with pagination.

PUT /api/ai/providers/:id

Update provider configuration.

DELETE /api/ai/providers/:id

Delete provider.

Usage & Statistics
GET /api/ai/usage

Get usage statistics.

Response:

{
  "total_requests": 1000,
  "successful_requests": 980,
  "failed_requests": 20,
  "cached_requests": 100,
  "total_tokens": 50000,
  "total_cost": 150.50,
  "average_duration_ms": 1500,
  "provider_breakdown": {
    "anthropic": {
      "requests": 500,
      "tokens": 25000,
      "cost": 75.00
    }
  }
}
GET /api/ai/usage/quota

Get user quota status.

Request History
GET /api/ai/requests

List request history with filtering.

GET /api/ai/requests/:id

Get request details.

Configuration

Provider Configuration
Option Type Default Description
default_provider string "anthropic" Default AI provider
enabled_providers []string ["anthropic", "openai", "gemini", "mistral"] List of enabled providers
anthropic_api_key string - Anthropic API key
openai_api_key string - OpenAI API key
gemini_api_key string - Google Gemini API key
mistral_api_key string - Mistral AI API key
Feature Configuration
Option Type Default Description
enable_cache bool true Enable response caching
cache_ttl int 3600 Cache TTL in seconds
enable_fallback bool true Enable provider fallback
enable_quota bool true Enable quota management
Limit Configuration
Option Type Default Description
max_tokens int 4096 Maximum tokens per request
default_temperature float64 0.7 Default temperature (0-2)
rate_limit_per_min int 60 Requests per minute
request_timeout int 30 Request timeout in seconds
Security Configuration
Option Type Default Description
require_auth bool true Require authentication
allow_anonymous bool false Allow anonymous requests
Audit Configuration
Option Type Default Description
enable_audit bool true Enable audit logging
retain_audit_days int 90 Audit retention period

Advanced Usage

Custom Provider Configuration

Create a custom provider configuration via API:

curl -X POST http://localhost:8000/api/ai/providers \
  -H "Content-Type: application/json" \
  -d '{
    "name": "openai",
    "display_name": "OpenAI Custom",
    "api_key": "sk-...",
    "enabled": true,
    "priority": 1,
    "max_tokens": 4096,
    "temperature": 0.8,
    "rate_limit": 100
  }'
Provider Fallback

If enable_fallback is true and the primary provider fails, requests automatically failover to the next available provider based on priority.

Caching

Caching uses SHA256 hashing of the request parameters:

  • Provider
  • Model
  • Messages
  • Temperature
  • Max tokens

Identical requests return cached responses instantly.

Quota Management

Configure per-user quotas:

  • Daily request limit
  • Monthly request limit
  • Daily token limit
  • Monthly token limit

Quotas automatically reset at configured intervals.

Cost Tracking

Token-based cost calculation with per-provider pricing:

  • Anthropic: ~$3 per million tokens
  • OpenAI: ~$30 per million tokens (GPT-4)
  • Gemini: ~$1 per million tokens
  • Mistral: ~$2 per million tokens

Database Schema

The plugin creates four tables:

ai_providers

Stores AI provider configurations with encrypted API keys.

ai_requests

Audit trail of all AI requests with token usage and costs.

ai_cache

Cache responses with TTL and hit count tracking.

ai_quotas

User-level quota tracking with daily/monthly limits.

Architecture

Provider Interface

All providers implement a common interface:

type Provider interface {
    Name() string
    Chat(ctx context.Context, req *ChatRequest) (*ChatResponse, error)
    ChatStream(ctx context.Context, req *ChatRequest) (<-chan StreamChunk, <-chan error)
    CountTokens(ctx context.Context, messages []Message) (int, error)
    ValidateConfig() error
    HealthCheck(ctx context.Context) error
}
Service Layer

The service layer handles:

  • Cache checking and storage
  • Provider selection and fallback
  • Quota enforcement
  • Cost calculation
  • Audit logging
Middleware

Two middleware components:

  • QuotaMiddleware - Enforces user quotas
  • AuditMiddleware - Logs all requests and responses

Production Deployment

1. Enable Authentication
plugins:
  - name: auth
    enabled: true

  - name: ai
    config:
      require_auth: true
      allow_anonymous: false
2. Configure Quotas
plugins:
  - name: ai
    config:
      enable_quota: true
3. Use Environment Variables
anthropic_api_key: "${ANTHROPIC_API_KEY}"
openai_api_key: "${OPENAI_API_KEY}"
4. Enable Audit Logging
plugins:
  - name: ai
    config:
      enable_audit: true
      retain_audit_days: 90
5. Use Production Database
database:
  url: "${DATABASE_URL}"

Testing

Unit Tests
go test ./...
Integration Tests
go test -tags=integration ./...
Load Testing
# Using hey
hey -n 1000 -c 10 -m POST -H "Content-Type: application/json" \
  -d '{"provider":"anthropic","messages":[{"role":"user","content":"Hi"}]}' \
  http://localhost:8000/api/ai/chat

Examples

See examples/basic/ for a complete working example.

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Write tests for new features
  4. Submit a pull request

License

MIT License - see LICENSE file for details.

Support

Roadmap

  • Core plugin implementation
  • Multiple provider support
  • Caching system
  • Quota management
  • Fallback mechanism
  • Cost tracking
  • Streaming support (in progress)
  • Advanced quota rules
  • Provider health monitoring
  • Webhook support
  • Function calling support
  • Vision API support
  • Embedding API support

Built using GoREST

Documentation ¶

Index ¶

Constants ¶

This section is empty.

Variables ¶

This section is empty.

Functions ¶

func NewPlugin ¶

func NewPlugin() plugin.Plugin

func UpdateProviderModel ¶

func UpdateProviderModel(provider *AIProvider, dto *ProviderUpdateDTO)

Types ¶

type AICache ¶

type AICache struct {
	ID               uuid.UUID  `db:"id" json:"id"`
	CacheKey         string     `db:"cache_key" json:"cache_key"`
	ProviderName     string     `db:"provider_name" json:"provider_name"`
	Model            string     `db:"model" json:"model"`
	RequestType      string     `db:"request_type" json:"request_type"`
	ResponseText     string     `db:"response_text" json:"response_text"`
	PromptTokens     int        `db:"prompt_tokens" json:"prompt_tokens"`
	CompletionTokens int        `db:"completion_tokens" json:"completion_tokens"`
	TotalTokens      int        `db:"total_tokens" json:"total_tokens"`
	HitCount         int        `db:"hit_count" json:"hit_count"`
	ExpiresAt        time.Time  `db:"expires_at" json:"expires_at"`
	CreatedAt        time.Time  `db:"created_at" json:"created_at"`
	UpdatedAt        *time.Time `db:"updated_at" json:"updated_at,omitempty"`
}

func (AICache) TableName ¶

func (AICache) TableName() string

type AIProvider ¶

type AIProvider struct {
	ID           uuid.UUID  `db:"id" json:"id"`
	Name         string     `db:"name" json:"name"`
	DisplayName  string     `db:"display_name" json:"display_name"`
	APIKey       string     `db:"api_key" json:"-"`
	BaseURL      *string    `db:"base_url" json:"base_url,omitempty"`
	Enabled      bool       `db:"enabled" json:"enabled"`
	Priority     int        `db:"priority" json:"priority"`
	MaxTokens    int        `db:"max_tokens" json:"max_tokens"`
	Temperature  float64    `db:"temperature" json:"temperature"`
	RateLimit    int        `db:"rate_limit" json:"rate_limit"`
	CostPerToken float64    `db:"cost_per_token" json:"cost_per_token"`
	CreatedAt    time.Time  `db:"created_at" json:"created_at"`
	UpdatedAt    *time.Time `db:"updated_at" json:"updated_at,omitempty"`
}

func ToProviderModel ¶

func ToProviderModel(dto *ProviderCreateDTO) *AIProvider

func (AIProvider) TableName ¶

func (AIProvider) TableName() string

type AIQuota ¶

type AIQuota struct {
	ID                uuid.UUID  `db:"id" json:"id"`
	UserID            uuid.UUID  `db:"user_id" json:"user_id"`
	DailyLimit        int        `db:"daily_limit" json:"daily_limit"`
	MonthlyLimit      int        `db:"monthly_limit" json:"monthly_limit"`
	DailyTokenLimit   int        `db:"daily_token_limit" json:"daily_token_limit"`
	MonthlyTokenLimit int        `db:"monthly_token_limit" json:"monthly_token_limit"`
	DailyUsed         int        `db:"daily_used" json:"daily_used"`
	MonthlyUsed       int        `db:"monthly_used" json:"monthly_used"`
	DailyTokensUsed   int        `db:"daily_tokens_used" json:"daily_tokens_used"`
	MonthlyTokensUsed int        `db:"monthly_tokens_used" json:"monthly_tokens_used"`
	ResetDaily        time.Time  `db:"reset_daily" json:"reset_daily"`
	ResetMonthly      time.Time  `db:"reset_monthly" json:"reset_monthly"`
	CreatedAt         time.Time  `db:"created_at" json:"created_at"`
	UpdatedAt         *time.Time `db:"updated_at" json:"updated_at,omitempty"`
}

func (*AIQuota) IsExceeded ¶

func (q *AIQuota) IsExceeded() bool

func (*AIQuota) NeedsReset ¶

func (q *AIQuota) NeedsReset() (daily, monthly bool)

func (*AIQuota) ResetDailyCounters ¶

func (q *AIQuota) ResetDailyCounters()

func (*AIQuota) ResetMonthlyCounters ¶

func (q *AIQuota) ResetMonthlyCounters()

func (AIQuota) TableName ¶

func (AIQuota) TableName() string

type AIRequest ¶

type AIRequest struct {
	ID               uuid.UUID  `db:"id" json:"id"`
	UserID           *uuid.UUID `db:"user_id" json:"user_id,omitempty"`
	ProviderID       uuid.UUID  `db:"provider_id" json:"provider_id"`
	ProviderName     string     `db:"provider_name" json:"provider_name"`
	Model            string     `db:"model" json:"model"`
	RequestType      string     `db:"request_type" json:"request_type"`
	Prompt           string     `db:"prompt" json:"prompt"`
	ResponseText     *string    `db:"response_text" json:"response_text,omitempty"`
	PromptTokens     int        `db:"prompt_tokens" json:"prompt_tokens"`
	CompletionTokens int        `db:"completion_tokens" json:"completion_tokens"`
	TotalTokens      int        `db:"total_tokens" json:"total_tokens"`
	Cost             float64    `db:"cost" json:"cost"`
	DurationMs       int        `db:"duration_ms" json:"duration_ms"`
	Status           string     `db:"status" json:"status"`
	ErrorMessage     *string    `db:"error_message" json:"error_message,omitempty"`
	Cached           bool       `db:"cached" json:"cached"`
	IPAddress        *string    `db:"ip_address" json:"ip_address,omitempty"`
	CreatedAt        time.Time  `db:"created_at" json:"created_at"`
}

func (AIRequest) TableName ¶

func (AIRequest) TableName() string

type AutoTranslator ¶ added in v0.2.1

type AutoTranslator struct {
	// contains filtered or unexported fields
}

func NewAutoTranslator ¶ added in v0.2.1

func NewAutoTranslator(service Chatter, db database.Database, localeProvider LocaleProvider, config *Config) *AutoTranslator

func (*AutoTranslator) Translate ¶ added in v0.2.1

func (t *AutoTranslator) Translate(ctx context.Context, resourceType, resourceID string, userID *uuid.UUID) (*TranslationResult, error)

func (*AutoTranslator) TranslateAsync ¶ added in v0.2.1

func (t *AutoTranslator) TranslateAsync(ctx context.Context, resourceType, resourceID string, userID *uuid.UUID)

type ChatMessage ¶

type ChatMessage struct {
	Role    string `json:"role" validate:"required,oneof=system user assistant"`
	Content string `json:"content" validate:"required"`
}

type ChatRequestDTO ¶

type ChatRequestDTO struct {
	Provider    string        `json:"provider" validate:"required,oneof=anthropic openai gemini mistral auto"`
	Model       *string       `json:"model,omitempty"`
	Messages    []ChatMessage `json:"messages" validate:"required,min=1,dive"`
	Temperature *float64      `json:"temperature,omitempty" validate:"omitempty,gte=0,lte=2"`
	MaxTokens   *int          `json:"max_tokens,omitempty" validate:"omitempty,gt=0"`
	Stream      bool          `json:"stream"`
	UseCache    bool          `json:"use_cache"`
}

type ChatResponseDTO ¶

type ChatResponseDTO struct {
	ID               uuid.UUID `json:"id"`
	Provider         string    `json:"provider"`
	Model            string    `json:"model"`
	Content          string    `json:"content"`
	PromptTokens     int       `json:"prompt_tokens"`
	CompletionTokens int       `json:"completion_tokens"`
	TotalTokens      int       `json:"total_tokens"`
	Cost             float64   `json:"cost"`
	DurationMs       int       `json:"duration_ms"`
	Cached           bool      `json:"cached"`
	CreatedAt        time.Time `json:"created_at"`
}

func ToChatResponseDTO ¶

func ToChatResponseDTO(request *AIRequest) *ChatResponseDTO

type Chatter ¶ added in v0.2.1

type Chatter interface {
	Chat(ctx context.Context, req *ChatRequestDTO, userID *uuid.UUID) (*ChatResponseDTO, error)
}

Chatter allows Chat calls to be mocked in tests.

type Config ¶

type Config struct {
	Database             database.Database `json:"-" yaml:"-"`
	DefaultProvider      string            `json:"default_provider" yaml:"default_provider"`
	EnabledProviders     []string          `json:"enabled_providers" yaml:"enabled_providers"`
	AnthropicAPIKey      string            `json:"anthropic_api_key" yaml:"anthropic_api_key"`
	AnthropicBaseURL     string            `json:"anthropic_base_url" yaml:"anthropic_base_url"`
	OpenAIAPIKey         string            `json:"openai_api_key" yaml:"openai_api_key"`
	OpenAIBaseURL        string            `json:"openai_base_url" yaml:"openai_base_url"`
	GeminiAPIKey         string            `json:"gemini_api_key" yaml:"gemini_api_key"`
	GeminiBaseURL        string            `json:"gemini_base_url" yaml:"gemini_base_url"`
	MistralAPIKey        string            `json:"mistral_api_key" yaml:"mistral_api_key"`
	MistralBaseURL       string            `json:"mistral_base_url" yaml:"mistral_base_url"`
	EnableCache          bool              `json:"enable_cache" yaml:"enable_cache"`
	CacheTTL             int               `json:"cache_ttl" yaml:"cache_ttl"`
	EnableFallback       bool              `json:"enable_fallback" yaml:"enable_fallback"`
	EnableQuota          bool              `json:"enable_quota" yaml:"enable_quota"`
	MaxTokens            int               `json:"max_tokens" yaml:"max_tokens"`
	DefaultTemperature   float64           `json:"default_temperature" yaml:"default_temperature"`
	RateLimitPerMin      int               `json:"rate_limit_per_min" yaml:"rate_limit_per_min"`
	RequestTimeout       int               `json:"request_timeout" yaml:"request_timeout"`
	PaginationLimit      int               `json:"pagination_limit" yaml:"pagination_limit"`
	MaxPaginationLimit   int               `json:"max_pagination_limit" yaml:"max_pagination_limit"`
	RequireAuth          bool              `json:"require_auth" yaml:"require_auth"`
	AllowAnonymous       bool              `json:"allow_anonymous" yaml:"allow_anonymous"`
	EnableAudit          bool              `json:"enable_audit" yaml:"enable_audit"`
	RetainAuditDays      int               `json:"retain_audit_days" yaml:"retain_audit_days"`
	AutoTranslate        bool              `json:"auto_translate" yaml:"auto_translate"`
	AllowedResourceTypes []string          `json:"allowed_resource_types" yaml:"allowed_resource_types"`
}

func DefaultConfig ¶

func DefaultConfig() Config

func (*Config) GetProviderAPIKey ¶

func (c *Config) GetProviderAPIKey(provider string) string

func (*Config) GetProviderBaseURL ¶

func (c *Config) GetProviderBaseURL(provider string) string

func (*Config) IsProviderEnabled ¶

func (c *Config) IsProviderEnabled(provider string) bool

func (*Config) Validate ¶

func (c *Config) Validate() error

type ErrorResponseDTO ¶

type ErrorResponseDTO struct {
	Error   string      `json:"error"`
	Message string      `json:"message"`
	Details interface{} `json:"details,omitempty"`
}

type LocaleProvider ¶ added in v0.2.1

type LocaleProvider interface {
	DefaultLocale() string
	TargetLocales() []string
}

type PaginatedResponseDTO ¶

type PaginatedResponseDTO struct {
	Data    interface{} `json:"data"`
	Total   int         `json:"total"`
	Limit   int         `json:"limit"`
	Offset  int         `json:"offset"`
	HasMore bool        `json:"has_more"`
}

type Plugin ¶

type Plugin struct {
	// contains filtered or unexported fields
}

func (*Plugin) GetAutoTranslator ¶ added in v0.2.1

func (p *Plugin) GetAutoTranslator() *AutoTranslator

func (*Plugin) GetRegistry ¶

func (p *Plugin) GetRegistry() *providers.ProviderRegistry

func (*Plugin) GetService ¶

func (p *Plugin) GetService() *Service

func (*Plugin) Handler ¶

func (p *Plugin) Handler() fiber.Handler

func (*Plugin) Initialize ¶

func (p *Plugin) Initialize(config map[string]interface{}) error

func (*Plugin) MigrationDependencies ¶ added in v0.1.1

func (p *Plugin) MigrationDependencies() []string

func (*Plugin) MigrationSource ¶ added in v0.1.1

func (p *Plugin) MigrationSource() any

func (*Plugin) Name ¶

func (p *Plugin) Name() string

func (*Plugin) SetLocaleProvider ¶ added in v0.2.1

func (p *Plugin) SetLocaleProvider(lp LocaleProvider)

func (*Plugin) SetupEndpoints ¶

func (p *Plugin) SetupEndpoints(app *fiber.App) error

type ProviderCreateDTO ¶

type ProviderCreateDTO struct {
	Name        string  `json:"name" validate:"required,oneof=anthropic openai gemini mistral"`
	DisplayName string  `json:"display_name" validate:"required"`
	APIKey      string  `json:"api_key" validate:"required"`
	BaseURL     *string `json:"base_url,omitempty" validate:"omitempty,url"`
	Enabled     bool    `json:"enabled"`
	Priority    int     `json:"priority" validate:"gte=0"`
	MaxTokens   int     `json:"max_tokens" validate:"required,gt=0"`
	Temperature float64 `json:"temperature" validate:"required,gte=0,lte=2"`
	RateLimit   int     `json:"rate_limit" validate:"gte=0"`
}

type ProviderResponseDTO ¶

type ProviderResponseDTO struct {
	ID          uuid.UUID  `json:"id"`
	Name        string     `json:"name"`
	DisplayName string     `json:"display_name"`
	BaseURL     *string    `json:"base_url,omitempty"`
	Enabled     bool       `json:"enabled"`
	Priority    int        `json:"priority"`
	MaxTokens   int        `json:"max_tokens"`
	Temperature float64    `json:"temperature"`
	RateLimit   int        `json:"rate_limit"`
	HasAPIKey   bool       `json:"has_api_key"`
	CreatedAt   time.Time  `json:"created_at"`
	UpdatedAt   *time.Time `json:"updated_at,omitempty"`
}

func ToProviderResponseDTO ¶

func ToProviderResponseDTO(provider *AIProvider) *ProviderResponseDTO

type ProviderUpdateDTO ¶

type ProviderUpdateDTO struct {
	DisplayName *string  `json:"display_name,omitempty"`
	APIKey      *string  `json:"api_key,omitempty"`
	BaseURL     *string  `json:"base_url,omitempty" validate:"omitempty,url"`
	Enabled     *bool    `json:"enabled,omitempty"`
	Priority    *int     `json:"priority,omitempty" validate:"omitempty,gte=0"`
	MaxTokens   *int     `json:"max_tokens,omitempty" validate:"omitempty,gt=0"`
	Temperature *float64 `json:"temperature,omitempty" validate:"omitempty,gte=0,lte=2"`
	RateLimit   *int     `json:"rate_limit,omitempty" validate:"omitempty,gte=0"`
}

type ProviderUsageDTO ¶

type ProviderUsageDTO struct {
	Provider    string  `json:"provider"`
	Requests    int     `json:"requests"`
	Tokens      int     `json:"tokens"`
	Cost        float64 `json:"cost"`
	AvgDuration int     `json:"avg_duration_ms"`
}

type QuotaStatusDTO ¶

type QuotaStatusDTO struct {
	DailyLimit             int       `json:"daily_limit"`
	MonthlyLimit           int       `json:"monthly_limit"`
	DailyTokenLimit        int       `json:"daily_token_limit"`
	MonthlyTokenLimit      int       `json:"monthly_token_limit"`
	DailyUsed              int       `json:"daily_used"`
	MonthlyUsed            int       `json:"monthly_used"`
	DailyTokensUsed        int       `json:"daily_tokens_used"`
	MonthlyTokensUsed      int       `json:"monthly_tokens_used"`
	DailyRemaining         int       `json:"daily_remaining"`
	MonthlyRemaining       int       `json:"monthly_remaining"`
	DailyTokensRemaining   int       `json:"daily_tokens_remaining"`
	MonthlyTokensRemaining int       `json:"monthly_tokens_remaining"`
	ResetDaily             time.Time `json:"reset_daily"`
	ResetMonthly           time.Time `json:"reset_monthly"`
}

func ToQuotaStatusDTO ¶

func ToQuotaStatusDTO(quota *AIQuota) *QuotaStatusDTO

type RequestFilterDTO ¶

type RequestFilterDTO struct {
	UserID   *uuid.UUID `json:"user_id,omitempty"`
	Provider *string    `json:"provider,omitempty"`
	Status   *string    `json:"status,omitempty" validate:"omitempty,oneof=success error cached"`
	FromDate *time.Time `json:"from_date,omitempty"`
	ToDate   *time.Time `json:"to_date,omitempty"`
	Limit    int        `json:"limit" validate:"omitempty,gt=0,lte=100"`
	Offset   int        `json:"offset" validate:"omitempty,gte=0"`
}

type RequestResponseDTO ¶

type RequestResponseDTO struct {
	ID               uuid.UUID  `json:"id"`
	UserID           *uuid.UUID `json:"user_id,omitempty"`
	Provider         string     `json:"provider"`
	Model            string     `json:"model"`
	Prompt           string     `json:"prompt"`
	PromptTokens     int        `json:"prompt_tokens"`
	CompletionTokens int        `json:"completion_tokens"`
	TotalTokens      int        `json:"total_tokens"`
	Cost             float64    `json:"cost"`
	DurationMs       int        `json:"duration_ms"`
	Status           string     `json:"status"`
	Cached           bool       `json:"cached"`
	CreatedAt        time.Time  `json:"created_at"`
}

func ToRequestResponseDTO ¶

func ToRequestResponseDTO(request *AIRequest) *RequestResponseDTO

type Service ¶

type Service struct {
	// contains filtered or unexported fields
}

func NewService ¶

func NewService(config *Config, registry *providers.ProviderRegistry, db database.Database) *Service

func (*Service) Chat ¶

func (s *Service) Chat(ctx context.Context, req *ChatRequestDTO, userID *uuid.UUID) (*ChatResponseDTO, error)

func (*Service) CheckQuota ¶

func (s *Service) CheckQuota(ctx context.Context, userID uuid.UUID) (bool, error)

type TranslationResult ¶ added in v0.2.1

type TranslationResult struct {
	Translated []string `json:"translated"`
	Skipped    []string `json:"skipped"`
	Failed     []string `json:"failed"`
}

type UsageStatsDTO ¶

type UsageStatsDTO struct {
	TotalRequests      int                         `json:"total_requests"`
	SuccessfulRequests int                         `json:"successful_requests"`
	FailedRequests     int                         `json:"failed_requests"`
	CachedRequests     int                         `json:"cached_requests"`
	TotalTokens        int                         `json:"total_tokens"`
	PromptTokens       int                         `json:"prompt_tokens"`
	CompletionTokens   int                         `json:"completion_tokens"`
	TotalCost          float64                     `json:"total_cost"`
	AverageDuration    int                         `json:"average_duration_ms"`
	ProviderBreakdown  map[string]ProviderUsageDTO `json:"provider_breakdown"`
}

Directories ¶

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL