BUCKYVERSE

Troubleshooting Guide

This guide helps diagnose and resolve common issues with the LLM-based scanno detection system.

Common Issues

1. Ollama Connection Issues

Symptoms:

Solutions:

# Check if Ollama is running
curl http://localhost:11434/api/version

# Start Ollama service
ollama serve

# On macOS, restart Ollama
brew services restart ollama

# Check Ollama logs
ollama logs

Configuration check:

# Verify Ollama URL in config
config = Application.get_env(:codexis, :scanno_detection)
IO.inspect(config[:ollama_url])

# Test connection
Req.get!("#{config[:ollama_url]}/api/version")

2. Model Not Found

Symptoms:

Solutions:

# List available models
ollama list

# Pull required model
ollama pull qwen3.0:8b
ollama pull deepseek-r1:8b

# Verify model is downloaded
ollama show qwen3.0:8b

3. Slow Performance

Symptoms:

Solutions:

# Reduce concurrency
config :codexis, :scanno_detection,
  max_concurrency: 2,  # Reduce from default
  batch_size: 50,      # Smaller batches
  model: "qwen2.5:3b"  # Use smaller model

# Enable caching
config :codexis, :scanno_detection,
  cache_results: true,
  cache_directory: "priv/scanno_cache"

# Profile performance
{time, result} = :timer.tc(fn ->
  ScannoDetector.detect_scannos(content)
end)
IO.puts("Time: #{time/1_000_000} seconds")

4. Memory Issues

Symptoms:

Solutions:

# Limit memory usage
config :codexis, :scanno_memory,
  max_heap_size: 1_000_000,
  fullsweep_after: 10

# Process in smaller chunks
def process_large_file(path) do
  path
  |> File.stream!([], 5000)  # Read in 5KB chunks
  |> Stream.chunk_every(10)  # Process 10 lines at a time
  |> Stream.map(&process_chunk/1)
  |> Enum.to_list()
end

# Monitor memory usage
:erlang.memory()

5. Poor Detection Accuracy

Symptoms:

Solutions:

# Adjust confidence thresholds
config :codexis, :scanno_detection,
  confidence_threshold: 0.8,    # Increase threshold
  auto_accept_threshold: 0.95   # Be more conservative

# Use better models
config :codexis, :scanno_detection,
  default_model: "qwen2.5:14b",  # Larger model
  math_model: "deepseek-r1:8b"

# Add custom patterns
defmodule CustomPatterns do
  def domain_specific_patterns do
    %{
      ~r/\bspecific_error\b/ => "specific_correction",
      # Add more patterns
    }
  end
end

6. LaTeX Processing Errors

Symptoms:

Solutions:

# Improve LaTeX extraction
defmodule ImprovedLatexProcessor do
  def extract_commands(content) do
    # Better regex for LaTeX commands
    Regex.scan(~r/\\([a-zA-Z]+\*?)(?:\[[^\]]*\])?(?:\{[^}]*\})*/, content)
  end
  
  def extract_math(content) do
    # Handle both inline and display math
    inline = Regex.scan(~r/\$([^$]+)\$/, content)
    display = Regex.scan(~r/\\\[(.*?)\\\]/s, content)
    inline ++ display
  end
end

# Use specialized prompts for LaTeX
def latex_specific_prompt(content) do
  """
  You are checking LaTeX source code for OCR errors.
  Focus on:
  1. LaTeX command misspellings
  2. Bracket mismatches
  3. Math symbol errors
  
  Content:
  #{content}
  """
end

Debugging Tools

1. Enable Debug Logging

# config/dev.exs
config :logger, level: :debug

config :codexis, :scanno_detection,
  verbose_logging: true,
  save_intermediate_results: true

# In your code
require Logger

Logger.debug("Processing block: #{inspect(block)}")
Logger.debug("LLM response: #{inspect(response)}")

2. Inspection Tools

defmodule Codexis.Debug do
  def inspect_prompt(content) do
    prompt = ScannoDetector.build_prompt(content)
    IO.puts("Generated prompt:")
    IO.puts(prompt)
    prompt
  end
  
  def test_llm_connection do
    case Codexis.LLM.OllamaClient.generate("test", model: "qwen3.0:8b") do
      {:ok, response} -> 
        IO.puts("LLM connection OK")
        IO.inspect(response)
      {:error, error} ->
        IO.puts("LLM connection failed:")
        IO.inspect(error)
    end
  end
  
  def analyze_corrections(corrections) do
    %{
      total: length(corrections),
      by_confidence: Enum.group_by(corrections, & &1["confidence"]),
      unique_patterns: corrections
        |> Enum.map(& {&1["original"], &1["corrected"]})
        |> Enum.uniq()
        |> length()
    }
  end
