Skip to main content

LIMEN-AI (Łukasiewicz Interpretable Markov Engine for Neuralized AI)

PyPI version License Python Version

LIMEN-AI is a neurosymbolic library for building transparent, auditable AI applications. It combines Large Language Models (LLMs) with Łukasiewicz fuzzy logic and Energy-Based Models (EBM) to create systems that:

  • Extract structured knowledge from unstructured text
  • Perform probabilistic logical reasoning with fuzzy truth degrees
  • Learn new rules inductively from examples
  • Generate natural language explanations traceable to logical inference
  • Support EU AI Act compliance requirements (Articles 13, 14, 15)
  • Compatible with Ollama, OpenAI, Gemini, Claude, and DeepSeek

Core Use Case: Transform legal documents, policies, or domain texts into queryable knowledge bases with built-in explainability.


📦 Installation

pip install limen-ai
# Recommended for LLM features:
pip install requests python-dotenv

🚀 Quick Start (5 Lines)

from limen import LimenClient

# Initialize with local Ollama
client = LimenClient(model_name="ollama/gpt-oss:20b")

# Extract and query
proposal = client.extract("TechCorp is provider. Client is GlobalRetail.")
client.add_knowledge(proposal)
answer = client.ask("Who is provider?")
print(answer.natural_language)  # "TechCorp is provider."

🛠️ Step-by-Step Guide: Build Your First Application

1. Set Up Environment Variables

Create a .env file in your project directory:

# Choose ONE provider (uncomment relevant section)

# Option A: Local Ollama (Free, good for development)
OLLAMA_BASE_URL=http://localhost:11434/v1

# Option B: OpenAI (Production - best quality)
OPENAI_API_KEY=sk-your-openai-key-here

# Option C: Anthropic Claude (Production - best reasoning)
ANTHROPIC_API_KEY=your-anthropic-key-here

# Option D: Google Gemini (Production - good for long docs)
GEMINI_API_KEY=your-gemini-key-here

# Option E: DeepSeek (Budget-friendly)
DEEPSEEK_API_KEY=your-deepseek-key-here

2. Install and Configure Ollama (Local LLM)

For development without API costs, use Ollama:

# 1. Install Ollama
curl -fsSL https://ollama.com/install.sh | sh

# 2. Pull recommended model (fits in 16GB VRAM)
ollama pull gpt-oss:20b

# 3. Start Ollama server
ollama run gpt-oss:20b

Recommended Ollama Models:

  • gpt-oss:20b - Best reasoning, JSON output (14-16GB VRAM)
  • qwen2.5:32b - Best for reasoning (16GB VRAM)
  • qwen2.5:14b - Good balance (8GB VRAM)

3. Initialize LIMEN-AI Client

import os
from pathlib import Path
from dotenv import load_dotenv
from limen import LimenClient

load_dotenv()

# Initialize client (choose your provider)
client = LimenClient(
    model_name="ollama/gpt-oss:20b",  # Local Ollama
    # model_name="openai/gpt-4o-mini",  # OpenAI
    # model_name="claude/claude-3-5-sonnet-20241022",  # Anthropic
    # model_name="gemini/gemini-1.5-pro",  # Google
    # model_name="deepseek/deepseek-chat",  # DeepSeek
    base_url=os.getenv("OLLAMA_BASE_URL"),  # For Ollama only
    enable_auto_induction=True,  # Enable rule learning
    use_neurosymbolic_ilp=True    # Use LLM-guided ILP
)

4. Extract Knowledge from Document

# Load your document
contract_path = Path("your_contract.txt")
contract_text = contract_path.read_text(encoding="utf-8")

# Extract structured knowledge
proposal = client.extract(contract_text)

# Review what was extracted
print(proposal.to_markdown())

Expected Output:

## 1. Schema Extensions (New Predicates)
- **legalParty**(entity, role): Links entity to its legal role
- **effectiveDate**(date): Specifies effective date of agreement
- **paymentAmount**(amount, currency): Payment details

## 2. Fact Grounding (Extracted from Context)
| Predicate | Arguments | Confidence | Source |
| :--- | :--- | :--- | :--- |
| legalParty | TechCorp, Provider | 0.99 | Sentence 1 |
| legalParty | GlobalRetail, Client | 0.99 | Sentence 2 |

5. Commit Knowledge to Knowledge Base

# After human verification of proposal, commit to KB
result = client.add_knowledge(proposal)

print(f"Added {len(result.facts_added)} facts to KB")

6. Query Your Knowledge Base

# Natural language query
answer = client.ask("Who is the service provider?")

# Get results
print(f"Answer: {answer.natural_language}")

# Access structured inference results
for result in answer.answers:
    predicate = result['predicate']
    args = result['args']
    truth_degree = result['value']  # Fuzzy truth [0, 1]
    print(f"{predicate}({args}) = {truth_degree:.4f}")

# View logical trace (reasoning steps)
for step in answer.logical_trace:
    print(step)

7. Save and Restore Knowledge Base

# Save complete state (schema, facts, formulas, rules)
client.save_state("my_knowledge_base.json")

