LingLLM
A universal Go library for building LLM applications with support for multiple providers, tools, chains, and streaming.
Features
- 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)
Installation
go get github.com/LingByte/lingllm
Quick Start
Basic Chat
package 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())
}
Streaming
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)
}
}
Chains
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())
}
Embeddings
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))
}
Full-Text Search
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)
}
}
Document Retrieval
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)
}
}
Knowledge Base
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)
}
}
Project Structure
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
Core Concepts
Protocol
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)
Chains
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
Metrics
The metrics package tracks:
- API call latency
- Token usage
- Error rates
- Provider-specific metrics
Embeddings
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
Search
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
Retrieval
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
Knowledge Base
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
Supported Providers
The library provides a unified interface for:
- OpenAI (GPT-4, GPT-3.5, etc.)
- Anthropic (Claude)
- Local models (via compatible APIs)
- Custom implementations
Message Types
// 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")
Error Handling
resp, err := model.Chat(ctx, req)
if err != nil {
// Handle error
fmt.Printf("Error: %v\n", err)
}
Configuration
Configure clients using provider-specific implementations:
// Example with environment variables
apiKey := os.Getenv("OPENAI_API_KEY")
// Create your provider-specific client
Testing
Run tests:
go test ./...
Run tests with coverage:
go test -cover ./...
Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Submit a pull request
License
MIT License - see LICENSE file for details
Modules Status
β
Completed
-
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
π Roadmap
- 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
Support
For issues, questions, or suggestions, please open an issue on GitHub.