BODHI: Epistemic virtues (curiosity and humility) for LLM responses
Project description
BODHI: Bridging, Open, Discerning, Humble, Inquiring
A lightweight, provider-agnostic wrapper that embeds epistemic virtues (curiosity and humility) into LLM responses through a two-pass prompting strategy.
Results
BODHI achieved +24.2% improvement on HealthBench Hard and consistent gains across all benchmarks:
| Benchmark | Baseline | BODHI | Improvement |
|---|---|---|---|
| Consensus | 85.0% | 88.3% | +3.3% |
| Hard | 0.0% | 24.2% | +24.2% |
| General | 29.9% | 43.1% | +13.3% |
Installation
From PyPI
pip install bodhi-llm
# With OpenAI support
pip install bodhi-llm[openai]
# All providers
pip install bodhi-llm[all]
From Source (for development)
# Clone the repository
git clone https://github.com/sebasmos/bodhi.git
cd bodhi
# Create a virtual environment (recommended)
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Upgrade pip (required for editable install with pyproject.toml)
pip install --upgrade pip
# Install with all dependencies
pip install -e ".[all]"
# Or install with dev dependencies for testing
pip install -e ".[dev]"
Quick Start
With OpenAI
from bodhi import BODHI
from bodhi.providers import OpenAIChat
# Create chat function
chat = OpenAIChat(api_key="sk-...", model="gpt-4o-mini")
# Wrap with BODHI
bodhi = BODHI(chat)
# Generate response
response = bodhi.complete("I have chest pain")
print(response.content) # Final response
print(response.analysis) # Pass 1 analysis
With Any Provider (Custom Function)
BODHI works with any function that takes messages and returns a string:
from bodhi import BODHI
def my_chat(messages):
"""Your custom LLM call - just return a string."""
# Call your API, local model, whatever
return "response text"
bodhi = BODHI(my_chat)
response = bodhi.complete("I have chest pain")
Direct from OpenAI Client
from bodhi import BODHI
from openai import OpenAI
client = OpenAI()
bodhi = BODHI.from_openai(client, model="gpt-4o-mini")
response = bodhi.complete("I have chest pain")
How It Works
BODHI uses a two-pass prompting strategy:
Pass 1: Analysis
Input: User prompt
Output: Structured reflection containing:
- WHAT I THINK (assessment)
- WHAT I'M UNSURE ABOUT (uncertainties)
- WHAT I NEED TO KNOW (questions)
- RED FLAGS (safety concerns)
- SAFE ADVICE (confident recommendations)
Pass 2: Response
Input: Original prompt + Pass 1 analysis
Output: Natural response that:
- ASKS identified questions
- EXPRESSES identified uncertainties
- INCLUDES safety warnings
- PROVIDES safe recommendations
Why It Works
| Aspect | Baseline | BODHI |
|---|---|---|
| Uncertainty | Often overconfident | Appropriately humble |
| Missing info | Makes assumptions | Asks clarifying questions |
| Safety | May miss red flags | Explicitly considers red flags |
| Recommendations | Generic advice | Contextually appropriate advice |
Configuration
Custom Prompts
from bodhi import BODHI, BODHIConfig
config = BODHIConfig(
analysis_template="Analyze this: {input}",
response_template="Respond to: {input}\nUsing analysis: {analysis}",
domain="general" # or "medical" (default)
)
bodhi = BODHI(chat, config=config)
Single-Pass Mode
# For comparison or speed
response = bodhi.complete("prompt", two_pass=False)
Analysis Only
# Debug or inspect the analysis
analysis = bodhi.analyze("I have chest pain")
print(analysis)
API Reference
BODHI
Main class for BODHI functionality.
BODHI(
chat_function: ChatFunction, # Any callable: messages -> str
config: Optional[BODHIConfig] = None
)
Methods:
complete(prompt, two_pass=True)- Generate response with BODHI enhancementanalyze(prompt)- Run only Pass 1 (analysis)from_openai(client, model)- Create from OpenAI client (class method)
BODHIResponse
Response object returned by complete().
@dataclass
class BODHIResponse:
content: str # Final response text
analysis: str # Pass 1 analysis
metadata: dict # Timing, domain, etc.
BODHIConfig
Configuration for BODHI behavior.
@dataclass
class BODHIConfig:
analysis_template: Optional[str] = None # Custom Pass 1 prompt
response_template: Optional[str] = None # Custom Pass 2 prompt
domain: str = "medical" # "medical" or "general"
Provider Adapters
OpenAI
from bodhi.providers import OpenAIChat
chat = OpenAIChat(
api_key="sk-...", # Or use OPENAI_API_KEY env var
model="gpt-4o-mini",
temperature=0.7,
max_tokens=None
)
Custom Provider
Implement the ChatFunction protocol:
from typing import List, Dict
def my_chat(messages: List[Dict[str, str]]) -> str:
# Your implementation
return "response"
# Or as a class
class MyChat:
def __call__(self, messages: List[Dict[str, str]]) -> str:
return "response"
Citation
If you use BODHI in your research, please cite:
@article{cajas2026beyond,
title={Beyond overconfidence: Embedding curiosity and humility for ethical medical AI},
author={Cajas Ordóñez, Sebastián Andrés and Castro, Rowell and Celi, Leo Anthony and Delos Reyes, Roben and Engelmann, Justin and Ercole, Ari and Hilel, Almog and Kalla, Mahima and Kinyera, Leo and Lange, Maximin and others},
journal={PLOS Digital Health},
volume={5},
number={1},
pages={e0001013},
year={2026},
publisher={Public Library of Science San Francisco, CA USA}
}
@article{ordonez2025humility,
title={Humility and curiosity in human--AI systems for health care},
author={Ordoñez, Sebastián Andrés Cajas and Lange, Maximin and Lunde, Torleif Markussen and Meni, Mackenzie J and Premo, Anna E},
journal={The Lancet},
volume={406},
number={10505},
pages={804--805},
year={2025},
publisher={Elsevier}
}
License
CC BY-NC-SA 4.0 - See LICENSE for details.
Contributing
Contributions welcome! Please read the contributing guidelines and submit PRs.
Links
Project details
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 bodhi_llm-0.1.0.tar.gz.
File metadata
- Download URL: bodhi_llm-0.1.0.tar.gz
- Upload date:
- Size: 12.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a3492915062b07e16278e174fcf34c41d814b5e22e9e1278ca387d5a73b4c0d8
|
|
| MD5 |
679abeafcc7511b7ec1cf2d78671a044
|
|
| BLAKE2b-256 |
ba4b87da003766135e4200018fa9c9a461478e243588852949cfff18cdafc62f
|
File details
Details for the file bodhi_llm-0.1.0-py3-none-any.whl.
File metadata
- Download URL: bodhi_llm-0.1.0-py3-none-any.whl
- Upload date:
- Size: 12.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2ebd0cecc4f65300c1a13d128fe84c3cfad51e51ebd940685f55a0f69748bc16
|
|
| MD5 |
a8f2b680205860ccf4478c6469b344be
|
|
| BLAKE2b-256 |
16f9275500eb76181ed2010b486b3334bc71d2185a4829876eca095083491ce2
|