defog-ai/sql-eval

repository·main·Indexed 20 days ago

https://github.com/defog-ai/sql-eval

A framework for evaluating SQL generation models by comparing generated queries against 'gold' queries using data-driven matching on real database results. It supports multiple database dialects including Postgres, Snowflake, BigQuery, MySQL, SQLite, and SQL Server, and provides runners for OpenAI, Anthropic, Hugging Face, vLLM, Llama CPP, and MLX.

Tokens
13K
Snippets
34
Records
39
Agent score
73%

What's inside sql-eval

  1. Handle thinking tokens in LLM outputs

    main

    If you are using a model that outputs thinking tokens (e.g., reasoning models), use the --enable_thinking flag. This tells the runner to remove the thinking tokens from the LLM output before running the generated query to ensure valid SQL evaluation.

    ./run_qwen.sh --thinking
  2. Define prompt templates using variables

    main

    You can construct SQL generation prompts using a template containing specific variables. These variables are intended to be populated at runtime using Python's .format() method.

    Available variables:

    • {user_question}: The natural language question for which SQL needs to be generated.
    • {table_metadata_string}: A string containing table names, column names, and types. For the sqlcoder model, this should be formatted as a SQL DDL statement.
    • {instructions} (optional): Custom instructions for specific questions (e.g., date formatting, dialect adaptation).
    • {k_shot_prompt} (optional): Few-shot examples containing question-SQL pairs to provide context.
    • {glossary} (optional): Definitions for special terminology or specific SQL creation rules.
    ### Task
    Generate a SQL query to answer the following question:
    `{user_question}`
    `{instructions}`
    `{glossary}`
    ### Database Schema
    The query will run on a database with the following schema:
    {table_metadata_string}
    {k_shot_prompt}
    ### Answer
    Given the database schema, here is the SQL query that answers `{user_question}`:
    ```sql
  3. Import data into Postgres

    main

    After setting up the Postgres Docker container, use the defog-data repository to import the 7 SQL databases. You must set the database credentials as environment variables before running the setup.sh script. This assumes you have a psql client installed locally.

    cd defog-data
    export DBPASSWORD="postgres"
    export DBUSER="postgres"
    export DBHOST="localhost"
    export DBPORT=5432
    ./setup.sh
  4. Run evaluations with vLLM

    main

    The vLLM runner uses the vLLM engine to run inference as a single batch, which is faster for num_beams > 1.

    • Use -g vllm.
    • Use -a to pass paths to LoRA adapters.
    • Use -qz or --quantized if the model is quantized with AWQ.
    • For multiple prompts in one run, provide a list of files to -f and -o (the counts must match).
    # Standard vLLM run
    python -W ignore main.py \
      -db postgres \
      -q "data/questions_gen_postgres.csv" "data/instruct_basic_postgres.csv" "data/instruct_advanced_postgres.csv" \
      -o results/vllm_classic.csv results/vllm_basic.csv results/vllm_advanced.csv \
      -g vllm \
      -f "prompts/prompt.md" \
      -m defog/llama-3-sqlcoder-8b \
      -a path/to_adapter \
      -c 0
    
    # Running with multiple prompts to save model loading time
    python -W ignore main.py \
      -db postgres \
      -q "data/questions_gen_postgres.csv" \
      -o results/results_1.csv results/results_2.csv \
      -g vllm \
      -f prompts/prompt_1.md prompts/prompt_2.md \
      -m defog/sqlcoder2
  5. Run evaluations with Anthropic models

    main

    Ensure ANTHROPIC_API_KEY is set as an environment variable. Use the -g anthropic flag and provide an Anthropic-compatible prompt file (e.g., .md).

    python main.py \
      -db postgres \
      -q "data/questions_gen_postgres.csv" "data/instruct_basic_postgres.csv" "data/instruct_advanced_postgres.csv" \
      -o results/claude3_classic.csv results/claude3_basic.csv results/claude3_advanced.csv \
      -g anthropic \
      -f prompts/prompt_anthropic.md \
      -m claude-3-opus-20240229 \
      -p 5 \
      -c 0
  6. Report results to a Cloud Function via --upload_url

    main

    You can automatically report evaluation results to a server (like a Google Cloud Function) using the --upload_url flag.

    1. Deploy a Cloud Function

    The repository provides sample functions for BigQuery and Postgres.

    Setup:

    1. Copy .env.yaml.template to .env.yaml and fill in the fields.
    2. For BigQuery, place your service account key.json in the folder and set CREDENTIALS_PATH in .env.yaml.

    Deploy BigQuery function:

    gcloud functions deploy results_bigquery \
      --source results_fn_bigquery \
      --entry-point bigquery \
      --env-vars-file results_fn_bigquery/.env.yaml \
      --runtime python311 \
      --memory 512MB \
      --trigger-http \
      --allow-unauthenticated \
      --gen2

    Deploy Postgres function:

    gcloud functions deploy results_postgres \
      --source results_fn_postgres \
      --entry-point postgres \
      --env-vars-file results_fn_postgres/.env.yaml \
      --runtime python311 \
      --memory 512MB \
      --trigger-http \
      --allow-unauthenticated \
      --gen2

    2. Run Evaluation

    Pass the deployed URL to your main.py command:

    python main.py \
      -db postgres \
      -o results/test.csv \
      -g oa \
      -f prompts/prompt_openai.json \
      -m gpt-4o-mini \
      -n 1 \
      --upload_url <your cloud function url>

    Tip: To always report to a specific URL without passing the flag every time, set the SQL_EVAL_UPLOAD_URL environment variable.

  7. Run evaluations with Hugging Face models

    main

    Use the -g hf flag. You can load a PEFT adapter using the -a flag. To avoid warnings regarding sequential use of transformers pipelines, use python -W ignore main.py.

    # Testing with a specific model
    python -W ignore main.py \
      -db postgres \
      -q "data/questions_gen_postgres.csv" "data/instruct_basic_postgres.csv" "data/instruct_advanced_postgres.csv" \
      -o results/hf_classic.csv results/hf_basic.csv results/hf_advanced.csv \
      -g hf \
      -f prompts/prompt.md \
      -m defog/llama-3-sqlcoder-8b \
      -c 0
    
    # Testing with a PEFT adapter
    python -W ignore main.py \
      -db postgres \
      -q "data/questions_gen_postgres.csv" "data/instruct_basic_postgres.csv" "data/instruct_advanced_postgres.csv" \
      -o results/hf_classic.csv results/hf_basic.csv results/hf_advanced.csv \
      -g hf \
      -f prompts/prompt.md \
      -m defog/llama-3-sqlcoder-8b \
      -a path/to_adapter \
      -c 0
  8. Use private data for evaluation

    main

    You can repurpose the framework for private datasets by following these steps:

    1. Prepare Data: Create a separate git repository for your private data containing a setup.py file (similar to defog-data). Create metadata and data files and import them into your database.
    2. Define Joins: For metadata pruning, you must define a columns_join dictionary mapping database names to a nested dictionary of table tuples and column name tuples.
    3. Integrate:
      • Install your data library with pip install -e ..
      • Replace function calls and variables in utils/pruning.py (specifically within prune_metadata_str) to point to your private data's modules/functions.
      • Update your questions file to point to your custom questions tailored to your schema.

    Warning: Ensure your database is populated with meaningful data. Empty tables will result in empty dataframes, causing false positive matches in the evaluation.

  9. Run evaluations with local runtimes (Llama CPP and MLX)

    main

    Both Llama CPP and MLX currently do not support beam search, which may result in lower quality results.

    • Llama CPP: Requires llama-cpp-python. On Apple Silicon, install with CMAKE_ARGS="-DLLAMA_METAL=on" pip install llama-cpp-python.
    • MLX: Requires mlx-lm (pip install mlx-lm).
    # Llama CPP
    python -W ignore main.py \
      -q "data/questions_gen_postgres.csv" \
      -db postgres \
      -o "results/llama_cpp.csv" \
      -g llama_cpp \
      -f "prompts/prompt.md" \
      -m path/to/model.gguf
    
    # MLX
    python -W ignore main.py \
      -db postgres \
      -q "data/questions_gen_postgres.csv" \
      -o "results/mlx_llama-3-sqlcoder-8b.csv" \
      -g mlx \
      -f "prompts/prompt.md" \
      -m mlx-community/defog-llama-3-sqlcoder-8b
  10. Set up a Postgres instance using Docker

    main

    The evaluation framework uses Postgres. It is recommended to use Docker with mounted volumes to persist data and facilitate imports.

    1. Create the container: Run the following to create a container named postgres-sql-eval with a password of postgres, mapping port 5432 and mounting local data/postgres and data/export directories.
    2. Start the container: Use docker start to run it.
    3. Stop/Reset: Use docker stop to stop the instance. You can verify the container exists using docker container list -a.

    Note: Ensure no other Postgres instances are using port 5432 before running these commands.

    mkdir data/postgres data/export
    docker create --name postgres-sql-eval -e POSTGRES_PASSWORD=postgres -p 5432:5432 -v $(pwd)/data/postgres:/var/lib/postgresql/data -v $(pwd)/data/export:/export postgres:16-alpine
    
    docker start postgres-sql-eval
  11. Run evaluations with OpenAI models

    main

    To evaluate OpenAI models, ensure OPENAI_API_KEY is set as an environment variable.

    For standard models (like o3-mini), use a standard prompt file. For o1-* models which do not support system prompts, use a specific prompt file (e.g., prompts/prompt_openai_o1.json), reduce the parallel requests (-p), and increase the timeout (-t).

    # Standard OpenAI model
    python main.py \
      -db postgres \
      -q "data/questions_gen_postgres.csv" "data/instruct_basic_postgres.csv" "data/instruct_advanced_postgres.csv" \
      -o results/openai_classic.csv results/openai_basic.csv results/openai_advanced.csv \
      -g oa \
      -f prompts/prompt_openai.json \
      -m o3-mini \
      -p 5 \
      -c 0
    
    # o1 series models (no system prompt support)
    python main.py \
      -db postgres \
      -q "data/questions_gen_postgres.csv" "data/instruct_basic_postgres.csv" "data/instruct_advanced_postgres.csv" \
      -o results/openai_o1mini_classic.csv results/openai_o1mini_basic.csv results/openai_o1mini_advanced.csv \
      -g oa \
      -f prompts/prompt_openai_o1.json \
      -m o1-mini \
      -p 1 \
      -t 120 \
      -c 0
  12. Import data into BigQuery, MySQL, SQLite, or SQL Server

    main

    To import data for other dialects, configure your credentials and use the translate_ddl_dialect.py script from the defog-data repository.

    When running the evaluation, you must:

    1. Set the correct --db_type flag.
    2. Use the corresponding _{dialect} question files from the /data directory.
    python translate_ddl_dialect.py