Skip to main content

Łukasiewicz Interpretable Markov Engine for Neuralized AI

Project description

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

Recommended Models by Use Case

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

Legal Domain (Contracts, Regulations)

# 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)

📄 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.

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

limen_ai-0.3.4.tar.gz (80.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

limen_ai-0.3.4-py3-none-any.whl (85.7 kB view details)

Uploaded Python 3

File details

Details for the file limen_ai-0.3.4.tar.gz.

File metadata

  • Download URL: limen_ai-0.3.4.tar.gz
  • Upload date:
  • Size: 80.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for limen_ai-0.3.4.tar.gz
Algorithm Hash digest
SHA256 36d07d3e16647bc318e61dd4c818bdafdaa67ea618ead635ba19768aa76bb007
MD5 ea349dbbc17db34b07d6afea6cc84ba4
BLAKE2b-256 ea1de353896135316d299a5e09cc9a2e5fc0db1d95665babdf25cc3b1ae64571

See more details on using hashes here.

File details

Details for the file limen_ai-0.3.4-py3-none-any.whl.

File metadata

  • Download URL: limen_ai-0.3.4-py3-none-any.whl
  • Upload date:
  • Size: 85.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for limen_ai-0.3.4-py3-none-any.whl
Algorithm Hash digest
SHA256 694acec27922604bc6cc1d4b5dbaa637e2c1a1882fadba5c66ee7a7a7edbf67a
MD5 fb523ec2f8c84ee54eae363611d76a08
BLAKE2b-256 223b6c1ec2d72a4310e0e7ea7f231e0582660d0831a97ecdaf59ff514b9e6a3b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page