A universal Go library for building LLM applications with support for multiple providers, tools, chains, and streaming.
- Multi-Provider Support: Unified interface for OpenAI, Anthropic, and other LLM providers
- Tool/Function Calling: Built-in support for tool execution and management
- Streaming: Full support for streaming responses with event-based processing
- Chain Architecture: Composable chain-based processing pipeline for complex workflows
- Tool Chains: Automatic tool calling and result collection with configurable rounds
- Metrics: Built-in metrics collection for monitoring API calls and performance
- Type-Safe: Strongly typed Go interfaces and implementations
- Embeddings: Multi-provider text embedding (OpenAI, Ollama, Nvidia, DashScope, Local)
- Full-Text Search: Bleve-powered search with facets, highlighting, and suggestions
- Document Retrieval: Multi-strategy retrieval (vector, keyword, hybrid) with reranking
- Chunking: Intelligent document chunking with multiple strategies
- Knowledge Base: Integrated knowledge management with vector databases (Qdrant, Milvus)
go get github.com/LingByte/lingllmpackage main
import (
"context"
"fmt"
"github.com/LingByte/lingllm/protocol"
)
func main() {
// Create a chat request
req := protocol.NewChatRequest(
"gpt-4",
protocol.UserMessage("What is the capital of France?"),
)
// Call your model implementation
// resp, err := model.Chat(context.Background(), *req)
// if err != nil {
// panic(err)
// }
// fmt.Println(resp.FirstContent())
}package main
import (
"context"
"encoding/json"
"fmt"
"github.com/LingByte/lingllm/protocol"
"github.com/LingByte/lingllm/tools"
)
func main() {
// Create a tool executor
executor := tools.NewSimpleToolExecutor()
// Register a tool
weatherTool := tools.WeatherTool()
executor.RegisterTool(weatherTool, func(args json.RawMessage) (string, error) {
// Implement weather lookup
return "Sunny, 72°F", nil
})
// Create a tool chain
toolChain := tools.NewToolChain(model, executor)
toolChain.WithMaxRounds(5)
// Execute with tools
req := protocol.NewChatRequest(
"gpt-4",
protocol.UserMessage("What's the weather in San Francisco?"),
)
resp, err := toolChain.ExecuteWithTools(context.Background(), *req)
if err != nil {
panic(err)
}
fmt.Println(resp.FirstContent())
}package main
import (
"context"
"fmt"
"io"
"github.com/LingByte/lingllm/protocol"
)
func main() {
req := protocol.NewChatRequest(
"gpt-4",
protocol.UserMessage("Write a poem about Go programming"),
)
stream, err := model.StreamChat(context.Background(), *req)
if err != nil {
panic(err)
}
defer stream.Close()
for {
chunk, err := stream.Recv()
if err == io.EOF {
break
}
if err != nil {
panic(err)
}
fmt.Print(chunk.Delta)
}
}package main
import (
"context"
"github.com/LingByte/lingllm/chain"
"github.com/LingByte/lingllm/protocol"
)
func main() {
// Build a chain with multiple models/processors
c := chain.NewBuilder("my-chain").
AddModel("model1", model1).
AddProcessor("processor1", func(ctx context.Context, resp *protocol.ChatResponse) (*protocol.ChatResponse, error) {
// Process response
return resp, nil
}).
AddModel("model2", model2).
Build()
req := protocol.NewChatRequest(
"gpt-4",
protocol.UserMessage("Hello"),
)
resp, err := c.Invoke(context.Background(), *req)
if err != nil {
panic(err)
}
println(resp.FirstContent())
}package main
import (
"context"
"github.com/LingByte/lingllm/embedder"
)
func main() {
// Create embedder with OpenAI
cfg := &embedder.Config{
Provider: "openai",
Model: "text-embedding-3-small",
APIKey: os.Getenv("OPENAI_API_KEY"),
}
emb, err := embedder.Create(context.Background(), cfg)
if err != nil {
panic(err)
}
defer emb.Close()
// Single embedding
vec, err := emb.EmbedSingle(context.Background(), "Hello world")
if err != nil {
panic(err)
}
fmt.Printf("Vector dimension: %d\n", len(vec))
// Batch embedding
vecs, err := emb.Embed(context.Background(), []string{
"Hello world",
"Goodbye world",
})
if err != nil {
panic(err)
}
fmt.Printf("Embedded %d texts\n", len(vecs))
}package main
import (
"context"
"github.com/LingByte/lingllm/search"
)
func main() {
// Create search engine
cfg := search.Config{
IndexPath: "./search_index",
DefaultAnalyzer: "standard",
DefaultSearchFields: []string{"title", "body"},
}
m := search.BuildIndexMapping("standard")
engine, err := search.New(cfg, m)
if err != nil {
panic(err)
}
defer engine.Close()
// Index documents
docs := []search.Doc{
{
ID: "1",
Type: "article",
Fields: map[string]interface{}{
"title": "Go Programming",
"body": "Go is a fast and efficient language",
},
},
}
engine.IndexBatch(context.Background(), docs)
// Search
result, err := engine.Search(context.Background(), search.SearchRequest{
Keyword: "Go",
Size: 10,
})
if err != nil {
panic(err)
}
fmt.Printf("Found %d results\n", result.Total)
for _, hit := range result.Hits {
fmt.Printf("- %s (score: %.2f)\n", hit.Fields["title"], hit.Score)
}
}package main
import (
"context"
"github.com/LingByte/lingllm/retrieve"
)
func main() {
// Create hybrid retriever
retriever, err := retrieve.New(retrieve.Config{
Strategy: retrieve.StrategyHybrid,
Vector: vectorStore,
Search: searchEngine,
TopK: 10,
VectorWeight: 0.65,
})
if err != nil {
panic(err)
}
// Retrieve documents
docs, err := retriever.Retrieve(context.Background(), "machine learning", 10)
if err != nil {
panic(err)
}
for i, doc := range docs {
fmt.Printf("%d. %s (score: %.2f)\n", i+1, doc.Content, doc.Score)
}
}package main
import (
"context"
"github.com/LingByte/lingllm/knowledge"
"github.com/LingByte/lingllm/embedder"
"github.com/LingByte/lingllm/search"
)
func main() {
// Create embedder
emb, _ := embedder.Create(context.Background(), &embedder.Config{
Provider: "openai",
Model: "text-embedding-3-small",
APIKey: os.Getenv("OPENAI_API_KEY"),
})
// Create search engine
searchCfg := search.Config{
IndexPath: "./search_index",
DefaultSearchFields: []string{"title", "content"},
}
m := search.BuildIndexMapping("standard")
searcher, _ := search.New(searchCfg, m)
// Create vector database handler
handler, _ := knowledge.NewKnowledgeHandler(knowledge.HandlerFactoryParams{
Provider: knowledge.ProviderQdrant,
QdrantConfig: &knowledge.QdrantConfig{
BaseURL: "http://localhost:6333",
APIKey: "your-api-key",
},
})
// Create knowledge base
kb, _ := knowledge.NewKnowledgeBase(knowledge.KnowledgeBaseConfig{
Handler: handler,
Embedder: emb,
Searcher: searcher,
})
defer kb.Close()
// Add document
kb.AddDocument(context.Background(), "doc1", "Title", "Content...", nil)
// Query
results, _ := kb.Query(context.Background(), "search query", 10)
for _, result := range results {
fmt.Printf("%s (score: %.2f)\n", result.Record.Title, result.Score)
}
}lingllm/
├── protocol/ # Core protocol definitions and interfaces
│ ├── types.go # ChatRequest, ChatResponse, Message, Tool definitions
│ ├── factory.go # Provider factory for creating clients
│ ├── stream.go # Streaming utilities and transformers
│ └── ...
├── tools/ # Tool execution and management
│ ├── tools.go # Tool definitions, executors, and chains
│ └── ...
├── chain/ # Chain-based processing pipeline
│ ├── chain.go # Chain composition and execution
│ └── ...
├── metrics/ # Metrics collection
│ └── metrics.go # Call metrics and monitoring
├── embedder/ # Text embedding providers
│ ├── types.go # Core types and interfaces
│ ├── local.go # Local MD5-based embedder
│ ├── openai.go # OpenAI embeddings
│ ├── ollama.go # Ollama local embeddings
│ ├── nvidia.go # Nvidia enterprise embeddings
│ ├── dashscope.go # Alibaba DashScope embeddings
│ ├── factory.go # Embedder factory pattern
│ └── *_test.go # Comprehensive tests (80%+ coverage)
├── search/ # Full-text search engine
│ ├── types.go # Search types and interfaces
│ ├── engine.go # Bleve-based search engine
│ ├── mapping.go # Index mapping configuration
│ ├── query_builder.go # Query construction
│ └── *_test.go # Tests (96.1% coverage)
├── retrieve/ # Multi-strategy document retrieval
│ ├── types.go # Retrieval types
│ ├── config.go # Configuration and factory
│ ├── retriever.go # Retrieval logic
│ └── *_test.go # Tests (80.6% coverage)
├── chunk/ # Document chunking strategies
│ └── ...
├── knowledge/ # Knowledge base management
│ ├── types.go # Core types and interfaces
│ ├── integration.go # KnowledgeBase integration
│ ├── qdrant.go # Qdrant vector database handler
│ ├── milvus.go # Milvus vector database handler
│ ├── embedding.go # Embedding client (Nvidia)
│ ├── doc_type_detector.go # Document type detection
│ ├── README.md # Knowledge base documentation
│ └── *_test.go # Tests (40+ tests)
├── utils/ # Shared utilities
│ ├── clean.go # Text cleaning utilities
│ └── *_test.go # Tests
├── shared/ # Shared utilities
├── examples/ # Example implementations
│ ├── embedder-demo/ # Multi-provider embedding demo
│ ├── search-demo/ # Full-text search demo
│ └── ...
└── go.mod
The protocol package defines the core interfaces and types:
- ChatModel: Interface for language models
- ChatRequest: Unified request format
- ChatResponse: Normalized response format
- ChatStream: Streaming interface
- Tool: Tool/function definitions
The tools package provides:
- ToolExecutor: Interface for executing tools
- SimpleToolExecutor: Basic implementation using function maps
- ToolChain: Automatic tool calling with conversation management
- ToolCallParser: Parse tool calls from model responses (ReAct, JSON formats)
The chain package enables:
- Chain: Sequential composition of nodes
- Node: Composable units (models, processors, stream processors)
- Builder: Fluent API for building chains
- ProcessingStream: Stream transformation pipeline
The metrics package tracks:
- API call latency
- Token usage
- Error rates
- Provider-specific metrics
The embedder package provides multi-provider text embeddings:
- OpenAI: High-quality embeddings (1536 dimensions)
- Ollama: Local deployment support (384 dimensions)
- Nvidia: Enterprise-grade embeddings (1024+ dimensions)
- DashScope: Alibaba's native API (64-2048 dimensions)
- Local: MD5-based deterministic embeddings (384 dimensions)
Features:
- Unified interface across providers
- Batch processing support
- Configurable dimensions
- Vector normalization
- Factory pattern for easy provider switching
The search package provides full-text search powered by Bleve:
- Full-Text Search: Keyword and phrase matching
- Advanced Queries: Match, phrase, prefix, wildcard, regex, fuzzy
- Faceted Search: Category aggregation and counting
- Highlighting: Query term highlighting with HTML formatting
- Suggestions: Autocomplete and search suggestions
- Pagination: Offset-based result pagination
- Sorting: Multi-field sorting support
The retrieve package implements multi-strategy document retrieval:
- Vector Strategy: Dense vector similarity search
- Keyword Strategy: Full-text search
- Hybrid Strategy: Combines vector and keyword with configurable weights
- Reranking: Optional document re-scoring
- Min Score Filtering: Quality control for results
The knowledge package provides integrated knowledge management:
- Multi-Backend Support: Qdrant and Milvus vector databases
- Intelligent Chunking: Automatic document type detection and optimal chunking
- Semantic Search: Vector-based similarity with embeddings
- Full-Text Search: Keyword-based search integration
- Hybrid Retrieval: Combine vector and keyword search
- Document Management: Add, query, delete, and list documents
- Metadata Support: Flexible metadata storage and filtering
- Document Type Detection: Structured, Table/KV, Unstructured
Features:
- Automatic document chunking based on type
- Embedding generation for semantic search
- Integration with search engines
- Multi-tenancy with namespaces
- Health checks and monitoring
The library provides a unified interface for:
- OpenAI (GPT-4, GPT-3.5, etc.)
- Anthropic (Claude)
- Local models (via compatible APIs)
- Custom implementations
// Create messages
msg := protocol.UserMessage("Hello")
msg := protocol.SystemMessage("You are a helpful assistant")
msg := protocol.AssistantMessage("Hi there!")
msg := protocol.ToolMessage("Result", "tool_call_id")
// Build requests
req := protocol.NewChatRequest("gpt-4", msg1, msg2, msg3)
req.WithMaxTokens(1000).
WithTemperature(0.7).
WithTopP(0.9).
WithStop("END")resp, err := model.Chat(ctx, req)
if err != nil {
// Handle error
fmt.Printf("Error: %v\n", err)
}Configure clients using provider-specific implementations:
// Example with environment variables
apiKey := os.Getenv("OPENAI_API_KEY")
// Create your provider-specific clientRun tests:
go test ./...Run tests with coverage:
go test -cover ./...Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Submit a pull request
MIT License - see LICENSE file for details
-
Embedder Module (80%+ coverage)
- 5 providers: OpenAI, Ollama, Nvidia, DashScope, Local
- Batch processing, vector normalization
- Comprehensive tests and demo
-
Search Module (96.1% coverage)
- Bleve-powered full-text search
- Advanced query types
- Facets, highlighting, suggestions
- 60+ tests
-
Retrieve Module (80.6% coverage)
- 3 strategies: Vector, Keyword, Hybrid
- Reranking support
- 26 tests
-
Knowledge Base Module (40+ tests)
- Multi-backend support (Qdrant, Milvus)
- Intelligent document chunking
- Semantic and keyword search
- Document type detection
- Metadata support
- Health checks
-
Chunk Module
- Multiple chunking strategies
- Configurable chunk sizes
- Overlap support
- Official OpenAI provider implementation
- Official Anthropic provider implementation
- MCP (Model Context Protocol) integration
- Caching layer for responses and embeddings
- Advanced prompt engineering utilities
- Evaluation framework
- More tool examples and templates
- Vector database integration (Qdrant, Milvus)
- Knowledge base management utilities
- RAG (Retrieval-Augmented Generation) pipeline
For issues, questions, or suggestions, please open an issue on GitHub.