mirror of
https://github.com/vxcontrol/langchaingo.git
synced 2026-08-25 11:10:02 -04:00
268 lines
10 KiB
Go
268 lines
10 KiB
Go
// Package lint provides architectural linting for the LangChain Go codebase.
|
|
//
|
|
// This linter enforces architectural patterns and best practices specific to
|
|
// building robust, maintainable Go libraries, with special focus on AI/ML
|
|
// service integration patterns common in LangChain Go.
|
|
//
|
|
// # Implemented Rules
|
|
//
|
|
// The following architectural rules are currently implemented:
|
|
//
|
|
// - HTTP Client Usage: Enforce httputil.DefaultClient over http.DefaultClient
|
|
// - Provider Isolation: Prevent cross-provider dependencies
|
|
// - Options Pattern: Ensure constructors use functional options
|
|
// - Test HTTP Usage: Enforce httprr usage in tests for deterministic HTTP behavior
|
|
// - Internal Package Access: Validate internal package import rules
|
|
//
|
|
// # TODO: Additional Architectural Patterns to Implement
|
|
//
|
|
// ## High Priority - Core Go Library Design Patterns
|
|
//
|
|
// TODO: Context Propagation Rule
|
|
// All public functions that make network calls, file I/O, or could be long-running
|
|
// should accept context.Context as the first parameter. This enables cancellation,
|
|
// timeouts, and request tracing.
|
|
//
|
|
// ❌ func (llm *OpenAI) Generate(prompt string) (string, error)
|
|
// ✅ func (llm *OpenAI) Generate(ctx context.Context, prompt string) (string, error)
|
|
//
|
|
// TODO: Error Wrapping Consistency
|
|
// All errors should be wrapped with context using fmt.Errorf with %w verb to
|
|
// maintain error chains and provide debugging context.
|
|
//
|
|
// ❌ return fmt.Errorf("failed to call API")
|
|
// ✅ return fmt.Errorf("failed to call OpenAI API: %w", err)
|
|
//
|
|
// TODO: Resource Cleanup Patterns
|
|
// Functions that acquire resources (connections, files, etc.) should either use
|
|
// defer for cleanup or return a cleanup function.
|
|
//
|
|
// ❌ func Connect() *Client
|
|
// ✅ func Connect() (*Client, func() error, error)
|
|
//
|
|
// TODO: Interface Segregation
|
|
// Interfaces should be small and focused (1-3 methods max). Large interfaces
|
|
// should be composed of smaller ones.
|
|
//
|
|
// ❌ type LLMProvider interface { Generate(...); Embed(...); Complete(...); Stream(...); Validate(...) }
|
|
// ✅ type Generator interface { Generate(...) }
|
|
// ✅ type Embedder interface { Embed(...) }
|
|
//
|
|
// TODO: Package Dependency Direction
|
|
// Core packages (chains, agents, memory) should not depend on specific provider
|
|
// implementations. Dependencies should flow from specific to general.
|
|
//
|
|
// ❌ import "github.com/vxcontrol/langchaingo/llms/openai" in chains package
|
|
// ✅ import "github.com/vxcontrol/langchaingo/llms" in chains package
|
|
//
|
|
// TODO: Global State Avoidance
|
|
// Avoid global mutable state. Prefer dependency injection and explicit configuration.
|
|
//
|
|
// ❌ var DefaultLLM = openai.New()
|
|
// ✅ func NewChain(llm llms.Model) *Chain
|
|
//
|
|
// TODO: Configuration Validation
|
|
// All configuration should be validated at creation time, not at usage time,
|
|
// to fail fast and provide clear error messages.
|
|
//
|
|
// ❌ Validate during Generate() call
|
|
// ✅ Validate during New() constructor
|
|
//
|
|
// ## Medium Priority - Performance & Reliability Patterns
|
|
//
|
|
// TODO: Streaming Interface Consistency
|
|
// Operations that return large datasets should offer streaming variants to
|
|
// handle memory-constrained environments.
|
|
//
|
|
// ✅ func (emb *Embedder) EmbedDocuments(ctx context.Context, docs []string) ([][]float32, error)
|
|
// ✅ func (emb *Embedder) EmbedDocumentsStream(ctx context.Context, docs []string) (<-chan EmbeddingResult, error)
|
|
//
|
|
// TODO: Memory Pool Usage
|
|
// Use sync.Pool for frequently allocated/deallocated objects to reduce GC pressure.
|
|
//
|
|
// ✅ var bufferPool = sync.Pool{New: func() interface{} { return &bytes.Buffer{} }}
|
|
//
|
|
// TODO: Rate Limiting Integration
|
|
// Network-bound operations should support rate limiting through context or options.
|
|
//
|
|
// ✅ func WithRateLimit(rps int) Option
|
|
// ✅ Check context.Context for rate limiting signals
|
|
//
|
|
// TODO: Timeout Patterns
|
|
// All network operations should have reasonable default timeouts and respect
|
|
// context deadlines.
|
|
//
|
|
// ✅ ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
|
|
//
|
|
// TODO: Retry Logic Consistency
|
|
// Implement consistent retry patterns with exponential backoff for transient failures.
|
|
//
|
|
// ✅ func WithRetryPolicy(maxRetries int, backoff BackoffStrategy) Option
|
|
//
|
|
// TODO: Circuit Breaker Pattern
|
|
// Protect against cascading failures in external service calls.
|
|
//
|
|
// ✅ Implement circuit breaker for provider failures
|
|
//
|
|
// ## AI/ML Domain-Specific Patterns
|
|
//
|
|
// TODO: Token Counting Consistency
|
|
// All LLM providers should implement consistent token counting for cost estimation
|
|
// and request validation.
|
|
//
|
|
// ✅ type TokenCounter interface { CountTokens(text string) int }
|
|
// ✅ All LLM providers implement TokenCounter
|
|
//
|
|
// TODO: Model Capability Abstraction
|
|
// Model-specific features should be behind feature interfaces rather than
|
|
// provider-specific methods.
|
|
//
|
|
// ✅ type ImageCapable interface { GenerateWithImages(...) }
|
|
// ✅ type FunctionCallCapable interface { CallFunction(...) }
|
|
//
|
|
// TODO: Prompt Template Safety
|
|
// Implement prompt injection protection and template validation.
|
|
//
|
|
// ✅ func ValidatePrompt(template string) error
|
|
// ✅ func SanitizeInput(userInput string) string
|
|
//
|
|
// TODO: Response Validation
|
|
// LLM responses should be validated for completeness and safety before returning.
|
|
//
|
|
// ✅ func ValidateResponse(response string) error
|
|
// ✅ Check for truncated responses, safety violations
|
|
//
|
|
// TODO: Embedding Dimension Consistency
|
|
// Embedding operations should validate and document vector dimensions.
|
|
//
|
|
// ✅ type EmbeddingModel interface { Dimensions() int }
|
|
// ✅ Validate dimension consistency across operations
|
|
//
|
|
// TODO: Chain Composability
|
|
// Chains should be composable and testable in isolation without external dependencies.
|
|
//
|
|
// ✅ type Chain interface { Run(ctx context.Context, input ChainInput) (ChainOutput, error) }
|
|
// ✅ Chains accept other chains as dependencies
|
|
//
|
|
// TODO: Agent State Immutability
|
|
// Agent state should be immutable or clearly documented as mutable with thread-safety guarantees.
|
|
//
|
|
// ✅ func (a *Agent) WithMemory(mem Memory) *Agent // returns new agent
|
|
// ❌ func (a *Agent) SetMemory(mem Memory) // mutates existing agent
|
|
//
|
|
// TODO: Memory Retention Policies
|
|
// Conversation memory should have clear retention and cleanup policies.
|
|
//
|
|
// ✅ type Memory interface { Prune(maxItems int) error }
|
|
// ✅ func WithRetentionPolicy(policy RetentionPolicy) Option
|
|
//
|
|
// TODO: Tool Input/Output Validation
|
|
// Tools should validate their inputs and outputs for type safety and security.
|
|
//
|
|
// ✅ type Tool interface {
|
|
// Validate(input string) error
|
|
// Execute(ctx context.Context, input string) (string, error)
|
|
// }
|
|
//
|
|
// TODO: Streaming Response Handling
|
|
// LLM streaming should handle partial responses, reconnections, and error recovery gracefully.
|
|
//
|
|
// ✅ Handle partial JSON responses
|
|
// ✅ Implement connection recovery
|
|
// ✅ Provide progress callbacks
|
|
//
|
|
// ## Testing & Quality Patterns
|
|
//
|
|
// TODO: Test Isolation
|
|
// Tests should not depend on external services or shared state between test runs.
|
|
//
|
|
// ✅ Use httprr for HTTP mocking
|
|
// ✅ Use testcontainers for database/service dependencies
|
|
// ❌ Direct calls to external APIs in tests
|
|
//
|
|
// TODO: Provider Compliance Testing
|
|
// All providers implementing the same interface should pass the same compliance test suite.
|
|
//
|
|
// ✅ func TestProviderCompliance(t *testing.T, provider Provider)
|
|
//
|
|
// TODO: Benchmark Coverage
|
|
// Performance-critical paths should have benchmark tests to prevent regressions.
|
|
//
|
|
// ✅ func BenchmarkEmbedding(b *testing.B)
|
|
// ✅ func BenchmarkTokenCounting(b *testing.B)
|
|
//
|
|
// TODO: Property-Based Testing
|
|
// Use property-based testing for validating invariants in chain composition and data processing.
|
|
//
|
|
// ✅ Test that chain composition is associative
|
|
// ✅ Test that embedding operations are deterministic
|
|
//
|
|
// ## Security & Observability Patterns
|
|
//
|
|
// TODO: Secret Handling
|
|
// API keys and secrets should never be logged or exposed in error messages.
|
|
//
|
|
// ✅ Redact secrets in logs and errors
|
|
// ✅ Use secure environment variable patterns
|
|
//
|
|
// TODO: Input Sanitization
|
|
// All user inputs should be sanitized to prevent injection attacks.
|
|
//
|
|
// ✅ func SanitizeUserInput(input string) string
|
|
// ✅ Validate prompt templates for safety
|
|
//
|
|
// TODO: Observability Integration
|
|
// Operations should emit structured logs, metrics, and traces for monitoring.
|
|
//
|
|
// ✅ Use structured logging (slog)
|
|
// ✅ Emit metrics for token usage, latency, errors
|
|
// ✅ Support OpenTelemetry tracing
|
|
//
|
|
// TODO: TLS Configuration
|
|
// All external HTTP calls should use proper TLS configuration.
|
|
//
|
|
// ✅ Enforce minimum TLS version
|
|
// ✅ Certificate validation
|
|
// ✅ Configurable TLS settings
|
|
//
|
|
// ## Documentation & API Design
|
|
//
|
|
// TODO: Example Test Coverage
|
|
// All public APIs should have example tests demonstrating usage.
|
|
//
|
|
// ✅ func ExampleNewOpenAI()
|
|
// ✅ func ExampleChain_Run()
|
|
//
|
|
// TODO: Godoc Completeness
|
|
// All public types, functions, and methods should have comprehensive godoc.
|
|
//
|
|
// ✅ Document expected behavior
|
|
// ✅ Document error conditions
|
|
// ✅ Document thread safety guarantees
|
|
//
|
|
// TODO: Backward Compatibility
|
|
// API changes should maintain backward compatibility or follow proper deprecation cycles.
|
|
//
|
|
// ✅ Use interface evolution patterns
|
|
// ✅ Proper deprecation notices
|
|
// ✅ Semantic versioning compliance
|
|
//
|
|
// # Implementation Priority
|
|
//
|
|
// These rules should be implemented in order of impact on library quality and user experience:
|
|
//
|
|
// 1. Context propagation and error handling (critical for reliability)
|
|
// 2. Test isolation and HTTP mocking (critical for CI/CD stability)
|
|
// 3. Provider compliance and interface consistency (critical for maintainability)
|
|
// 4. Performance patterns and resource management (important for production use)
|
|
// 5. Security and observability patterns (important for enterprise adoption)
|
|
// 6. Documentation and API design patterns (important for developer experience)
|
|
//
|
|
// Each rule should include:
|
|
// - AST-based detection logic
|
|
// - Clear error messages with examples
|
|
// - Automatic fixes where possible
|
|
// - Comprehensive test coverage
|
|
// - Documentation of the architectural reasoning
|
|
package main
|