{
  "storage": {
    "type": "sparql",
    "options": {
      "query": "http://${SPARQL_HOST:-localhost}:${SPARQL_PORT:-3030}/semem/query",
      "update": "http://${SPARQL_HOST:-localhost}:${SPARQL_PORT:-3030}/semem/update",
      "data": "http://${SPARQL_HOST:-localhost}:${SPARQL_PORT:-3030}/semem/data",
      "graphName": "http://tensegrity.it/semem",
      "user": "${SPARQL_USER}",
      "password": "${SPARQL_PASSWORD}"
    }
  },
  "servers": {
    "api": 4100,
    "ui": 4150,
    "workbench": 4102,
    "mcp": 4101
  },
  "api": {
    "key": "${SEMEM_API_KEY}"
  },
  "port": 4120,
  "graphName": "http://tensegrity.it/semem",
  "chatModel": "qwen2:1.5b",
  "embeddingModel": "nomic-embed-text:v1.5",
  "embeddingProvider": "nomic",
  "templatesPath": "prompts/templates",
  "sparqlEndpoints": [
    {
      "label": "Hyperdata Fuseki",
      "user": "${SPARQL_USER}",
      "password": "${SPARQL_PASSWORD}",
      "urlBase": "https://fuseki.hyperdata.it",
      "dataset": "hyperdata.it",
      "query": "/hyperdata.it/query",
      "update": "/hyperdata.it/update",
      "upload": "/hyperdata.it/upload",
      "gspRead": "/hyperdata.it/data",
      "gspWrite": "/hyperdata.it/data"
    },
    {
      "label": "Tbox Fuseki",
      "user": "${SPARQL_USER}",
      "password": "${SPARQL_PASSWORD}",
      "urlBase": "http://localhost:4030",
      "dataset": "hyperdata.it",
      "query": "/hyperdata.it/query",
      "update": "/hyperdata.it/update",
      "upload": "/hyperdata.it/upload",
      "gspRead": "/hyperdata.it/data",
      "gspWrite": "/hyperdata.it/data"
    }
  ],
  "llmProviders": [
    {
      "type": "groq",
      "implementation": "hyperdata-clients",
      "apiKey": "${GROQ_API_KEY}",
      "chatModel": "llama-3.1-8b-instant",
      "priority": 1,
      "capabilities": [
        "chat"
      ],
      "rateLimit": {
        "delayMs": 100,
        "description": "Delay between API calls to avoid rate limiting"
      },
      "description": "Using hyperdata-clients implementation for fast inference"
    },
    {
      "type": "mistral",
      "implementation": "hyperdata-clients",
      "apiKey": "${MISTRAL_API_KEY}",
      "chatModel": "mistral-small-latest",
      "priority": 2,
      "capabilities": [
        "chat"
      ],
      "rateLimit": {
        "delayMs": 1000,
        "description": "Delay between API calls to avoid rate limiting"
      },
      "description": "Using hyperdata-clients implementation"
    },
    {
      "type": "claude",
      "implementation": "hyperdata-clients",
      "apiKey": "${CLAUDE_API_KEY}",
      "chatModel": "claude-3-opus-20240229",
      "priority": 3,
      "capabilities": [
        "chat"
      ],
      "rateLimit": {
        "delayMs": 500,
        "description": "Delay between API calls to avoid rate limiting"
      },
      "description": "Using hyperdata-clients implementation"
    },
    {
      "type": "nomic",
      "apiKey": "${NOMIC_API_KEY}",
      "embeddingModel": "nomic-embed-text:v1.5",
      "embeddingDimension": 768,
      "priority": 1,
      "capabilities": [
        "embedding"
      ],
      "description": "Nomic Atlas API for cloud-based embeddings"
    },
    {
      "type": "ollama",
      "baseUrl": "http://localhost:11434",
      "chatModel": "qwen2:1.5b",
      "embeddingModel": "nomic-embed-text",
      "embeddingDimension": 768,
      "priority": 2,
      "capabilities": [
        "embedding",
        "chat"
      ],
      "description": "Local Ollama for embeddings and chat - fallback option"
    },
    {
      "type": "nomic",
      "implementation": "hyperdata-clients",
      "apiKey": "${NOMIC_API_KEY}",
      "embeddingModel": "nomic-embed-text:v1.5",
      "priority": 4,
      "capabilities": [
        "embedding"
      ],
      "rateLimit": {
        "delayMs": 200,
        "description": "Delay between API calls to avoid rate limiting"
      },
      "description": "Embedding provider for text embeddings"
    }
  ],
  "performance": {
    "wikidata": {
      "rateLimit": 200,
      "maxEntitiesPerConcept": 5,
      "maxWikidataSearchResults": 5,
      "minConfidence": 0.7,
      "batchSize": 5,
      "parallelRequests": 3,
      "timeout": 15000
    },
    "wikipedia": {
      "rateLimit": 100,
      "defaultLimit": 20,
      "maxLimit": 75,
      "batchSize": 25,
      "timeout": 10000,
      "searchResultsLimit": 2
    },
    "ingestion": {
      "earlyTerminationThreshold": 0.8,
      "maxPagesPerQuery": 50,
      "useRelevanceFiltering": true,
      "skipLowConfidenceEntities": true,
      "chunking": {
        "enabled": true,
        "threshold": 5000,
        "maxChunkSize": 2000,
        "minChunkSize": 100,
        "overlapSize": 100,
        "batchSize": 5
      }
    },
    "relationships": {
      "maxQuestionsToProcess": 5,
      "maxWikipediaCorpusclesPerQuestion": 20,
      "maxTriplesToGenerate": 100,
      "semanticSimilarityThreshold": 0.4,
      "enableBatching": true,
      "batchSize": 10
    }
  },
  "relevanceFiltering": {
    "enabled": true,
    "minTextSimilarity": 0.6,
    "popularityWeight": 0.2,
    "typeRelevanceWeight": 0.3,
    "skipExpandedSearch": false
  },
  "search": {
    "defaultThreshold": 0.5,
    "defaultMode": "dual",
    "defaultLimit": 10,
    "enableContextEnrichment": true,
    "enableProvenance": true
  },
  "baseUri": "http://tensegrity.it/semem/",
  "context": {
    "truncationLimit": null
  },
  "conceptExtraction": {
    "maxConcepts": 3,
    "temperature": 0.1,
    "retries": 3,
    "minConceptLength": 4,
    "maxConceptLength": 80,
    "deduplication": {
      "enabled": true,
      "strategy": "exact",
      "caseInsensitive": true,
      "embeddingSimilarityThreshold": 0.9,
      "maxExistingConceptsToCheck": 1000,
      "description": "Concept deduplication settings to avoid creating duplicate concept corpuscles"
    }
  },
  "sparqlIngestion": {
    "templateDirectory": "config/sparql-templates",
    "defaultTemplate": "generic-documents",
    "defaultLimit": 50,
    "defaultTimeout": 30000,
    "defaultBatchSize": 50,
    "presetEndpoints": {
      "danny-blog": {
        "url": "https://fuseki.hyperdata.it/danny.ayers.name/query",
        "template": "blog-articles",
        "auth": {
          "user": "${SPARQL_USER}",
          "password": "${SPARQL_PASSWORD}"
        },
        "fieldMappings": {
          "uri": "uri",
          "title": "title", 
          "content": "content",
          "created": "created",
          "modified": "modified",
          "slug": "slug",
          "relative": "relative"
        },
        "description": "Danny Ayers' blog articles from Fuseki endpoint"
      },
      "local-fuseki": {
        "url": "http://localhost:3030/dataset/query",
        "template": "generic-documents",
        "auth": {
          "user": "admin",
          "password": "admin"
        },
        "description": "Local Fuseki instance for testing"
      },
      "wikidata": {
        "url": "https://query.wikidata.org/sparql",
        "template": "wikidata-entities",
        "auth": null,
        "timeout": 60000,
        "description": "Wikidata SPARQL endpoint (public, no auth required)"
      }
    },
    "processing": {
      "defaultLazy": false,
      "enableProgressReporting": true,
      "retryFailedDocuments": 3,
      "skipExistingDocuments": true
    },
    "validation": {
      "minContentLength": 10,
      "maxContentLength": 1000000,
      "requiredFields": ["uri", "title", "content"],
      "skipEmptyContent": true
    }
  }
}