A complete, robust implementation of the Chain-of-Table algorithm for step-by-step tabular reasoning with Large Language Models (LLMs). This implementation includes advanced validation, loop prevention, and intelligent prompt engineering for reliable table operations.
Chain-of-Table (CoT) is a tabular reasoning strategy that allows LLMs to solve complex questions about tables. Instead of directly generating an answer, CoT guides the model to progressively transform the table through a chain of atomic operations until reaching a final table from which the answer is obtained.
This implementation includes several key improvements for production use:
- Loop Prevention: Prevents infinite loops by detecting repeated operations
- Smart Validation: Validates column existence before operations like
f_group_by,f_sort_by,f_select_column - Intelligent Prompting: Uses step-by-step reasoning examples with explicit "Analysis", "FIRST", and "THEN" logic
- Operation Exclusion: Automatically excludes problematic operations and retries with reduced sets
- Answer Detection: Stops the chain when the answer is available (e.g., after grouping/counting)
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β DynamicPlan βββββΆβ GenerateArgs βββββΆβ Execution β
β (Select β β (Generate β β (Apply β
β operation) β β arguments) β β operation) β
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β² β
β ββββββββββββββββββββ βΌ
βββββββββββββββββββ β Validation β βββββββββββββββββββ
β Query βββββββ - Loop Check ββββββ Table Transform β
β (Final β β - Column Check β β (T β T') β
β answer) β β - Answer Check β β β
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
- DynamicPlan: Selects the next operation using intelligent prompting with step-by-step reasoning
- GenerateArgs: Generates arguments for the selected operation
- Validation: Prevents loops, validates columns, and detects when answers are available
- Execution: Applies atomic operations to transform the table
- Query: Generates the final answer from the transformed table
Chain-Of-Table/
βββ main.py # Main orchestrator
βββ sample_table.json # Sample table
βββ utils/
β βββ table_ops.py # Atomic operations
β βββ table_io.py # Table input/output
βββ prompts/
β βββ dynamic_plan.py # Operation selection with step-by-step reasoning
β βββ generate_args.py # Argument generation with validation
β βββ query.py # Final answer generation
βββ reasoner.py # Main reasoning orchestrator with validation
βββ test_operations.py # Operation tests
βββ test_prompts.py # Prompt tests
βββ demo_operations.py # Operation demo
βββ full_demo.py # Complete demo
βββ README.md # This file
The system uses a sophisticated prompt structure that guides LLMs through explicit reasoning:
- Analysis: General analysis of the table and question
- FIRST: Explicit first step with reasoning
- THEN: Follow-up steps with clear logic
Analysis: The table contains cyclists with embedded country information. To answer
"What country has the most cyclists?", I need to extract countries, group by country,
and count.
FIRST: Use f_add_column to extract country information from the cyclist names.
THEN: Use f_group_by to group by country and count cyclists per country.
The prompts include explicit rules to prevent common errors:
- Column Existence Check: Before using
f_group_by,f_sort_by, orf_select_column, check if the column exists - Add Columns First: If a column doesn't exist, use
f_add_columnfirst - No Repetition: Don't repeat the same operation with identical arguments
- Answer Detection: Stop when the answer is clearly available in the table
- Tracks all executed operations with their arguments
- Prevents repeating identical operations
- Automatically excludes problematic operations and retries
- Checks column existence before operations that require specific columns
- Suggests
f_add_columnwhen needed columns are missing - Validates column names in arguments
- Detects when the answer is available (e.g., after grouping operations)
- Prevents unnecessary additional operations
- Maintains operation chain integrity
- Post-Generation Validation: Validates all generated arguments against current table state
- Column Existence Checks: Ensures operations only reference existing columns
- Duplicate Column Prevention: Prevents creating columns that already exist
- Row Index Validation: Validates row indices are within valid range (1-based indexing)
- Smart Error Messages: Provides clear error messages and helpful suggestions
- Automatic Recovery: Excludes operations with invalid arguments and retries with different operations
Add a new column to the table.
# Example: Add countries extracted from names
f_add_column(table, "Country", ["ESP", "ITA", "ESP"])Select specific rows (1-based indexing).
# Example: Select top 3
f_select_row(table, [1, 2, 3])Select specific columns.
# Example: Only cyclist and country
f_select_column(table, ["Cyclist", "Country"])Group rows and count elements.
# Example: Group by country
f_group_by(table, "Country")Sort rows by a column.
# Example: Sort by count descending
f_sort_by(table, "Count", ascending=False)python main.pypython main.py --question "What country has the most cyclists?" --output results.json--table: Path to JSON table file (default:sample_table.json)--question: Question to answer--output: Output file for results (JSON format)--max-steps: Maximum number of steps (default: 10)--quiet: Quiet mode
Input:
[
{"Rank": 1, "Cyclist": "Alejandro (ESP)"},
{"Rank": 2, "Cyclist": "Davide (ITA)"},
{"Rank": 3, "Cyclist": "Paolo (ITA)"},
{"Rank": 4, "Cyclist": "Haimar (ESP)"}
]Question: "What country has the most cyclists in the top 3?"
Operation Chain:
f_add_column("Country")β Extract countries from namesf_select_row([1, 2, 3])β Select top 3f_group_by("Country")β Group by countryf_sort_by("Count", False)β Sort by count descending
Answer: "Italy" (2 cyclists vs 1 from Spain in top 3)
python test_operations.pypython test_prompts.pypython demo_operations.pypython full_demo.py- Error and edge case handling
- Input validation with column existence checks
- 1-based indexing (as in original paper)
- Loop prevention and operation tracking
- Step-by-step reasoning with Analysis β FIRST β THEN structure
- Explicit rules to prevent common LLM errors
- Critical column existence validation in prompts
- Fallback logic without LLM for testing
- Loop Prevention: Tracks executed operations to prevent infinite loops
- Column Validation: Ensures columns exist before operations that require them
- Answer Detection: Automatically stops when answer is available
- Operation Exclusion: Excludes problematic operations and retries intelligently
- PIPE format visualization
- JSON export with complete operation chain
- Complete transformation history
- Step-by-step execution tracking
- Works reliably with real LLMs
- Handles edge cases and malformed inputs
- Command line interface with extensive options
- Silent and verbose modes
- Comprehensive error handling
def chain_of_table_flow(table, question):
chain = ['[B]'] # Start
executed_operations = set() # Track operations to prevent loops
excluded_ops = set() # Track problematic operations
while True:
# 1. Check if answer is available
if answer_available_in_table(table, question):
break
# 2. Select operation (excluding problematic ones)
operation = dynamic_plan(table, question, chain, excluded_ops)
if operation == '[E]': # End
break
# 3. Generate arguments with validation
args = generate_args(table, question, operation)
# 4. Validate operation (prevent loops, check columns)
operation_key = (operation, str(args))
if operation_key in executed_operations:
excluded_ops.add(operation)
continue # Retry with excluded operation
# 5. Validate column existence for certain operations
if operation in ['f_group_by', 'f_sort_by', 'f_select_column']:
if not column_exists(table, args):
excluded_ops.add(operation)
continue # Retry, hopefully with f_add_column
# 6. Apply operation
table = apply_operation(table, operation, args)
chain.append((operation, args))
executed_operations.add(operation_key)
# 7. Generate final answer
answer = query(table, question)
return answer- Loop Detection: Tracks executed operations to prevent infinite loops
- Column Validation: Ensures columns exist before operations that require them
- Answer Detection: Stops when the answer is clearly available
- Operation Exclusion: Excludes problematic operations and retries
- Smart Retry Logic: Automatically adjusts strategy when operations fail
The system generates a JSON file with:
- answer: Final answer
- chain: Complete operation chain
- tables: Intermediate tables at each step
- final_table: Final transformed table
- steps: Number of executed steps
- Transparency: Each step is visible and explainable
- Reliability: Advanced validation prevents common LLM errors and infinite loops
- Flexibility: Works with different types of questions and table structures
- Robustness: Handles errors, edge cases, and malformed LLM outputs
- Scalability: Easy to add new operations and validation rules
- Evaluation: Allows step-by-step metrics and debugging
- Production Ready: Includes comprehensive error handling and retry logic
The system has been tested for common failure modes:
- β Infinite Loops: System detects and prevents repeated operations
- β Missing Columns: Validates column existence before operations
- β Malformed Arguments: Robust argument parsing and validation
- β Endless Chains: Automatically stops when answer is available
- β Operation Conflicts: Excludes problematic operations and retries
# Test loop prevention
python main.py --question "Test question that might cause loops"
# Test column validation
python main.py --question "Question requiring non-existent columns"
# Test answer detection
python main.py --question "Simple question with clear answer"- Implement function in
utils/table_ops.py - Add to
get_available_operations() - Update
apply_operation() - Add logic in prompts if necessary
# In prompts, change use_llm=True
reasoner = ChainOfTableReasoner()
results = reasoner.reason(table, question, use_llm=True, llm_function=your_llm)- Original paper: "Chain-of-Table: Evolving Tables in the Reasoning Chain for Table Understanding"
- Implementation based on CoT algorithm for tabular reasoning
β Completed:
- Complete atomic operations with robust error handling
- Advanced prompts with step-by-step reasoning structure
- Comprehensive validation system (loop prevention, column validation, answer detection)
- Complete reasoning system with operation exclusion and retry logic
- Command line interface with extensive options
- Extensive tests and demos
- Production-ready robustness features
- Intelligent Prompting: Refactored all prompt examples to use Analysis β FIRST β THEN structure
- Loop Prevention: Added detection and prevention of repeated operations
- Column Validation: Added checks for column existence before operations
- Answer Detection: System stops automatically when answer is available
- Operation Exclusion: Problematic operations are excluded and system retries intelligently
- Critical Rules: Added explicit rules in prompts to prevent common LLM errors
- Enhanced Args Validation: Added comprehensive argument validation after generation to prevent operations on non-existent columns, duplicate columns, and invalid row indices
- Column Existence: Validates that operations like
f_group_by,f_sort_by,f_select_columnonly use existing columns - Duplicate Prevention: Prevents
f_add_columnfrom creating columns that already exist - Row Range Validation: Ensures
f_select_rowonly uses valid row indices (1-based) - Smart Error Messages: Provides helpful suggestions when validation fails
- Graceful Retry: Automatically excludes operations with invalid arguments and retries
π― Ready for production use in tabular reasoning projects with real LLMs!