# Later, restore without re-extracting
client2 = LimenClient(model_name="ollama/gpt-oss:20b")
client2.load_state("my_knowledge_base.json")

# Now query
answer = client2.ask("What is the monthly fee?")

🔧 Advanced Usage

Direct Predicate Queries (For Local Models)

If using Ollama where natural language queries sometimes fail, query the KB directly:

# After extraction and add_knowledge()

# Method 1: Iterate over all high-confidence facts
for atom, confidence in client.pipeline.assignment.values.items():
    if confidence > 0.8 and atom.predicate.name == "legalParty":
        entity = atom.arguments[0].name
        role = atom.arguments[1].name
        print(f"{entity} is {role} (confidence: {confidence:.2f})")

# Method 2: Query specific predicate
from limen.core import Atom

pred = client.pipeline.kb.get_predicate("legalParty")
provider = client.pipeline.kb.get_constant("TechCorp")
client_role = client.pipeline.kb.get_constant("Provider")
atom = Atom(pred, (provider, client_role))

truth_degree = client.pipeline.assignment.get(atom)
print(f"TechCorp is Provider: {truth_degree:.2f}")

Benefits:

  • ✅ Deterministic results (no LLM query translation)
  • ✅ Lower latency (no additional LLM calls)
  • ✅ Reliable (works with any model quality)

Manual Fact Addition (Fill LLM Gaps)

# If LLM missed critical facts, add them manually
client.set_fact("terminationNotice", ["30 days"], 1.0)
client.set_fact("governingLaw", ["California"], 1.0)
client.set_fact("monthlyFee", [15000, "USD"], 1.0)

Inductive Rule Learning

# Provide labeled examples to teach the system rules
labels = {
    "legalParty": {
        "pos": [("TechCorp", "Provider"), ("GlobalRetail", "Client")],
        "neg": [("TechCorp", "Client"), ("GlobalRetail", "Provider")]
    }
}

# Trigger inductive learning
client.feedback(labels)

# Check learned rules
if client.pipeline.kb.induced_clauses:
    print("Learned rules:")
    for clause in client.pipeline.kb.induced_clauses:
        print(f"  IF {', '.join(clause.body)} THEN {clause.head} (weight: {clause.weight:.2f})")

Human Oversight (Veto Power)

# Override incorrect LLM extraction (Article 14(4) compliance)
client.veto("incorrectPredicate", ["arg1", "arg2"])

# This sets truth degree to 0.0 and adds a high-weight NOT formula
# Future inference will respect this override

🤖 LLM Provider Configuration

Provider Model Extraction Query Translation Best For Cost
Ollama gpt-oss:20b ⭐⭐⭐⭐ ⭐⭐ Development Free
Ollama qwen2.5:32b ⭐⭐⭐⭐⭐ ⭐⭐⭐ Best local Free
OpenAI gpt-4o-mini ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ Production $$$
OpenAI gpt-4o ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐⭐ Production $$$$
Anthropic claude-3.5-sonnet ⭐⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐⭐ Complex $$$
Google gemini-1.5-pro ⭐⭐⭐⭐ ⭐⭐⭐ Long docs $$
DeepSeek deepseek-chat ⭐⭐⭐ ⭐⭐⭐ Budget $

Key Observations:

  • Ollama: Good for development, but query translation varies between runs
  • GPT-4/Claude: Recommended for production - high quality extraction and querying
  • Workaround for Ollama: Use direct predicate queries instead of natural language

Ollama Configuration

client = LimenClient(
    model_name="ollama/gpt-oss:20b",
    base_url=os.getenv("OLLAMA_BASE_URL", "http://localhost:11434/v1")
)

Installation:

ollama pull gpt-oss:20b  # 14-16GB VRAM
ollama run gpt-oss:20b

OpenAI Configuration

client = LimenClient(
    model_name="openai/gpt-4o-mini",
    api_key=os.getenv("OPENAI_API_KEY")
)

Anthropic Claude Configuration

client = LimenClient(
    model_name="claude/claude-3-5-sonnet-20241022",
    api_key=os.getenv("ANTHROPIC_API_KEY")
)

Google Gemini Configuration

client = LimenClient(
    model_name="gemini/gemini-1.5-pro",
    api_key=os.getenv("GEMINI_API_KEY")
)

DeepSeek Configuration

client = LimenClient(
    model_name="deepseek/deepseek-chat",
    api_key=os.getenv("DEEPSEEK_API_KEY")
)

📊 Understanding Results

LIMEN-AI returns a StructuredAnswer with multiple components:

answer = client.ask("Who is the provider?")

# Natural language response (LLM-generated)
print(answer.natural_language)  # "TechCorp is the provider."

# Structured inference results (from sampling)
for result in answer.answers:
    predicate = result['predicate']
    args = result['args']
    truth_degree = result['value']  # Fuzzy truth [0, 1]
    print(f"{predicate}({args}) = {truth_degree:.4f}")

# Logical trace (reasoning steps)
for step in answer.logical_trace:
    print(step)

Key Insight: LIMEN-AI performs probabilistic inference using importance sampling. Truth degrees represent expected value under induced distribution, not simple lookup values.


📈 Domain-Specific Usage Patterns

