Structured argument framework for meaningful debates
Project description
Difficult Dialogs
Compile LLM knowledge into portable, deterministic debate modules.
The Problem
LLMs are great for debates, but they're:
- ❌ Expensive at scale ($0.15 per 10-turn debate)
- ❌ Unreliable (hallucinate mid-conversation)
- ❌ Slow (2-5s latency per response)
- ❌ Online-only (need API access)
The Solution
Generate once with an LLM, run forever without one.
┌─────────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ LLM (one-time) │ │ File Format │ │ Interpreter │
│ │ │ (.premise, │ │ (dumb, fast, │
│ Generate argument │─────▶│ .support, │─────▶│ deterministic)│
│ structure │ │ .source) │ │ │
└─────────────────────┘ └──────────────────┘ └─────────────────┘
~60 seconds Portable Microseconds
Smart Auditable Offline
One-time Versionable Infinite runs
Quick Start (5 Minutes)
1. Install
pip install difficult-dialogs
Requires Python 3.10+
2. Try the CLI
# List available arguments
difficult-dialogs list examples/sample_arguments
# Validate quality
difficult-dialogs validate examples/sample_arguments
# Run a debate
difficult-dialogs debate examples/sample_arguments/philosophy/free_will_exists
3. Web Interface (Optional)
# Install Streamlit
pip install streamlit
# Launch web demo
streamlit run examples/streamlit_demo.py
Opens at http://localhost:8501 with beautiful UI for browsing and debating.
Features
✅ Complete Tool Suite
- CLI Tool - Generate, validate, export, debate from command line
- Web Demo - Streamlit-based interactive interface
- Python API - Full programmatic control
- Export Formats - JSON bundles, SQLite databases, Markdown documents
- Validation - Quality scoring and issue detection
✅ Rich Sample Library
32 pre-generated arguments across 6 categories:
- 💻 Technology (5 args) - AI, open source, privacy, remote work, social media
- 🔬 Science (5 args) - Climate change, space exploration, vaccines, genetics, renewable energy
- 🏥 Health (6 args) - Exercise, diet, sleep, meditation, preventive care
- 🌍 Society (6 args) - UBI, education, transportation, recycling, volunteering
- 🤔 Philosophy (5 args) - Cogito, free will, happiness, knowledge, ethics
- 📚 Education (5 args) - Critical thinking, testing, lifelong learning, teacher pay, online learning
✅ Quality Assurance
- 704 automated tests (100% pass rate)
- Validation framework with scoring (0.0-1.0)
- Quality labels: Excellent ⭐, Good 👍, Fair 😐, Poor ❌
- All 32 sample arguments: Excellent quality (1.00 avg score)
✅ Developer Friendly
- Zero runtime dependencies (only requests for LLM generation)
- Type hints throughout (mypy strict mode)
- Well tested (pytest suite)
- Clean API with dataclasses
- Comprehensive docs (inline + markdown)
CLI Commands
Generate Arguments
# Generate single topic
difficult-dialogs generate "AI benefits humanity" \
--server http://localhost:8000 \
--model qwen-72b \
--output my_arguments
# Generate multiple topics
difficult-dialogs generate "Topic 1" "Topic 2" "Topic 3" \
--stance pro \
--depth 2 \
--validate
# With progress bar (install tqdm first)
pip install tqdm
difficult-dialogs generate "Topic 1" "Topic 2" -v
Validate Quality
# Validate entire library
difficult-dialogs validate examples/sample_arguments
# Verbose mode (show issues)
difficult-dialogs validate examples/sample_arguments --verbose
Export
# Export to JSON bundle
difficult-dialogs export examples/sample_arguments library.json
# Export to SQLite database
difficult-dialogs export examples/sample_arguments library.db --stats
# Without validation data
difficult-dialogs export examples/sample_arguments library.json --no-validation
Debate
# Interactive debate
difficult-dialogs debate examples/sample_arguments/science/space_exploration
# Or use short alias
dd debate examples/sample_arguments/health/exercise_improves_mental_health
List Available
# List all arguments
difficult-dialogs list examples/sample_arguments
# Output:
# TECHNOLOGY (5):
# • Artificial Intelligence Will Benefit Humanity
# • Open Source Software Is Superior To Proprietary
# ...
Python API
Generate with LLM
from difficult_dialogs.llm import ArgumentGenerator
gen = ArgumentGenerator("http://localhost:8000")
arg = gen.generate(
topic="Solar energy is cost-effective",
stance="pro",
depth=2,
include_sources=True
)
print(f"Generated {len(arg.premises)} premises")
Validate
from difficult_dialogs.validators import validate_argument, get_quality_label
result = validate_argument(arg)
print(f"Score: {result.score:.2f}")
print(f"Passed: {result.passed}")
print(f"Quality: {get_quality_label(result.score)}")
for issue in result.issues:
print(f" {issue}")
Export
from difficult_dialogs.export import (
export_to_json,
export_library_to_json,
export_to_markdown,
LibraryDatabase,
)
# Single argument to JSON
export_to_json(arg, "my_argument.json")
# Entire library to JSON bundle
export_library_to_json("examples/sample_arguments", "library.json")
# Human-readable Markdown (returns string; writes file when path given)
md = export_to_markdown(arg)
export_to_markdown(arg, "my_argument.md")
# Export to SQLite
db = LibraryDatabase("library.db")
db.add_argument(arg, category="energy")
stats = db.get_statistics()
print(f"Total: {stats['total_arguments']}")
print(f"By category: {stats['by_category']}")
db.close()
Compare Argument Versions
# Review LLM-generated changes before committing
diff = original.diff(updated)
print(diff["meta"]) # changed name/intro/conclusion
print(diff["added_premises"]) # new premise names
print(diff["removed_premises"]) # deleted premise names
print(diff["modified_premises"]) # {name: {added_statements, removed_statements}}
Run Debate Programmatically
from difficult_dialogs.arguments import Argument
from difficult_dialogs.policy import KnowItAllPolicy
# Load argument
arg = Argument.from_directory("examples/sample_arguments/philosophy/free_will_exists")
# Create policy
policy = KnowItAllPolicy(arg)
# Start dialog
print(policy.start())
# Process user input (generator/coroutine protocol)
gen = policy.run_sync()
response = next(gen)
while response:
print(f"BOT: {response}")
user_input = input("USER: ")
try:
response = gen.send(user_input)
except StopIteration:
break
File Structure
Arguments are plain text files in structured directories:
argument_name/
├── intro.dialog # Opening statement
├── conclusion.conclusion # Final statement
└── premise_name/ # One subdirectory per premise
├── premise_name.premise # Core claims (one per line)
├── premise_name.support # Fallback arguments (optional)
├── premise_name.source # Evidence URLs (optional)
├── premise_name.what # Five-Ws explanations (optional)
├── premise_name.why
├── premise_name.how
├── premise_name.when
└── premise_name.where
Example:
free_will_exists/
├── intro.dialog
├── conclusion.conclusion
├── moral_responsibility/
│ ├── moral_responsibility.premise
│ └── moral_responsibility.support
└── quantum_indeterminacy/
├── quantum_indeterminacy.premise
└── quantum_indeterminacy.source
Comparison
| Feature | Difficult Dialogs | Raw LLM API | Other Debate Tools |
|---|---|---|---|
| Cost per debate | $0 (after generation) | $0.10-0.50 | Varies |
| Latency | <1ms | 2-5s | 1-3s |
| Offline | ✅ Yes | ❌ No | ❌ No |
| Hallucinations | ❌ None | ✅ Possible | ⚠️ Sometimes |
| Auditable | ✅ Full file format | ❌ Black box | ⚠️ Limited |
| Versionable | ✅ Git-friendly | ❌ API-dependent | ⚠️ Database |
| Customizable | ✅ Edit files | ⚠️ Prompt only | ❌ Fixed |
| Language | Any (LLM choice) | Any | Usually English |
Installation
Basic Install
pip install difficult-dialogs
With Extras
# Development tools
pip install difficult-dialogs[dev]
# Web interface
pip install difficult-dialogs[web]
# All extras
pip install difficult-dialogs[all]
From Source
git clone https://github.com/JarbasAl/difficult_dialogs
cd difficult_dialogs
pip install -e ".[dev]"
Testing
# Run all tests
pytest test/ -v
# With coverage
pytest test/ --cov=difficult_dialogs --cov-report=html
# Specific test categories
pytest test/test_cli.py -v
pytest test/test_validators.py -v
pytest test/test_export.py -v
Current Status: 704 tests passing ✅
Configuration
LLM Server Setup
Works with any OpenAI-compatible server:
Llama.cpp:
./server -m models/qwen-72b.gguf --host 0.0.0.0 --port 8000
Ollama:
ollama serve
# Default: http://localhost:11434
OpenAI:
export OPENAI_API_KEY="your-key"
# Use in generator: --server https://api.openai.com/v1
Environment Variables
export DD_LLM_SERVER="http://localhost:8000"
export DD_LLM_MODEL="qwen-72b"
export DD_TIMEOUT="120"
Project Structure
difficult_dialogs/
├── difficult_dialogs/
│ ├── __init__.py # Package exports
│ ├── statements.py # Statement dataclass
│ ├── premises.py # Premise dataclass
│ ├── arguments.py # Argument class + loader + diff
│ ├── policy.py # All 10 dialog policies + POLICY_REGISTRY
│ ├── validators.py # Quality validation
│ ├── export/
│ │ ├── __init__.py # Re-exports full public API
│ │ ├── json.py # JSON serialization
│ │ ├── sqlite.py # SQLite database
│ │ └── markdown.py # Markdown export
│ ├── cli.py # Command-line interface
│ └── llm/
│ ├── client.py # HTTP client
│ ├── generator.py # Argument generator
│ └── enhancer.py # Runtime enhancement
├── examples/
│ ├── sample_arguments/ # 32 pre-made arguments
│ ├── streamlit_demo.py # Web interface
│ └── run_argument.py # Simple runner
├── test/
│ └── test_*.py # 704 tests
├── docs/
│ ├── index.md # Overview and navigation
│ ├── argument-format.md # File format reference
│ ├── USER_GUIDE.md # User manual
│ ├── DEVELOPER_GUIDE.md # API reference
│ └── POLICIES.md # Policy reference
├── pyproject.toml # Build config
└── readme.md # This file
Contributing
Report Issues
https://github.com/JarbasAl/difficult_dialogs/issues
Submit PRs
- Fork the repo
- Create feature branch
- Add tests
- Ensure all tests pass
- Submit pull request
Create Arguments
See examples/sample_arguments/README.md for argument creation guide.
Roadmap
Q2 2026
- ✅ CLI tool
- ✅ Export formats (JSON, SQLite)
- ✅ Validation framework
- ✅ Web demo
- ✅ 32 sample arguments
Q3 2026
- JavaScript implementation
- Mobile app (React Native)
- Multi-language support
- Counter-argument generator
Q4 2026
- Visual argument editor
- Collaborative debates
- Argument marketplace
- Enterprise features
License
Apache 2.0 - See LICENSE for details.
Free for personal and commercial use. Attribution appreciated but not required.
Citation
@software{difficult_dialogs2026,
title = {Difficult Dialogs: Structured Argument Framework},
author = {JarbasAl},
year = {2026},
url = {https://github.com/JarbasAl/difficult_dialogs},
version = {0.5.0}
}
Support
- Documentation:
docs/USER_GUIDE.md,docs/DEVELOPER_GUIDE.md - Issues: https://github.com/JarbasAl/difficult_dialogs/issues
- Discussions: https://github.com/JarbasAl/difficult_dialogs/discussions
Happy debating! 💬
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file difficult_dialogs-0.5.1a1.tar.gz.
File metadata
- Download URL: difficult_dialogs-0.5.1a1.tar.gz
- Upload date:
- Size: 70.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
09d153af829e72b7db9986d491ae8c4cdc80ae3c6ab0d2817ca03f8a6b6e1c1a
|
|
| MD5 |
fc4bef4d5015b7f011301f4c0153ffe1
|
|
| BLAKE2b-256 |
1f258363168988442ce2fc0dd2b6cc679febf8851be23219a27b4e544c174ca9
|
File details
Details for the file difficult_dialogs-0.5.1a1-py3-none-any.whl.
File metadata
- Download URL: difficult_dialogs-0.5.1a1-py3-none-any.whl
- Upload date:
- Size: 43.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
578a30bb55877da7b57a369a5a3aca71301a8a359280d201ac5ebd987afc835a
|
|
| MD5 |
766cce89b941602a50785bb8f78fb377
|
|
| BLAKE2b-256 |
9a986a458b5aae515e37e2d59f3deab98b2776d3a895715906801ab1dffbaf9c
|