end

3. Performance Profiling

defmodule Codexis.Profiler do
  def profile_detection(content) do
    :fprof.apply(&ScannoDetector.detect_scannos/1, [content])
    :fprof.profile()
    :fprof.analyse(dest: "scanno_profile.txt")
  end
  
  def benchmark_models do
    models = ["qwen2.5:3b", "qwen3.0:8b", "qwen2.5:14b"]
    content = "Sample content with errors"
    
    Enum.each(models, fn model ->
      {time, _} = :timer.tc(fn ->
        ScannoDetector.detect_scannos(content, model: model)
      end)
      
      IO.puts("#{model}: #{time/1_000_000}s")
    end)
  end
end

Error Messages

Common Error Messages and Solutions

Error Message Cause Solution
{:error, :timeout} LLM response too slow Increase timeout, use smaller model
{:error, :invalid_json} Malformed LLM response Check prompt format, retry request
{:error, :model_not_found} Model not available Pull model with ollama pull
{:error, :connection_refused} Ollama not running Start Ollama service
{:error, :out_of_memory} Too much data in memory Process in smaller chunks

Custom Error Handling

defmodule Codexis.ErrorHandler do
  def handle_scanno_error({:error, :timeout}) do
    Logger.warn("LLM timeout - retrying with smaller chunk")
    {:retry, chunk_size: 1000}
  end
  
  def handle_scanno_error({:error, :invalid_json}) do
    Logger.error("Invalid JSON response - using fallback")
    {:fallback, use_pattern_matching: true}
  end
  
  def handle_scanno_error({:error, reason}) do
    Logger.error("Unexpected error: #{inspect(reason)}")
    {:error, reason}
  end
end

Health Checks

System Health Check

defmodule Codexis.HealthCheck do
  def check_system do
    %{
      ollama: check_ollama(),
      models: check_models(),
      memory: check_memory(),
      disk: check_disk_space(),
      cache: check_cache()
    }
  end
  
  defp check_ollama do
    case Req.get("http://localhost:11434/api/version") do
      {:ok, %{status: 200}} -> :ok
      _ -> :error
    end
  end
  
  defp check_models do
    required_models = ["qwen3.0:8b", "deepseek-r1:8b"]
    
    available = case System.cmd("ollama", ["list"]) do
      {output, 0} -> parse_model_list(output)
      _ -> []
    end
    
    missing = required_models -- available
    
    if Enum.empty?(missing), do: :ok, else: {:error, missing}
  end
  
  defp check_memory do
    memory = :erlang.memory(:total) / 1_024_024_024  # GB
    if memory < 2.0, do: :warning, else: :ok
  end
  
  defp check_disk_space do
    cache_dir = Application.get_env(:codexis, :scanno_detection)[:cache_directory]
    
    case System.cmd("df", [cache_dir]) do
      {output, 0} ->
        # Parse available space
        :ok
      _ ->
        :error
    end
  end
end

Monitoring Dashboard

defmodule Codexis.Monitor do
  use GenServer
  
  def start_link(_) do
    GenServer.start_link(__MODULE__, %{}, name: __MODULE__)
  end
  
  def get_stats do
    GenServer.call(__MODULE__, :get_stats)
  end
  
  @impl true
  def init(_) do
    :timer.send_interval(60_000, :collect_stats)
    {:ok, %{stats: %{}}}
  end
  
  @impl true
  def handle_info(:collect_stats, state) do
    stats = %{
      detections_per_minute: count_detections(),
      average_response_time: calculate_avg_response_time(),
      error_rate: calculate_error_rate(),
      cache_hit_rate: calculate_cache_hit_rate()
    }
    
    {:noreply, %{state | stats: stats}}
  end
end

Recovery Procedures

Automatic Recovery