# Extract legal entities, obligations, terms
client.extract(contract_text)

# Query for compliance, obligations, parties
answer = client.ask("What are the termination conditions?")
answer = client.ask("Who is liable for breach?")
answer = client.ask("What is the governing law?")

Cybersecurity Domain (Incidents, Controls)

# Extract security concepts, threats, controls
client.extract(security_policy_text)

# Query for incident response, controls, risks
answer = client.ask("What is the incident response time?")
answer = client.ask("What encryption is required?")
answer = client.ask("Which controls mitigate this threat?")

Financial Domain (Risk, Compliance)

# Extract risk factors, controls, metrics
client.extract(risk_framework_text)

# Query for compliance status, risk ratings, controls
answer = client.ask("What is the overall risk rating?")
answer = client.ask("Which controls are in place for AML?")
answer = client.ask("Is PCI-DSS compliance met?")

Key: LIMEN-AI works across any domain. Just provide domain-specific text and ask questions in that domain.


❓ Troubleshooting & FAQ

Q: I get a ConnectionError when using Ollama. A: Ensure Ollama is running: ollama run <model>. Check base_url is correct (usually http://localhost:11434/v1).

Q: Queries return "The fact is not supported" even though I see data in extraction. A: This is a query translation issue. The LLM failed to map your natural language question to the correct predicates.

  • Solution 1: Use a better model (GPT-4, Claude) - recommended for production
  • Solution 2: Query predicates directly instead of natural language (see "Direct Predicate Queries" section)

Q: The extraction is missing some facts. A: Small local models have extraction limitations.

  • Solution 1: Use GPT-4, Claude, or Gemini for complete extraction
  • Solution 2: Manually add missing facts with client.set_fact("predicate", ["arg1", "arg2"], 1.0)

Q: How do I save my Knowledge Base? A: Use client.save_state("my_kb.json") to save complete pipeline state:

  • Schema (predicates with descriptions)
  • Facts (ground truth assignments)
  • Formulas (weighted rules)
  • Induced clauses (learned rules)

Later, restore with client.load_state("my_kb.json").

Q: What's the difference between save_state() and save_knowledge_base()? A: save_state() (JSON) saves everything including facts and learned rules. save_knowledge_base() (SQLite) only saves KB structure (predicates/formulas) without facts. Recommendation: Always use save_state() for complete persistence.


🧪 Scientific Validation

LIMEN-AI is built on rigorous mathematical foundations:

Łukasiewicz Logic

  • T-norm: min(a ⊕ b, 1 - a ⊖ b)
  • Implication: a → b = 1 - a + b
  • Conjunction: a ⊙ b = min(a, b)

Energy-Based Models

  • Probability distribution: P(X) = (1/Z) * exp(E(X))
  • Inference via sampling (Importance Sampling, Langevin MCMC)
  • Learning via gradient-based optimization

Neurosymbolic Integration

  • LLM extracts schema and facts from natural language
  • Probabilistic logic engine performs reasoning
  • Inductive Logic Programming learns rules from examples

No Experimental Data: All examples in documentation use either:

  • Hand-calculable pedagogical examples (clearly labeled as such)
  • Real document processing (showing extraction and inference on actual texts)

📝 Changelog

0.3.5

  • LLM client robustness: OpenAIClient now enforces a configurable per-request timeout (timeout= argument or the LIMEN_LLM_TIMEOUT environment variable, default 180 s). A single stuck generation can no longer block a batch indefinitely, which previously caused long extraction/evaluation runs to hang.

0.3.4

  • Negation-aware fact extraction and deterministic fact verification in the ingestion pipeline; human-readable rule rendering.

📄 License

LIMEN-AI is licensed under the AGPL-3.0. See LICENSE file for details.


🤝 Contributing

We welcome contributions! Please see our GitHub repository.


Built with 🤖 for building trustworthy AI.

Metadata

Release files for limen-ai 0.3.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for limen-ai 0.3.5
File Size Uploaded Provenance
limen_ai-0.3.5.tar.gz 80.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for limen-ai 0.3.5
File Interpreter ABI Platform
limen_ai-0.3.5-py3-none-any.whl Python 3 none any Details

Total release size: 166.7 kB

Release files / limen_ai-0.3.5.tar.gz

Download URL limen_ai-0.3.5.tar.gz
Size 80.6 kB
Tags Source
SHA-256 checksum
How to use checksums
c35bb5956de0a53f866b42a0464ade28e8db22dc8c5ba11d2c3a74807262fa96
BLAKE2b-256 checksum
How to use checksums
1ad17e1d75dbc37b58204c63fc67550f96d873bd5dfd0c5112861b0fd0951533
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release files / limen_ai-0.3.5-py3-none-any.whl

Download URL limen_ai-0.3.5-py3-none-any.whl
Size 86.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1d6cc4d7adc692177cddb67ca6de210c56c9138bda94c2226424eb47fae90bd2
BLAKE2b-256 checksum
How to use checksums
c4653e647facb3b9f3af2d1359a87b0531c82be9ef7192ec76926cf2031cbe1e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Security for limen-ai 0.3.5

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page