Skip to content

Core Module

The pkg/core module is the cornerstone of the entire GoChat project. Its design purpose is to define a set of domain models and core interfaces completely decoupled from specific LLM vendors. Through this standardized abstraction, upper-layer business logic can seamlessly switch between different underlying model engines (such as from OpenAI to Anthropic or local Ollama) without code modifications.

Architecture

classDiagram
    direction TB

    class Client {
        <>
        +Chat(ctx, messages, opts) Response
        +ChatStream(ctx, messages, opts) Stream
    }

    class Message {
        +Role string
        +Content []ContentBlock
        +ToolCalls []ToolCall
        +TextContent() string
    }

    class ContentBlock {
        +Type ContentType
        +Text string
        +MediaType string
        +Data string
    }

    class Response {
        +ID string
        +Model string
        +Content string
        +ReasoningContent string
        +Message Message
        +FinishReason string
        +Usage Usage
    }

    class Stream {
        +Next() bool
        +Event() StreamEvent
        +Close() error
        +Usage() Usage
        +Text() string
    }

    class Option {
        <>
    }

    class AuthManager {
        +Login() error
        +GetToken() OAuthToken
    }

    Client ..> Message : depends on
    Client ..> Option : depends on
    Client ..> Response : returns
    Client ..> Stream : returns
    Message *-- ContentBlock

Interfaces

Client Interface

All vendor-specific clients (such as openai.Client, anthropic.Client) implement this interface.

  • Chat: Executes a blocking chat request, returning the complete response at once.
  • ChatStream: Initiates a streaming request, returning a Stream iterator object.

Message and ContentBlock

Message carriers based on multimodal design.

  • Message: Defines the role (user, assistant, system, tool) and its content.
  • ContentBlock: The smallest unit composing a message, distinguished by ContentType as plain text (text), image data (image), or deep thinking content (thinking).

Functional Options Pattern

All configuration adjustments (such as specifying Temperature, MaxTokens, mounting Tools, etc.) are implemented through core.Option closure functions. This ensures the extreme simplicity of the Client interface while granting it unlimited expansion capability.

Detailed Usage Examples

package main

import (
    "context"
    "fmt"
    "github.com/DotNetAge/gochat/pkg/core"
)

// Assume we have an instantiated client (implementing core.Client)
func interactWithModel(client core.Client) {
    // 1. Build multimodal/plain messages
    msg := core.NewUserMessage("Please analyze the current situation.")

    // 2. Use Option to pass complex execution parameters
    opts := []core.Option{
        core.WithTemperature(0.5),
        core.WithMaxTokens(2000),
        core.WithThinking(1024), // Enable o1/DeepSeek's deep thinking mode
        core.WithSystemPrompt("You are an objective analyst"),
    }

    // 3. Call core interface
    resp, err := client.Chat(context.Background(), []core.Message{msg}, opts...)
    if err != nil {
        panic(err)
    }

    fmt.Println("Response:", resp.Content)
    fmt.Printf("Tokens consumed: %d\n", resp.Usage.TotalTokens)
}

Implementation Principles and Design Advantages

  1. Structured Network Errors and Exponential Backoff: In errors.go and retry.go, standard ErrorType is defined. Combined with ExponentialBackoff, built-in resilient fault tolerance is implemented, so that occasional network jitter does not directly cause process crashes.
  2. Future-Proof Multimodal and Tool Calling: Abandoning simple string transmission, structured Message trees enable seamless integration of tool calling (Function Calling).
  3. Safe Stream Iteration (Stream Iterator): Encapsulating Go channels, exposing the Next() and Event() iterator pattern, preventing deadlocks and goroutine leaks that developers might encounter when handling channel.