defmodule Codexis.Recovery do
  def with_recovery(fun, opts \\ []) do
    max_retries = Keyword.get(opts, :max_retries, 3)
    
    try do
      fun.()
    rescue
      error ->
        if max_retries > 0 do
          Logger.warn("Error occurred, retrying... (#{max_retries} left)")
          Process.sleep(1000)
          with_recovery(fun, Keyword.put(opts, :max_retries, max_retries - 1))
        else
          reraise error, __STACKTRACE__
        end
    end
  end
  
  def recover_from_cache_corruption do
    cache_dir = Application.get_env(:codexis, :scanno_detection)[:cache_directory]
    
    Logger.warn("Clearing corrupted cache: #{cache_dir}")
    File.rm_rf!(cache_dir)
    File.mkdir_p!(cache_dir)
  end
  
  def recover_from_model_issues(model) do
    Logger.warn("Model issues detected, attempting to reload: #{model}")
    
    # Stop using the model temporarily
    disable_model(model)
    
    # Re-pull the model
    System.cmd("ollama", ["pull", model])
    
    # Re-enable the model
    enable_model(model)
  end
end

Manual Recovery Steps

  1. Clear Cache:

    rm -rf priv/scanno_cache/*
    
  2. Restart Services:

    # Restart Ollama
    brew services restart ollama
    
    # Restart application
    iex -S mix
    
  3. Reset Configuration:

    # Reset to defaults
    Application.put_env(:codexis, :scanno_detection, 
      Codexis.BuildPipeline.Config.default_scanno_config()
    )
    

Log Analysis

Log Patterns

defmodule Codexis.LogAnalyzer do
  def analyze_logs(log_file) do
    log_file
    |> File.stream!()
    |> Stream.map(&parse_log_line/1)
    |> Stream.filter(& &1)
    |> Enum.reduce(%{}, &categorize_log/2)
  end
  
  defp parse_log_line(line) do
    case Regex.run(~r/\[(error|warn|info|debug)\] (.+)/, line) do
      [_, level, message] -> %{level: level, message: message}
      _ -> nil
    end
  end
  
  defp categorize_log(log, acc) do
    category = determine_category(log.message)
    Map.update(acc, category, 1, & &1 + 1)
  end
  
  defp determine_category(message) do
    cond do
      message =~ "timeout" -> :timeout
      message =~ "memory" -> :memory
      message =~ "connection" -> :connection
      message =~ "model" -> :model
      true -> :other
    end
  end
end

Common Log Messages

Log Message Meaning Action
"LLM timeout after 30000ms" Request timed out Increase timeout or use smaller model
"Connection refused" Ollama not available Start Ollama service
"Out of memory" Memory exhausted Reduce batch size or concurrency
"Invalid JSON response" Parsing error Check prompt format
"Model not found" Model not installed Pull model with ollama

Support Resources

Getting Help

  1. Documentation: Check the full documentation at /docs/llm-scanno
  2. Issue Tracker: Report bugs on GitHub
  3. Community Forum: Ask questions in discussions
  4. Debug Mode: Enable with config :codexis, :debug_mode, true

Diagnostic Script

# Save as diagnostic.exs and run with: mix run diagnostic.exs

defmodule Diagnostic do
  def run do
    IO.puts("Codexis Scanno Detection Diagnostic")
    IO.puts("==================================")
    
    check_environment()
    check_configuration()
    check_models()
    test_detection()
    
    IO.puts("\nDiagnostic complete!")
  end
  
  defp check_environment do
    IO.puts("\n1. Environment Check:")
    IO.puts("   Elixir: #{System.version()}")
    IO.puts("   OTP: #{:erlang.system_info(:otp_release)}")
  end
  
  defp check_configuration do
    IO.puts("\n2. Configuration Check:")
    config = Application.get_env(:codexis, :scanno_detection)
    IO.inspect(config, label: "   Config")
  end
  
  defp check_models do
    IO.puts("\n3. Model Check:")
    case System.cmd("ollama", ["list"]) do
      {output, 0} -> IO.puts("   Models: #{output}")
      _ -> IO.puts("   ERROR: Cannot list models")
    end
  end
  
  defp test_detection do
    IO.puts("\n4. Detection Test:")
    test_content = "This is a tost with an error."
    
    case Codexis.QualityChecker.ScannoDetector.detect_scannos(test_content) do
      {:ok, results} -> 
        IO.puts("   SUCCESS: Detected #{map_size(results)} corrections")
      {:error, error} ->
        IO.puts("   ERROR: #{inspect(error)}")
    end
  end
end

Diagnostic.run()

Best Practices

  1. Start Small: Test with small documents first
  2. Monitor Resources: Watch CPU and memory usage
  3. Use Caching: Enable caching for repeated documents
  4. Choose Models Wisely: Balance accuracy vs. speed
  5. Handle Errors Gracefully: Implement proper error recovery
  6. Keep Logs: Enable logging for troubleshooting
  7. Regular Maintenance: Clean cache, update models periodically