GoInsight is an internal analytics tool that provides LLM-powered insights on customer feedback data. Product managers can ask natural language questions about customer feedback, and the service generates SQL queries, analyzes the data, and returns actionable insights with recommendations and suggested action items.
β¨ NEW: ML Predictions Integration - Surface predictive account health and product-area priority signals from TensorFlow models trained by tens-insight! See ML_PREDICTIONS.md for details.
β¨ NEW: Jira Integration - Automatically convert AI-generated insights into Jira tickets! See JIRA_INTEGRATION.md for details.
This application demonstrates LLM-powered analytics on structured customer feedback data. In production environments, ETL (Extract, Transform, Load) data would typically be structured differently based on your organization's data warehouse schema, business requirements, and compliance needs.
This project serves as a reference architecture for leveraging Large Language Models (LLMs) with data warehouses:
- Natural Language to SQL: Shows how to safely convert user questions into database queries using LLM prompt engineering
- Insight Generation: Demonstrates automated analysis and recommendation generation from query results
- API-First Design: Illustrates building analytics APIs that combine traditional SQL with modern AI capabilities
- Multi-LLM Support: Provides examples of integrating different LLM providers (OpenAI, Groq, Ollama) with fallback strategies
- Security-First Approach: Implements read-only database access, query validation, and API key management best practices
When implementing similar functionality in production:
- Replace the sample
feedback_enrichedtable with your actual data warehouse tables - Modify the LLM prompts in
internal/llm/prompts.goto match your schema and business logic - Implement proper authentication and authorization for your user base
- Add data governance controls appropriate for your industry and compliance requirements
- Consider data partitioning, caching, and performance optimization for large-scale deployments
The service operates in three main steps:
- SQL Generation: Converts natural language questions into safe SQL SELECT queries
- Data Retrieval: Executes queries against a Postgres database containing structured feedback and ML predictions
- Insight Generation: Uses an LLM to analyze results and produce summaries, recommendations, and action items
GoInsight integrates with tens-insight (TensorFlow-based ML trainer) to provide:
- Account Churn Risk: Predict which accounts are likely to churn
- Product Area Priorities: Identify high-impact areas by customer segment
- Combined Analysis: LLM queries can join feedback data with ML predictions for deeper insights
For ML setup and model training details, see the tens-insight repository.
- Language: Go 1.22+
- Database: PostgreSQL 15
- HTTP Router: Chi (with CORS support for frontend integration)
- LLM Provider: OpenAI (configurable interface)
- Containerization: Docker & Docker Compose
goinsight/
βββ cmd/
β βββ api/ # Main API server entrypoint
β β βββ main.go
β βββ seed/ # Database seeder utility
β βββ main.go
βββ internal/
β βββ builder/ # Query builder utilities
β β βββ query_builder.go
β βββ cache/ # Caching layer
β β βββ cache.go
β β βββ manager.go
β β βββ memory_cache.go
β β βββ memory_cache_test.go
β βββ config/ # Configuration & environment variable loading
β β βββ config.go
β βββ db/ # Database client and query execution
β β βββ interface.go
β β βββ migrations.go
β β βββ postgres.go
β βββ domain/ # Domain models and types
β β βββ feedback.go
β β βββ jira.go
β βββ http/ # HTTP handlers and routing
β β βββ handlers.go
β β βββ handlers_test.go
β β βββ middleware/
β β β βββ middleware.go
β β βββ router.go
β β βββ service_handler.go
β βββ jira/ # Jira integration
β β βββ client.go
β βββ llm/ # LLM client interface and implementations
β β βββ client.go # Interface definition
β β βββ groq_client.go # Groq API implementation
β β βββ mock_client.go # Mock implementation for testing
β β βββ ollama_client.go # Ollama implementation
β β βββ openai_client.go # OpenAI implementation
β β βββ prompts.go # System prompts for SQL and insight generation
β βββ profiler/ # Query profiling and optimization
β β βββ init.go
β β βββ logger.go
β β βββ optimizer.go
β β βββ query_profiler.go
β β βββ slow_query_log.go
β βββ repository/ # Data access layer
β βββ factory.go
β βββ feedback_repository.go
β βββ feedback_repository_test.go
β βββ query_builder.go
β βββ transaction.go
β βββ transaction_test.go
βββ migrations/ # SQL migration files
β βββ 001_init.sql
β βββ 002_seed_feedback.sql
β βββ 003_add_account_risk_scores.sql
β βββ 004_add_product_area_impact.sql
βββ tests/ # Test utilities and integration tests
β βββ fixtures/
β β βββ seed.sql
β βββ integration/
β β βββ api_integration_test.go
β β βββ repository_test.go
β β βββ service_test.go
β β βββ test_helpers.go
β βββ mocks/
β β βββ feedback_repository.go
β βββ testutil/
β βββ db.go
β βββ factory.go
βββ docs/ # Documentation and images
β βββ images/
βββ logs/ # Application logs
βββ bin/ # Compiled binaries
β βββ api
βββ Dockerfile
βββ docker-compose.yml
βββ go.mod
βββ go.sum
βββ README.md
- Docker and Docker Compose installed
- Go 1.22+ (for local development)
- LLM Provider (choose one):
- Mock client (built-in, no setup) - for testing
- Groq API key (FREE, recommended) - get at https://console.groq.com
- Ollama (FREE, local) - install from https://ollama.ai
- OpenAI API key (paid) - get at https://platform.openai.com
- Jira Cloud (optional, for ticket creation) - see JIRA_INTEGRATION.md
cd goinsightCRITICAL: The .env file contains sensitive API keys and must NEVER be committed to version control.
cp .env.example .envEdit .env and fill in your actual values:
# Database Configuration
DATABASE_URL=postgres://goinsight:your_password@postgres:5432/goinsight?sslmode=disable
POSTGRES_PASSWORD=your_password
# LLM Configuration - Using FREE Groq! (RECOMMENDED)
# Get free key: https://console.groq.com/keys
LLM_PROVIDER=groq
GROQ_API_KEY=your_groq_api_key_here
LLM_MODEL=
# Other options:
# Option 1: Mock (No setup, testing only)
# LLM_PROVIDER=mock
# Option 2: Ollama (FREE, local)
# Install: https://ollama.ai
# OLLAMA_URL=http://host.docker.internal:11434
# LLM_PROVIDER=ollama
# LLM_MODEL=llama3
# Option 3: OpenAI (Paid)
# OPENAI_API_KEY=sk-your-key-here
# LLM_PROVIDER=openai
# LLM_MODEL=gpt-4o-mini
# Jira Configuration (Optional - for creating tickets from insights)
# Get your API token: https://id.atlassian.com/manage-profile/security/api-tokens
# Project Key: The key of your Jira project (e.g., SASS, PROJ, DEV)
# JIRA_BASE_URL=https://your-domain.atlassian.net
# JIRA_EMAIL=your-email@company.com
# JIRA_API_TOKEN=your_jira_api_token_here
# JIRA_PROJECT_KEY=YOUR_PROJECT_KEY
# Server Configuration
PORT=8080
ENV=development
DEBUG=false- The
.envfile is in.gitignoreand will NOT be committed - Never hardcode API keys in source code, Dockerfiles, or docker-compose.yml
- Only placeholder/development values appear in committed files
docker compose up --buildThis will:
- Build the Go application container
- Start PostgreSQL
- Run database migrations automatically
- Start the API server on port 8080
The API will wait for PostgreSQL to be ready before starting.
The seed data (33 sample feedback records) is automatically inserted via the 002_seed_feedback.sql migration.
Alternatively, you can run the seeder manually:
go run cmd/seed/main.goOr inside Docker:
docker compose exec api ./seedcurl http://localhost:8080/api/healthResponse:
{
"status": "healthy"
}Returns ML-based churn risk and health metrics for a specific account.
curl http://localhost:8080/api/accounts/acc_ent_001/healthResponse:
{
"account_id": "acc_ent_001",
"churn_probability": 0.78,
"health_score": 32.0,
"risk_category": "high",
"recent_negative_feedback_count": 5,
"predicted_at": "2025-12-08T10:30:00Z",
"model_version": "v1.2.3"
}Returns ML-based priority scores for product areas (optionally filtered by segment).
# All segments
curl http://localhost:8080/api/priorities/product-areas
# Filter by segment
curl http://localhost:8080/api/priorities/product-areas?segment=enterpriseResponse:
{
"product_areas": [
{
"product_area": "billing",
"segment": "enterprise",
"priority_score": 92.5,
"feedback_count": 145,
"avg_sentiment_score": -0.65,
"negative_count": 98,
"critical_count": 34
}
]
}See ML_PREDICTIONS.md for detailed documentation and examples.
Convert AI-generated insights into Jira tickets. See the complete guide: JIRA_INTEGRATION.md
curl -X POST http://localhost:8080/api/jira-tickets \
-H "Content-Type: application/json" \
-d '{
"question": "What are critical issues?",
"summary": "Analysis shows...",
"recommendations": ["Fix X", "Improve Y"],
"actions": [
{"title": "Fix Critical Bug", "description": "..."}
],
"meta": {
"project_key": "PROD",
"default_issue_type": "Story",
"default_labels": ["feedback", "ai-insight"]
}
}'curl -X POST http://localhost:8080/api/ask \
-H "Content-Type: application/json" \
-d '{
"question": "What are the most common billing issues?"
}'Response:
{
"question": "What are the most common billing issues?",
"data_preview": [
{
"topic": "refund processing",
"count": 2
},
{
"topic": "invoice errors",
"count": 1
}
],
"summary": "The data shows that refund processing is the most common billing issue with 2 reports, followed by invoice errors and payment method requests.",
"recommendations": [
"Prioritize fixing the refund processing workflow",
"Review invoice generation logic for accuracy",
"Consider adding PayPal as a payment option"
],
"actions": [
{
"title": "Fix Refund Processing System",
"description": "Investigate and resolve the refund processing delays affecting enterprise customers. This is critical as it's blocking quarterly reconciliation."
},
{
"title": "Audit Invoice Generation",
"description": "Review the invoice calculation logic to prevent incorrect amounts on subscription upgrades."
}
]
}# Performance issues
curl -X POST http://localhost:8080/api/ask \
-H "Content-Type: application/json" \
-d '{"question": "Show me all critical performance issues"}'
# Sentiment analysis
curl -X POST http://localhost:8080/api/ask \
-H "Content-Type: application/json" \
-d '{"question": "What is the sentiment distribution for onboarding feedback?"}'
# Regional analysis
curl -X POST http://localhost:8080/api/ask \
-H "Content-Type: application/json" \
-d '{"question": "Which region has the most negative feedback?"}'
# Customer tier analysis
curl -X POST http://localhost:8080/api/ask \
-H "Content-Type: application/json" \
-d '{"question": "What are enterprise customers complaining about?"}'tens-insight - ML Prediction Engine
TensorFlow-based ML trainer that generates account churn predictions and product area priorities.
The ML predictions are written to PostgreSQL and consumed by GoInsight's /api/accounts/{id}/health and /api/priorities/product-areas endpoints. See ML_PREDICTIONS.md for integration details and workflow.
For a visual, user-friendly way to interact with GoInsight without using curl commands, check out the companion web interface:
Features:
- Interactive Query Interface: Ask questions in natural language with a clean web form
- Real-time Results: See AI-generated insights, recommendations, and action items instantly
- Jira Integration: One-click ticket creation from insights with visual feedback
- Response History: Keep track of previous queries and their results
- Responsive Design: Works on desktop and mobile devices
Quick Start:
- Clone the web UI repository
- Configure it to point to your GoInsight API (default:
http://localhost:8080) - Start the web interface and begin exploring your feedback data visually
The web UI provides the same functionality as the API but with a modern, intuitive interface perfect for product managers and analysts.
The feedback_enriched table structure:
CREATE TABLE feedback_enriched (
id TEXT PRIMARY KEY,
created_at TIMESTAMPTZ NOT NULL,
source TEXT NOT NULL, -- 'zendesk', 'google_play', 'nps_survey'
product_area TEXT NOT NULL, -- 'billing', 'onboarding', 'performance', etc.
sentiment TEXT NOT NULL, -- 'positive', 'neutral', 'negative'
priority INT NOT NULL, -- 1 (low) to 5 (critical)
topic TEXT NOT NULL, -- 'refund issues', 'slow load times', etc.
region TEXT NOT NULL, -- 'NA', 'EU', 'APAC'
customer_tier TEXT NOT NULL, -- 'free', 'pro', 'enterprise'
account_id VARCHAR, -- Customer account identifier
summary TEXT NOT NULL -- Short feedback summary
);All configuration is managed through environment variables:
| Variable | Description | Required | Default |
|---|---|---|---|
DATABASE_URL |
PostgreSQL connection string | Yes | - |
LLM_PROVIDER |
LLM provider: mock, groq, ollama, openai |
No | mock |
OPENAI_API_KEY |
OpenAI API key (if using OpenAI) | Conditional | - |
GROQ_API_KEY |
Groq API key (if using Groq) | Conditional | - |
OLLAMA_URL |
Ollama server URL (if using Ollama) | No | http://localhost:11434 |
LLM_MODEL |
LLM model to use | No | Provider-specific default |
JIRA_BASE_URL |
Jira Cloud base URL (optional) | No | - |
JIRA_EMAIL |
Jira account email (optional) | No | - |
JIRA_API_TOKEN |
Jira API token (optional) | No | - |
JIRA_PROJECT_KEY |
Jira project key (optional) | No | - |
PORT |
HTTP server port | No | 8080 |
ENV |
Environment name | No | development |
DEBUG |
Enable debug logging | No | false |
The application uses the godotenv package to load .env files for local development. In production/Docker environments, environment variables can be set directly without a .env file.
Configuration validation happens at startup - the app will not start without required environment variables.
The OpenAI client (internal/llm/openai_client.go) reads the OPENAI_API_KEY from the environment and makes requests to the OpenAI API.
If OPENAI_API_KEY is not set, the application automatically falls back to a mock client that returns placeholder responses. This is useful for:
- Testing the API structure without LLM costs
- Development without API access
- CI/CD pipelines
To add a new LLM provider (e.g., Claude, Llama):
- Create a new file:
internal/llm/provider_client.go - Implement the
Clientinterface:type Client interface { GenerateSQL(ctx context.Context, question string) (string, error) GenerateInsight(ctx context.Context, question string, queryResults []map[string]any) (string, error) }
- Update
cmd/api/main.goto initialize your client based onLLM_PROVIDERenvironment variable
-
Start PostgreSQL:
docker compose up postgres -d
-
Set up your
.envfile withDATABASE_URLpointing tolocalhost:5432 -
Run migrations:
go run cmd/api/main.go # Migrations run automatically on startup -
Seed data:
go run cmd/seed/main.go
-
Run the API:
go run cmd/api/main.go
go test ./...Create a new SQL file in migrations/ with an incremental number:
# Example: migrations/003_add_sentiment_index.sql
CREATE INDEX idx_sentiment_priority ON feedback_enriched(sentiment, priority);Migrations run automatically on application startup.
- NEVER commit
.envfiles containing real API keys - NEVER hardcode secrets in source code, Dockerfiles, or docker-compose.yml
- Use placeholder values in committed files
- In production, use secret management systems (AWS Secrets Manager, HashiCorp Vault, etc.)
The application implements multiple layers of SQL injection protection:
- LLM Prompt Engineering: The SQL generation prompt explicitly instructs the LLM to generate only SELECT queries
- Query Validation: The handler validates that queries start with SELECT
- Keyword Blacklist: Dangerous keywords (DROP, DELETE, INSERT, UPDATE, etc.) are blocked
- Read-Only Operations: Only SELECT queries are allowed
For production use, consider:
- Using a read-only database user
- Implementing query timeouts
- Adding rate limiting
- Auditing all generated queries
Database Access:
- Create a dedicated read-only database user for the application
- Grant only SELECT permissions on feedback tables
- Never use admin or write-access database credentials
API Security:
- Store LLM API keys in secure secret management systems
- Use API key rotation and monitoring for unusual usage
- Implement rate limiting to prevent API abuse
- Enable HTTPS/TLS for all API communications
Application Hardening:
- Run the application in a containerized environment (Docker/Kubernetes)
- Use non-root user for the application process
- Implement health checks and monitoring
- Set appropriate resource limits (CPU, memory)
- Enable structured logging for audit trails
Data Privacy:
- Ensure compliance with data protection regulations (GDPR, CCPA)
- Implement data retention policies for feedback data
- Anonymize sensitive customer information in logs
- Regular security audits of the codebase and dependencies
# Start services
docker compose up -d
# View logs
docker compose logs -f api
# Stop services
docker compose down
# Rebuild after code changes
docker compose up --build
# Execute commands in container
docker compose exec api sh
# Reset database
docker compose down -v # Removes volumes
docker compose up --buildInterested in what's coming next? Check out our Future Features & Roadmap document to see:
- Planned enhancements and new capabilities
- Advanced ML integrations with tens-insight
- Multi-source feedback aggregation
- Enhanced dashboards and alerting
- Enterprise features and scalability improvements
Have a feature request? Open an issue or see the FUTURE_FEATURES.md for how to contribute!
- The seed data includes 33 diverse feedback records covering billing, onboarding, performance, features, security, UI/UX, and integrations
- Sample data spans different regions (NA, EU, APAC), customer tiers (free, pro, enterprise), and sentiment levels
- Migrations are idempotent and safe to run multiple times
- The application includes automatic database connection retry logic for Docker environments
When contributing:
- Never commit real API keys or credentials
- Test with the mock client before using real LLM APIs
- Ensure all new environment variables are documented in
.env.example - Add appropriate indexes for new query patterns
- Follow Go best practices and idiomatic code style
This project is licensed under the MIT License - see the LICENSE file for details.
Questions or Issues? Check the logs with docker compose logs -f api or open an issue in the repository.