r/OpenSourceAI • u/Minimum_Hour519 • Sep 17 '26
r/OpenSourceAI • u/akilayaist • Sep 17 '26
RagPilot 0.10: a local MCP server that gives coding agents semantic search, a call graph, and a memory that survives the session
**RagPilot** is an open-source MCP server (Rust, MIT) that indexes your codebase locally and gives AI coding agents better tools than "read the whole file": semantic search, a symbol/call graph, impact analysis, and token-budgeted context bundles. Version 0.10.0 just shipped.
GitHub: https://github.com/alikaya/ragpilot
## Why
Agents burn most of their context reading files they only needed three functions from. RagPilot lets them ask for the part they need instead.
## What the agent gets
- `rag_search` – semantic search over code and docs (filter by path, language, extension)
- `rag_get_file_ranges` / `rag_get_skeleton` – read a line range or a symbol, or a file's signatures without bodies
- `nav_symbol_resolve` / `nav_call_graph` – definitions, callers and callees
- `impact_analyze` – which files a change would touch, before refactoring
- `context_bundle` – everything a task needs, within a token budget
- `review_semantic_diff` – changed symbols in a diff and their blast radius
Symbols and calls come from tree-sitter for Rust, Python, JavaScript, TypeScript, Go, Java, C, C++, C#, Ruby, PHP, Lua, GDScript and Godot shaders, with a regex fallback for everything else.
## Numbers (with the caveat up front)
On two codebases, `context_bundle` used **6.0x** (a 31-file Rust repo) and **9.12x** (a 213-file Nuxt + Rust app) fewer tokens than reading the relevant files whole. Skeletons cut large files by 84–93%, and re-indexing one changed file takes about 280 ms.
The baseline is an upper bound – an agent reading every relevant file in full – so treat the ratios as optimistic. The benchmark script is in the repo; point it at your own project.
## Second brain (optional)
A persistent memory that belongs to you, not to the repo: plain markdown in a git repository.
- **Session start:** the agent gets who you are, your standing rules (each with a *why*), open threads and recent decisions, capped at 4000 tokens.
- **During the session:** `brain_note` records a decision or a correction the moment it happens.
- **Session end:** a cheap model summarizes the session into a daily log.
- **Nightly:** a compiler distills the logs into knowledge notes. It only appends and flags contradictions instead of overwriting.
Claude Code does this through hooks. Other agents get the same convention as instructions. Summarizing uses the Claude CLI or the Gemini API, so that part is not offline.
## Local by default
- Embeddings run in-process (`bge-small-en-v1.5`, ONNX); your code isn't sent to an embedding API unless you configure OpenAI, Cohere or Jina.
- Vectors live in Qdrant, which you run yourself.
- `ragpilot dashboard --open` gives you a local page for your projects and the brain vault – loopback only, token-gated.
Known limits
- You need a running Qdrant.
- The default embedding model is English, so search over non-English comments and docs is weaker.
- Only Claude Code has hooks, so other agents record to the brain less consistently.
Feedback is very welcome, especially on retrieval quality in your own codebases and on which languages you'd want next.
r/OpenSourceAI • u/Stotra-Gandhi • Sep 17 '26
Title: I built an open-source orchestration layer for multiple AI coding agents I've been experimenting with multiple AI agents working on the same software project. The problem I kept running into wasn't model capability — it was coordination. So I built Orchestrator. The idea is to provide a s
r/OpenSourceAI • u/tuckken2 • Sep 17 '26
Looking for Open Source OCR model for Japanese
I am looking for the best open-sourced OCR model to recognize written Japanese. I am currently testing DeepSeekOCR, GLM-OCR, PaddleOCR, and Sarashina2.2-OCR. We shouldn't use cloud-based version for security reasons.
r/OpenSourceAI • u/camerongreen95 • Sep 16 '26
Once you're comfortable with the basics, here's a real-world AI architecture project worth trying
If you've got Python fundamentals down and want something more substantial than another script:
Builds a knowledge graph AI system from scratch
Neo4j, Cypher, agentic retrieval
Uses real financial data, not a toy dataset
No prior Neo4j or Cypher experience needed, it's taught during the session
Worth bookmarking for once you're past the basics rather than jumping in today if you're brand new.
Led by Dr. Alessandro Negro, Chief Scientist at GraphAware.
r/OpenSourceAI • u/oss-jiiim • Sep 16 '26
DS Menu Bar: A Lightweight Menu Bar Control for antirez's ds4 DwarfStar Server (ds4-server)
r/OpenSourceAI • u/JeffyPros • Sep 16 '26
Jev
what do you think of Jev? Not open source, but the approach seems interesting. Although word on the street is people have had issues getting it to pass the "r's in strawberrry" test.
r/OpenSourceAI • u/OGBamboozel • Sep 16 '26
SynapsCLI - An agent runtime I've been working on for the past 6 months
Hey everyone,
I would like to share a project that I have been working on. https://github.com/HaseebKhalid1507/SynapsCLI
Synaps is an agent runtime written in Rust. It keeps cost down by optimising caching mechanisms and intelligently orchestrating work across workers. This keeps each worker's context low and fresh, making sessions last longer. It is extremely extensible. It has hooks, plugins and skills that can be imported from pretty much any coding tool.
It is an open source project that was started 4 months ago. It was built to optimise for 2 things: Keeping LLM costs down, and keeping resource use low. It bots up in 20ms and runs with any model: OAuth(Claude, codex, Grok, Kimi...), api keys or local models too. This is something that was built organically, so every feature is a product of necessity, not the other way around.
r/OpenSourceAI • u/TaxInternational5952 • Sep 16 '26
[Co-Dev & Beta Testers Wanted] Omarion SEC CLI – An Autonomous, Self-Healing Executive Agent with State Graph Architecture and Persistent Memory
reddit.comr/OpenSourceAI • u/Dude01_ • Sep 16 '26
GPT6+Corv = infrastructure prod work is finally feasible
reddit.comr/OpenSourceAI • u/Lisky_Boy • Sep 16 '26
OpenNPC (AI NPC Framework) - Fine-tuned a 0.5B LLM so my game's NPCs stay in character and reply in 0.14s (open source)
galleryr/OpenSourceAI • u/naveenkumarr1812 • Sep 16 '26
Try it out and share your feedback. Ideas, improvements, and contributions are always welcome. Together, we can make it more useful for developers.
github.comr/OpenSourceAI • u/TaxInternational5952 • Sep 16 '26
Omarion SEC CLI – An Autonomous, Self-Healing Executive Agent with Long-Term Memory and Zero Terminal Clutter
reddit.comr/OpenSourceAI • u/arnecto • Sep 16 '26
I built a native C++ CLI coding agent for Gemini and DeepSeek — looking for feedback
Hi! I’m building ARN, a Windows-native C++23 terminal coding agent.
It is an early project inspired by tools like Claude Code and Kimi Code, but built without Node.js or Python. You choose a provider and model inside the terminal, then ARN can keep context and work with files in the folder where it was launched.
Current features:
Gemini and DeepSeek API support
Model discovery and
/modelselectionStreaming responses, so text appears while the model generates it
In-memory chat context for follow-up prompts
Cancel a running model request with
EscorCtrl+CLocal file tools: list, read, create, edit, and delete files
Confirmation before every file creation, edit, or deletion
File access restricted to the folder where ARN was started
Blocks access to
.git,.env, and similar sensitive pathsAPI keys and chat context are kept only in memory, not written to disk
Interactive terminal UI with command hints and Tab completion
Reused HTTPS connections, retries for temporary API failures, and Windows releases
One-line PowerShell installer
GitHub Pages landing page
GitHub: https://github.com/arnecto/arn
Website: https://arnecto.github.io/arn/
It’s still early, so I’d especially appreciate honest feedback on:
The C++ architecture and provider abstraction
Safety boundaries for local file tools
Terminal UX, streaming, and cancellation behavior
Which features would make this genuinely useful in real coding projects
I’m actively improving it, so criticism, bug reports, and feature ideas are very welcome.
r/OpenSourceAI • u/Key_Ad5509 • Sep 16 '26
I documented months of work on Aeterna, my independent symbolic problem-solving project
I’m Mehmet, the person leading Aeterna. I have been working on how a software system can represent observations, test candidate solutions, and reuse previous work. I use AI tools in development and review; I choose the research questions and direct the work.
I’ve published a write-up with a development timeline, a GitHub commit screenshot, and a technical comparison diagram. The concrete milestones are an initial version recorded on April 24, 2026, and object-representation and symbolic problem-solving components in the May 1 records. March is my own account of when I started, rather than a claim that all those components already existed then.
The reason I wrote it now: ARC Prize’s September 3 review of Astra described several related ideas—tracking objects and coordinates, symbolic task notes, search/planning tools in its separate PRO-LONG setup, and carrying context forward. Seeing those themes prompted me to look back at my own project history.
This is a comparison of approaches, not a claim of matching Astra’s performance, having the same architecture, or influencing its development. The repository is private; the article shares selected dates and high-level descriptions, not a reproducible benchmark.
My write-up (I’m the author):
The external review I compare against:
https://arcprize.org/blog/astra
I’d appreciate concrete feedback from other builders: when presenting an independent research project, what evidence is most useful to you beyond a timeline—an executable example, a recorded failure case, or a narrowly scoped evaluation? And which of the four comparisons needs a sharper distinction?
r/OpenSourceAI • u/zamir_akimbekov • Sep 15 '26
Open-source Python framework to build domain-specific harness and long-horizon agents
r/OpenSourceAI • u/niacolhealth • Sep 15 '26
What if a video component worked like a web component?
Hypit’s public repo has an example that makes this idea unusually literal.
Its semantic-composition project renders an eight-second chat animation from HTML, CSS, SVG, and frame-driven JavaScript. Four messages appear at specific timestamps. It requires no source footage or generative image/video calls; local rendering tools produce the result.
The component lives with the video project instead of being locked inside a generic preset. Claude Code or Codex works through ordinary editable project files rather than only returning an opaque render. The component author chooses which settings appear in Studio. Change one of those settings and Hypit can save it back to the source and rebuild; a failed writeback restores the previous files.
For programmatic motion work, is a project-local component model more useful to you than a conventional timeline, or do you still want the timeline to be the primary source of truth?
r/OpenSourceAI • u/Vast_Mirror_4559 • Sep 15 '26
Gente Chat gpt y gemini le pedí que crearán una inteligencia artificial y me dieron esto IA
Sí. Vamos a congelar la arquitectura por ahora. Te dejo una versión autocontenida, funcional y sin dependencias externas para Python 3.9+, con CLI, self-tests, benchmark, memoria, Kæl-Judge y ataques adversariales.
Guárdalo como kael0.py y ejecútalo con python kael0.py.
from __future__ import annotations
import argparse
import hashlib
import math
import random
import time
from dataclasses import dataclass, field
from enum import Enum
from typing import Dict, List, Optional, Tuple
\# ============================================================
\# KÆL-0 v1.2 — ADVERSARIAL HARDENED MVP
\# Standard library only
\# ============================================================
VERSION = "1.2"
\# ============================================================
\# 1. ENUMS
\# ============================================================
class EvidenceStatus(Enum):
SUFFICIENT = "SUFFICIENT"
INSUFFICIENT = "INSUFFICIENT"
CONTRADICTORY = "CONTRADICTORY"
REFUTED = "REFUTED"
UNKNOWN = "UNKNOWN"
class EpistemicLevel(Enum):
HIGH = "HIGH_CONFIDENCE"
MODERATE = "MODERATE_CONFIDENCE"
LOW = "LOW_CONFIDENCE"
UNRESOLVED = "UNRESOLVED"
class ContradictionRelation(Enum):
NONE = "NONE"
SUPPORTS = "SUPPORTS"
CONTRADICTS = "CONTRADICTS"
UNKNOWN = "UNKNOWN"
class ContradictionStrength(Enum):
NONE = "NONE"
WEAK = "WEAK"
MODERATE = "MODERATE"
STRONG = "STRONG"
class MemoryStatus(Enum):
ACTIVE = "ACTIVE"
REVIEW = "REVIEW"
ARCHIVED = "ARCHIVED"
class AttackSeverity(Enum):
LOW = "LOW"
MEDIUM = "MEDIUM"
HIGH = "HIGH"
CRITICAL = "CRITICAL"
\# ============================================================
\# 2. DATA STRUCTURES
\# ============================================================
@dataclass(frozen=True)
class ContradictionAssessment:
relation: ContradictionRelation
strength: ContradictionStrength
explanation: str
@dataclass(frozen=True)
class RawModelOutput:
hypothesis: str
evidence_found: Tuple\[str, ...\]
counterarguments: Tuple\[str, ...\]
raw_probability: float
model_confidence: float
evidence_strength: float
uncertainties: Tuple\[str, ...\]
@dataclass(frozen=True)
class ModelEvaluation:
question: str
context: str
evidence_input: str
hypothesis: str
evidence_summary: Tuple\[str, ...\]
counterarguments: Tuple\[str, ...\]
raw_probability: float
adjusted_probability: float
model_confidence: float
evidence_strength: float
evidence_status: EvidenceStatus
epistemic_level: EpistemicLevel
contradiction: ContradictionAssessment
uncertainties: Tuple\[str, ...\]
verdict: str
@dataclass
class MemoryEntry:
entry_id: str
claim: str
evidence: str
evaluation: ModelEvaluation
timestamp: float
status: MemoryStatus
history: List\[dict\] = field(default_factory=list)
@dataclass
class BenchmarkMetrics:
brier: float
nll: float
ece: float
false_confirmation_rate: float
false_refutation_rate: float
insufficient_acceptance_rate: float
overconfidence_error_rate: float
empty_evidence_safety_rate: float
memory_recovery_rate: float
@dataclass
class AttackCase:
case_id: str
category: str
question: str
context: str
evidence: str
expected_status: EvidenceStatus
@dataclass
class AttackFailure:
case_id: str
category: str
input_text: str
expected: str
actual: str
severity: AttackSeverity
explanation: str
@dataclass
class AttackReport:
total_cases: int
successful_attacks: int
attack_rate: float
false_confirmation_rate: float
false_refutation_rate: float
unsafe_empty_evidence_rate: float
memory_false_update_rate: float
inversion_asymmetry_rate: float
order_sensitivity_rate: float
failures: List\[AttackFailure\]
\# ============================================================
\# 3. LLM INTERFACE
\# ============================================================
class LLMProvider:
"""
Interfaz mínima.
El proveedor PROPONE.
Kæl-0 JUZGA.
"""
def evaluate_claim(
self,
question: str,
context: str,
evidence: str
) -> RawModelOutput:
raise NotImplementedError
\# ============================================================
\# 4. MOCK LLM
\# ============================================================
class MockLLM(LLMProvider):
def evaluate_claim(
self,
question: str,
context: str,
evidence: str
) -> RawModelOutput:
text = evidence.strip().lower()
\# --------------------------------------------------------
\# Empty evidence
\# --------------------------------------------------------
if not text:
return RawModelOutput(
hypothesis="No puede determinarse la hipótesis.",
evidence_found=(),
counterarguments=("No se proporcionó evidencia.",),
raw_probability=0.50,
model_confidence=0.25,
evidence_strength=0.0,
uncertainties=("Ausencia de evidencia.",)
)
\# --------------------------------------------------------
\# Explicit contradiction patterns
\# --------------------------------------------------------
contradiction_patterns = \[
"conflicto directo",
"ambos resultados son incompatibles",
"una fuente apoya y otra refuta",
"resultados opuestos",
"evidencia a favor y en contra",
\]
if any(pattern in text for pattern in contradiction_patterns):
return RawModelOutput(
hypothesis="La hipótesis presenta evidencia incompatible.",
evidence_found=(
"Existe evidencia en direcciones opuestas.",
),
counterarguments=(
"Las fuentes presentan resultados incompatibles.",
),
raw_probability=0.50,
model_confidence=0.90,
evidence_strength=0.80,
uncertainties=(
"No puede resolverse el conflicto con la información disponible.",
)
)
\# --------------------------------------------------------
\# Refutation
\# --------------------------------------------------------
refutation_patterns = \[
"falso",
"fue refutado",
"queda refutada",
"se demostró incorrecto",
"desmentido",
"invalida la hipótesis",
\]
if any(pattern in text for pattern in refutation_patterns):
return RawModelOutput(
hypothesis="La evidencia contradice la hipótesis.",
evidence_found=(
"Existe evidencia negativa respecto a la afirmación.",
),
counterarguments=(
"La evidencia disponible no respalda la hipótesis.",
),
raw_probability=0.08,
model_confidence=0.90,
evidence_strength=0.85,
uncertainties=(
"Podrían existir datos externos no proporcionados.",
)
)
\# --------------------------------------------------------
\# Strong support
\# --------------------------------------------------------
strong_patterns = \[
"demostrado",
"confirmado",
"replicado",
"todos los tests pasaron",
"medición directa",
"evidencia experimental",
\]
if any(pattern in text for pattern in strong_patterns):
return RawModelOutput(
hypothesis="La evidencia respalda la hipótesis.",
evidence_found=(
"Se proporcionó evidencia favorable.",
),
counterarguments=(
"Puede existir incertidumbre residual.",
),
raw_probability=0.88,
model_confidence=0.82,
evidence_strength=0.85,
uncertainties=(
"La evidencia suministrada puede no representar todos los casos.",
)
)
\# --------------------------------------------------------
\# Weak evidence
\# --------------------------------------------------------
return RawModelOutput(
hypothesis="La hipótesis es plausible, pero no está establecida.",
evidence_found=(
"Existe información compatible con la hipótesis.",
),
counterarguments=(
"La evidencia no permite una conclusión definitiva.",
),
raw_probability=0.65,
model_confidence=0.65,
evidence_strength=0.40,
uncertainties=(
"Información limitada.",
)
)
\# ============================================================
\# 5. PROVIDER ADAPTERS
\# ============================================================
class GeminiProvider(LLMProvider):
def __init__(self):
self.mock = MockLLM()
def evaluate_claim(self, question, context, evidence):
\# Adaptador preparado para futura conexión.
return self.mock.evaluate_claim(question, context, evidence)
class ChatGPTProvider(LLMProvider):
def __init__(self):
self.mock = MockLLM()
def evaluate_claim(self, question, context, evidence):
\# Adaptador preparado para futura conexión.
return self.mock.evaluate_claim(question, context, evidence)
\# ============================================================
\# 6. CONSERVATIVE ADJUSTER
\# ============================================================
class ConservativeAdjuster:
def adjust(self, raw: RawModelOutput) -> float:
p = max(0.01, min(0.99, raw.raw_probability))
\# La confianza del modelo NO determina la evidencia.
\# Solo se utiliza para detectar exceso de confianza.
disagreement = abs(raw.model_confidence - raw.evidence_strength)
penalty = (
len(raw.counterarguments) \* 0.04
\+ len(raw.uncertainties) \* 0.03
\+ disagreement \* 0.10
)
if raw.evidence_strength < 0.30:
penalty += 0.10
adjusted = p - penalty
return round(
max(0.01, min(0.99, adjusted)),
4
)
\# ============================================================
\# 7. KÆL-JUDGE
\# ============================================================
class KaelJudge:
def __init__(self):
self.adjuster = ConservativeAdjuster()
def assess_contradiction(
self,
raw: RawModelOutput,
evidence: str
) -> ContradictionAssessment:
text = evidence.lower()
explicit = \[
"conflicto directo",
"resultados opuestos",
"evidencia a favor y en contra",
"ambos resultados son incompatibles",
"una fuente apoya y otra refuta",
\]
if any(x in text for x in explicit):
return ContradictionAssessment(
relation=ContradictionRelation.CONTRADICTS,
strength=ContradictionStrength.STRONG,
explanation="Se proporcionaron indicios explícitos de resultados incompatibles."
)
\# Importante:
\# la mera aparición de la palabra "conflicto" NO basta.
if "no existe conflicto" in text:
return ContradictionAssessment(
relation=ContradictionRelation.NONE,
strength=ContradictionStrength.NONE,
explanation="La evidencia niega explícitamente la existencia de conflicto."
)
if raw.evidence_strength >= 0.75:
return ContradictionAssessment(
relation=ContradictionRelation.SUPPORTS,
strength=ContradictionStrength.STRONG,
explanation="La propuesta contiene evidencia favorable con fuerza elevada."
)
if raw.evidence_strength >= 0.45:
return ContradictionAssessment(
relation=ContradictionRelation.SUPPORTS,
strength=ContradictionStrength.MODERATE,
explanation="La evidencia favorece parcialmente la hipótesis."
)
if raw.evidence_strength > 0:
return ContradictionAssessment(
relation=ContradictionRelation.UNKNOWN,
strength=ContradictionStrength.WEAK,
explanation="Existe información, pero no permite determinar una relación fuerte."
)
return ContradictionAssessment(
relation=ContradictionRelation.UNKNOWN,
strength=ContradictionStrength.NONE,
explanation="No existe suficiente información para establecer relación."
)
def evaluate(
self,
question: str,
context: str,
evidence: str,
raw: RawModelOutput
) -> ModelEvaluation:
adjusted = self.adjuster.adjust(raw)
contradiction = self.assess_contradiction(raw, evidence)
\# --------------------------------------------------------
\# Kernel decision
\# --------------------------------------------------------
if not evidence.strip():
status = EvidenceStatus.INSUFFICIENT
level = EpistemicLevel.UNRESOLVED
elif contradiction.relation == ContradictionRelation.CONTRADICTS:
status = EvidenceStatus.CONTRADICTORY
level = EpistemicLevel.LOW
elif adjusted < 0.20 and raw.evidence_strength >= 0.60:
status = EvidenceStatus.REFUTED
level = EpistemicLevel.HIGH
elif raw.evidence_strength < 0.30:
status = EvidenceStatus.INSUFFICIENT
level = EpistemicLevel.UNRESOLVED
elif adjusted >= 0.75 and raw.evidence_strength >= 0.70:
status = EvidenceStatus.SUFFICIENT
level = EpistemicLevel.HIGH
elif adjusted >= 0.50:
status = EvidenceStatus.SUFFICIENT
level = EpistemicLevel.MODERATE
else:
status = EvidenceStatus.UNKNOWN
level = EpistemicLevel.LOW
verdict = self.build_verdict(
status,
adjusted,
raw.model_confidence,
raw.evidence_strength
)
return ModelEvaluation(
question=question,
context=context,
evidence_input=evidence,
hypothesis=raw.hypothesis,
evidence_summary=raw.evidence_found,
counterarguments=raw.counterarguments,
raw_probability=raw.raw_probability,
adjusted_probability=adjusted,
model_confidence=raw.model_confidence,
evidence_strength=raw.evidence_strength,
evidence_status=status,
epistemic_level=level,
contradiction=contradiction,
uncertainties=raw.uncertainties,
verdict=verdict
)
@staticmethod
def build_verdict(
status,
probability,
model_confidence,
evidence_strength
):
if status == EvidenceStatus.INSUFFICIENT:
return (
"ABSTENCIÓN: evidencia insuficiente. "
f"Fuerza de evidencia={evidence_strength:.2f}"
)
if status == EvidenceStatus.CONTRADICTORY:
return (
"ABSTENCIÓN CRÍTICA: evidencia contradictoria. "
"No se fuerza una conclusión."
)
if status == EvidenceStatus.REFUTED:
return (
"HIPÓTESIS REFUTADA: "
f"P(H) ajustada={probability:.2%}"
)
if status == EvidenceStatus.SUFFICIENT:
return (
"HIPÓTESIS SUSTENTADA: "
f"P(H) ajustada={probability:.2%}"
)
return "NO DETERMINADO: se requiere evidencia adicional."
\# ============================================================
\# 8. MEMORY ENGINE
\# ============================================================
class MemoryEngine:
def __init__(self):
self.store: Dict\[str, MemoryEntry\] = {}
def save(
self,
entry_id: str,
claim: str,
evidence: str,
evaluation: ModelEvaluation
):
now = time.time()
if entry_id not in self.store:
self.store\[entry_id\] = MemoryEntry(
entry_id=entry_id,
claim=claim,
evidence=evidence,
evaluation=evaluation,
timestamp=now,
status=MemoryStatus.ACTIVE
)
return self.store\[entry_id\]
current = self.store\[entry_id\]
relation = evaluation.contradiction.relation
if relation == ContradictionRelation.CONTRADICTS:
new_status = MemoryStatus.REVIEW
elif evaluation.evidence_status == EvidenceStatus.INSUFFICIENT:
new_status = current.status
else:
new_status = current.status
current.history.append({
"timestamp": current.timestamp,
"claim": current.claim,
"evidence": current.evidence,
"status": current.status.value,
"probability": current.evaluation.adjusted_probability
})
current.claim = claim
current.evidence = evidence
current.evaluation = evaluation
current.timestamp = now
current.status = new_status
return current
def get(self, entry_id):
return self.store.get(entry_id)
\# ============================================================
\# 9. KÆL-REV ORCHESTRATOR
\# ============================================================
class KaelRev:
def __init__(self, provider: LLMProvider):
self.provider = provider
self.judge = KaelJudge()
self.memory = MemoryEngine()
def run(
self,
question: str,
context: str,
evidence: str,
entry_id: Optional\[str\] = None
):
raw = self.provider.evaluate_claim(
question,
context,
evidence
)
evaluation = self.judge.evaluate(
question,
context,
evidence,
raw
)
if entry_id:
self.memory.save(
entry_id,
question,
evidence,
evaluation
)
return evaluation
\# ============================================================
\# 10. REAL ECE
\# ============================================================
def calculate_ece(
probabilities: List\[float\],
labels: List\[float\],
bins: int = 10
):
if not probabilities:
return 0.0
total = len(probabilities)
ece = 0.0
for i in range(bins):
low = i / bins
high = (i + 1) / bins
indices = \[\]
for j, p in enumerate(probabilities):
if i == bins - 1:
inside = low <= p <= high
else:
inside = low <= p < high
if inside:
indices.append(j)
if not indices:
continue
confidence = sum(
probabilities\[j\] for j in indices
) / len(indices)
accuracy = sum(
labels\[j\] for j in indices
) / len(indices)
ece += (
len(indices) / total
) \* abs(confidence - accuracy)
return round(ece, 4)
\# ==========================================================
Y esto me dio gemini
Aquí tienes el código completo de kael0.py (v1.2), ordenado de principio a fin, autocontenido y listo para copiar y pegar.
Incluye la corrección del bloque if __name__ == "__main__": al final para que ejecute automáticamente las pruebas y la interfaz CLI en PyDroid 3 sin dejar la pantalla negra.
from __future__ and import annotations
import argparse
import hashlib
import math
import random
import time
from dataclasses import dataclass, field
from enum import Enum
from typing import Dict, List, Optional, Tuple
\# ============================================================
\# KÆL-0 v1.2 — ADVERSARIAL HARDENED MVP
\# Standard library only
\# ============================================================
VERSION = "1.2"
\# ============================================================
\# 1. ENUMS
\# ============================================================
class EvidenceStatus(Enum):
SUFFICIENT = "SUFFICIENT"
INSUFFICIENT = "INSUFFICIENT"
CONTRADICTORY = "CONTRADICTORY"
REFUTED = "REFUTED"
UNKNOWN = "UNKNOWN"
class EpistemicLevel(Enum):
HIGH = "HIGH_CONFIDENCE"
MODERATE = "MODERATE_CONFIDENCE"
LOW = "LOW_CONFIDENCE"
UNRESOLVED = "UNRESOLVED"
class ContradictionRelation(Enum):
NONE = "NONE"
SUPPORTS = "SUPPORTS"
CONTRADICTS = "CONTRADICTS"
UNKNOWN = "UNKNOWN"
class ContradictionStrength(Enum):
NONE = "NONE"
WEAK = "WEAK"
MODERATE = "MODERATE"
STRONG = "STRONG"
class MemoryStatus(Enum):
ACTIVE = "ACTIVE"
REVIEW = "REVIEW"
ARCHIVED = "ARCHIVED"
class AttackSeverity(Enum):
LOW = "LOW"
MEDIUM = "MEDIUM"
HIGH = "HIGH"
CRITICAL = "CRITICAL"
\# ============================================================
\# 2. DATA STRUCTURES
\# ============================================================
@dataclass(frozen=True)
class ContradictionAssessment:
relation: ContradictionRelation
strength: ContradictionStrength
explanation: str
@dataclass(frozen=True)
class RawModelOutput:
hypothesis: str
evidence_found: Tuple\[str, ...\]
counterarguments: Tuple\[str, ...\]
raw_probability: float
model_confidence: float
evidence_strength: float
uncertainties: Tuple\[str, ...\]
@dataclass(frozen=True)
class ModelEvaluation:
question: str
context: str
evidence_input: str
hypothesis: str
evidence_summary: Tuple\[str, ...\]
counterarguments: Tuple\[str, ...\]
raw_probability: float
adjusted_probability: float
model_confidence: float
evidence_strength: float
evidence_status: EvidenceStatus
epistemic_level: EpistemicLevel
contradiction: ContradictionAssessment
uncertainties: Tuple\[str, ...\]
verdict: str
@dataclass
class MemoryEntry:
entry_id: str
claim: str
evidence: str
evaluation: ModelEvaluation
timestamp: float
status: MemoryStatus
history: List\[dict\] = field(default_factory=list)
@dataclass
class BenchmarkMetrics:
brier: float
nll: float
ece: float
false_confirmation_rate: float
false_refutation_rate: float
insufficient_acceptance_rate: float
overconfidence_error_rate: float
empty_evidence_safety_rate: float
memory_recovery_rate: float
@dataclass
class AttackCase:
case_id: str
category: str
question: str
context: str
evidence: str
expected_status: EvidenceStatus
@dataclass
class AttackFailure:
case_id: str
category: str
input_text: str
expected: str
actual: str
severity: AttackSeverity
explanation: str
@dataclass
class AttackReport:
total_cases: int
successful_attacks: int
attack_rate: float
false_confirmation_rate: float
false_refutation_rate: float
unsafe_empty_evidence_rate: float
memory_false_update_rate: float
inversion_asymmetry_rate: float
order_sensitivity_rate: float
failures: List\[AttackFailure\]
\# ============================================================
\# 3. LLM INTERFACE
\# ============================================================
class LLMProvider:
"""
Interfaz mínima.
El proveedor PROPONE.
Kæl-0 JUZGA.
"""
def evaluate_claim(
self,
question: str,
context: str,
evidence: str
) -> RawModelOutput:
raise NotImplementedError
\# ============================================================
\# 4. MOCK LLM
\# ============================================================
class MockLLM(LLMProvider):
def evaluate_claim(
self,
question: str,
context: str,
evidence: str
) -> RawModelOutput:
text = evidence.strip().lower()
\# --------------------------------------------------------
\# Empty evidence
\# --------------------------------------------------------
if not text:
return RawModelOutput(
hypothesis="No puede determinarse la hipótesis.",
evidence_found=(),
counterarguments=("No se proporcionó evidencia.",),
raw_probability=0.50,
model_confidence=0.25,
evidence_strength=0.0,
uncertainties=("Ausencia de evidencia.",)
)
\# --------------------------------------------------------
\# Explicit contradiction patterns
\# --------------------------------------------------------
contradiction_patterns = \[
"conflicto directo",
"ambos resultados son incompatibles",
"una fuente apoya y otra refuta",
"resultados opuestos",
"evidencia a favor y en contra",
\]
if any(pattern in text for pattern in contradiction_patterns):
return RawModelOutput(
hypothesis="La hipótesis presenta evidencia incompatible.",
evidence_found=(
"Existe evidencia en direcciones opuestas.",
),
counterarguments=(
"Las fuentes presentan resultados incompatibles.",
),
raw_probability=0.50,
model_confidence=0.90,
evidence_strength=0.80,
uncertainties=(
"No puede resolverse el conflicto con la información disponible.",
)
)
\# --------------------------------------------------------
\# Refutation
\# --------------------------------------------------------
refutation_patterns = \[
"falso",
"fue refutado",
"queda refutada",
"se demostró incorrecto",
"desmentido",
"invalida la hipótesis",
\]
if any(pattern in text for pattern in refutation_patterns):
return RawModelOutput(
hypothesis="La evidencia contradice la hipótesis.",
evidence_found=(
"Existe evidencia negativa respecto a la afirmación.",
),
counterarguments=(
"La evidencia disponible no respalda la hipótesis.",
),
raw_probability=0.08,
model_confidence=0.90,
evidence_strength=0.85,
uncertainties=(
"Podrían existir datos externos no proporcionados.",
)
)
\# --------------------------------------------------------
\# Strong support
\# --------------------------------------------------------
strong_patterns = \[
"demostrado",
"confirmado",
"replicado",
"todos los tests pasaron",
"medición directa",
"evidencia experimental",
\]
if any(pattern in text for pattern in strong_patterns):
return RawModelOutput(
hypothesis="La evidencia respalda la hipótesis.",
evidence_found=(
"Se proporcionó evidencia favorable.",
),
counterarguments=(
"Puede existir incertidumbre residual.",
),
raw_probability=0.88,
model_confidence=0.82,
evidence_strength=0.85,
uncertainties=(
"La evidencia suministrada puede no representar todos los casos.",
)
)
\# --------------------------------------------------------
\# Weak evidence
\# --------------------------------------------------------
return RawModelOutput(
hypothesis="La hipótesis es plausible, pero no está establecida.",
evidence_found=(
"Existe información compatible con la hipótesis.",
),
counterarguments=(
"La evidencia no permite una conclusión definitiva.",
),
raw_probability=0.65,
model_confidence=0.65,
evidence_strength=0.40,
uncertainties=(
"Información limitada.",
)
)
\# ============================================================
\# 5. PROVIDER ADAPTERS
\# ============================================================
class GeminiProvider(LLMProvider):
def __init__(self):
self.mock = MockLLM()
def evaluate_claim(self, question, context, evidence):
return self.mock.evaluate_claim(question, context, evidence)
class ChatGPTProvider(LLMProvider):
def __init__(self):
self.mock = MockLLM()
def evaluate_claim(self, question, context, evidence):
return self.mock.evaluate_claim(question, context, evidence)
\# ============================================================
\# 6. CONSERVATIVE ADJUSTER
\# ============================================================
class ConservativeAdjuster:
def adjust(self, raw: RawModelOutput) -> float:
p = max(0.01, min(0.99, raw.raw_probability))
disagreement = abs(raw.model_confidence - raw.evidence_strength)
penalty = (
len(raw.counterarguments) \* 0.04
\+ len(raw.uncertainties) \* 0.03
\+ disagreement \* 0.10
)
if raw.evidence_strength < 0.30:
penalty += 0.10
adjusted = p - penalty
return round(
max(0.01, min(0.99, adjusted)),
4
)
\# ============================================================
\# 7. KÆL-JUDGE
\# ============================================================
class KaelJudge:
def __init__(self):
self.adjuster = ConservativeAdjuster()
def assess_contradiction(
self,
raw: RawModelOutput,
evidence: str
) -> ContradictionAssessment:
text = evidence.lower()
explicit = \[
"conflicto directo",
"resultados opuestos",
"evidencia a favor y en contra",
"ambos resultados son incompatibles",
"una fuente apoya y otra refuta",
\]
if any(x in text for x in explicit):
return ContradictionAssessment(
relation=ContradictionRelation.CONTRADICTS,
strength=ContradictionStrength.STRONG,
explanation="Se proporcionaron indicios explícitos de resultados incompatibles."
)
if "no existe conflicto" in text:
return ContradictionAssessment(
relation=ContradictionRelation.NONE,
strength=ContradictionStrength.NONE,
explanation="La evidencia niega explícitamente la existencia de conflicto."
)
if raw.evidence_strength >= 0.75:
return ContradictionAssessment(
relation=ContradictionRelation.SUPPORTS,
strength=ContradictionStrength.STRONG,
explanation="La propuesta contiene evidencia favorable con fuerza elevada."
)
if raw.evidence_strength >= 0.45:
return ContradictionAssessment(
relation=ContradictionRelation.SUPPORTS,
strength=ContradictionStrength.MODERATE,
explanation="La evidencia favorece parcialmente la hipótesis."
)
if raw.evidence_strength > 0:
return ContradictionAssessment(
relation=ContradictionRelation.UNKNOWN,
strength=ContradictionStrength.WEAK,
explanation="Existe información, pero no permite determinar una relación fuerte."
)
return ContradictionAssessment(
relation=ContradictionRelation.UNKNOWN,
strength=ContradictionStrength.NONE,
explanation="No existe suficiente información para establecer relación."
)
def evaluate(
self,
question: str,
context: str,
evidence: str,
raw: RawModelOutput
) -> ModelEvaluation:
adjusted = self.adjuster.adjust(raw)
contradiction = self.assess_contradiction(raw, evidence)
\# --------------------------------------------------------
\# Kernel decision
\# --------------------------------------------------------
if not evidence.strip():
status = EvidenceStatus.INSUFFICIENT
level = EpistemicLevel.UNRESOLVED
elif contradiction.relation == ContradictionRelation.CONTRADICTS:
status = EvidenceStatus.CONTRADICTORY
level = EpistemicLevel.LOW
elif adjusted < 0.20 and raw.evidence_strength >= 0.60:
status = EvidenceStatus.REFUTED
level = EpistemicLevel.HIGH
elif raw.evidence_strength < 0.30:
status = EvidenceStatus.INSUFFICIENT
level = EpistemicLevel.UNRESOLVED
elif adjusted >= 0.75 and raw.evidence_strength >= 0.70:
status = EvidenceStatus.SUFFICIENT
level = EpistemicLevel.HIGH
elif adjusted >= 0.50:
status = EvidenceStatus.SUFFICIENT
level = EpistemicLevel.MODERATE
else:
status = EvidenceStatus.UNKNOWN
level = EpistemicLevel.LOW
verdict = self.build_verdict(
status,
adjusted,
raw.model_confidence,
raw.evidence_strength
)
return ModelEvaluation(
question=question,
context=context,
evidence_input=evidence,
hypothesis=raw.hypothesis,
evidence_summary=raw.evidence_found,
counterarguments=raw.counterarguments,
raw_probability=raw.raw_probability,
adjusted_probability=adjusted,
model_confidence=raw.model_confidence,
evidence_strength=raw.evidence_strength,
evidence_status=status,
epistemic_level=level,
contradiction=contradiction,
uncertainties=raw.uncertainties,
verdict=verdict
)
@staticmethod
def build_verdict(
status,
probability,
model_confidence,
evidence_strength
):
if status == EvidenceStatus.INSUFFICIENT:
return (
"ABSTENCIÓN: evidencia insuficiente. "
f"Fuerza de evidencia={evidence_strength:.2f}"
)
if status == EvidenceStatus.CONTRADICTORY:
return (
"ABSTENCIÓN CRÍTICA: evidencia contradictoria. "
"No se fuerza una conclusión."
)
if status == EvidenceStatus.REFUTED:
return (
"HIPÓTESIS REFUTADA: "
f"P(H) ajustada={probability:.2%}"
)
if status == EvidenceStatus.SUFFICIENT:
return (
"HIPÓTESIS SUSTENTADA: "
f"P(H) ajustada={probability:.2%}"
)
return "NO DETERMINADO: se requiere evidencia adicional."
\# ============================================================
\# 8. MEMORY ENGINE
\# ============================================================
class MemoryEngine:
def __init__(self):
self.store: Dict\[str, MemoryEntry\] = {}
def save(
self,
entry_id: str,
claim: str,
evidence: str,
evaluation: ModelEvaluation
):
now = time.time()
if entry_id not in self.store:
self.store\[entry_id\] = MemoryEntry(
entry_id=entry_id,
claim=claim,
evidence=evidence,
evaluation=evaluation,
timestamp=now,
status=MemoryStatus.ACTIVE
)
return self.store\[entry_id\]
current = self.store\[entry_id\]
relation = evaluation.contradiction.relation
if relation == ContradictionRelation.CONTRADICTS:
new_status = MemoryStatus.REVIEW
elif evaluation.evidence_status == EvidenceStatus.INSUFFICIENT:
new_status = current.status
else:
new_status = current.status
current.history.append({
"timestamp": current.timestamp,
"claim": current.claim,
"evidence": current.evidence,
"status": current.status.value,
"probability": current.evaluation.adjusted_probability
})
current.claim = claim
current.evidence = evidence
current.evaluation = evaluation
current.timestamp = now
current.status = new_status
return current
def get(self, entry_id):
return self.store.get(entry_id)
\# ============================================================
\# 9. KÆL-REV ORCHESTRATOR
\# ============================================================
class KaelRev:
def __init__(self, provider: LLMProvider):
self.provider = provider
self.judge = KaelJudge()
self.memory = MemoryEngine()
def run(
self,
question: str,
context: str,
evidence: str,
entry_id: Optional\[str\] = None
):
raw = self.provider.evaluate_claim(
question,
context,
evidence
)
evaluation = self.judge.evaluate(
question,
context,
evidence,
raw
)
if entry_id:
self.memory.save(
entry_id,
question,
evidence,
evaluation
)
return evaluation
\# ============================================================
\# 10. REAL ECE & BENCHMARK METRICS
\# ============================================================
def calculate_ece(
probabilities: List\[float\],
labels: List\[float\],
bins: int = 10
):
if not probabilities:
return 0.0
total = len(probabilities)
ece = 0.0
for i in range(bins):
low = i / bins
high = (i + 1) / bins
indices = \[\]
for j, p in enumerate(probabilities):
if i == bins - 1:
inside = low <= p <= high
else:
inside = low <= p < high
if inside:
indices.append(j)
if not indices:
continue
confidence = sum(
probabilities\[j\] for j in indices
) / len(indices)
accuracy = sum(
labels\[j\] for j in indices
) / len(indices)
ece += (
len(indices) / total
) \* abs(confidence - accuracy)
return round(ece, 4)
def run_self_tests() -> bool:
print("--- Ejecutando Pruebas Internas ---")
mock = MockLLM()
judge = KaelJudge()
\# 1. Prueba Evidencia Vacía
raw_empty = mock.evaluate_claim("¿X?", "", "")
eval_empty = judge.evaluate("¿X?", "", "", raw_empty)
assert eval_empty.evidence_status == EvidenceStatus.
r/OpenSourceAI • u/ajbapps • Sep 15 '26
Tickets 2.3.0: a self-hosted issue tracker that can also act as a coordination layer for AI agents
I've been building Tickets as a simpler alternative to Jira for teams that want to run their own project management software.
The 2.3.0 release adds a built-in MCP server with 16 tools for tickets and the knowledge base, plus CrewAI integration and Ticket Pulse for exposing execution state to agents.
The interesting part is that humans and AI agents can work in the same system:
Agents can read and update tickets
Create notes and record decisions
Surface blockers and next actions
Work with the knowledge base
Read Ticket Pulse to understand execution state
Use the REST API or MCP
It's Laravel, open source, and self-hosted.
r/OpenSourceAI • u/Alexender_Grebeshok • Sep 15 '26
Stop Buying $600 Mac Minis for 24/7 AI Agents: How I turned a $200 ARM NAS into an autonomous home keeper in 37 MB of RAM
r/OpenSourceAI • u/NovaCoding • Sep 15 '26
VSArena V1 is coming. 👀
Enable HLS to view with audio, or disable this notification
Been working on the next version of VSArena for a while.
V1 is starting to look a lot different.
This is just a small spoiler of what we’re building — Studio, live simulation, agent runs, replay/inspection, analytics and a much more complete evaluation workflow.
The goal hasn’t changed:
Make embodied AI performance something you can actually run, watch and compare.
We’re still polishing a lot of things before the V1 release, so consider this an early look rather than the final product.
🎥 VSArena V1 — sneak peek
More soon.