Commit 2789b332 authored by Kantz's avatar Kantz
Browse files

adding comments

parent 8c1db631
# Context store base implementation.
from __future__ import annotations
import hashlib
......@@ -30,6 +32,9 @@ def _resolve_latest_path(chat_id: str) -> str | None:
return max(matches, key=os.path.getmtime)
return None
# ---
# timekeeping
# ---
def _mez_now() -> str:
return datetime.now(ZoneInfo("Europe/Berlin")).strftime("%Y-%m-%dT%H:%M:%SZ")
......@@ -43,6 +48,10 @@ def touch_sheet(sheet: dict[str, Any]) -> None:
_touch(sheet)
# ---
# setup and formatting
# ---
def get_chat_id(messages: list[dict], draft: str | None = None) -> str:
if draft:
return draft
......@@ -130,6 +139,9 @@ def format_sheet_base(sheet: dict[str, Any]) -> str:
parts.append(f"INITIALIZED:\n{get_initialized(sheet)}")
return "\n\n".join(parts)
# ---
# getter and setter
# ---
def set_chat_id(sheet: dict[str, Any], value: str) -> None:
sheet["chat_id"] = value
......
# Embedding
from __future__ import annotations
import time
......@@ -38,6 +40,8 @@ def get_embedder() -> tuple[BaseEmbeddings, bool]:
return _CACHED_EMBEDDER, False
# Warm up the embedder by initializing it and running a dummy query. This can help reduce latency for the first real query.
def warmup_embedder() -> Dict[str, Any]:
started = time.perf_counter()
embedder, cache_hit = get_embedder()
......
# Embeddings-Implementation with Factory-Pattern
from __future__ import annotations
import math
......@@ -10,7 +12,7 @@ from sentence_transformers import SentenceTransformer
# -----------------------------
# Konfigurationsmodelle (optional, aber empfohlen)
# configuration model
# -----------------------------
class EmbeddingType(str, Enum):
......@@ -44,7 +46,7 @@ class EmbeddingConfig(BaseModel):
..., description="Spezifische Konfiguration")
# -----------------------------
# Basisklasse für Embeddings
# base class for embeddings
# -----------------------------
......@@ -86,7 +88,7 @@ class BaseEmbeddings:
# -----------------------------
# Subklassen
# subclass
# -----------------------------
class OpenAILikeEmbeddings(BaseEmbeddings):
......@@ -182,7 +184,7 @@ class SentenceTransformerEmbeddings(BaseEmbeddings):
# -----------------------------
# Factory: Erzeugt die richtige Embeddings-Instanz
# Factory: creats embeddings based on config
# -----------------------------
class EmbeddingFactory:
......
# LLM client with support for multiple providers and tool use, including quota tracking and tool call logging.
import asyncio
import inspect
import json
......
# LLM-Quota-Management: tracks the dayly usage of LLM calls and tokens, enforces limits, and provides usage data for monitoring and billing purposes.
# Limits are set in .env
from __future__ import annotations
from dataclasses import dataclass
......
# decodes referneces from the _task_index.json to match sources, tasks and socratic prompts.
# There must be a easyer way to do this.
from __future__ import annotations
from typing import Dict, Iterable, Protocol, Set, Tuple
......
# Mask for Vector Store Retrieval.
# dont know why this is here?
from __future__ import annotations
from typing import List
......
# Session Store for archiving and retrieving chat sessions.
from __future__ import annotations
import json
......@@ -6,6 +8,7 @@ from collections import deque
from datetime import datetime
from threading import Lock
from typing import Any
from zoneinfo import ZoneInfo
from app.deterministic_services import context_store
......@@ -14,8 +17,8 @@ _LOG_DIR = os.path.join("logs", "chat_sessions")
_LOG_PATH = os.path.join(_LOG_DIR, "archive.jsonl")
def _utc_now() -> str:
return datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")
def _mez_now() -> str:
return datetime.now(ZoneInfo("Europe/Berlin")).strftime("%Y-%m-%dT%H:%M:%SZ")
def _extract_selected_task(sheet: dict[str, Any]) -> dict[str, str] | None:
......@@ -48,7 +51,7 @@ def archive_chat(
record = {
"chat_id": chat_id,
"saved_at": _utc_now(),
"saved_at": _mez_now(),
"orchestrator": str(orchestrator or "").strip().lower() or None,
"history": sheet.get("history", []),
"context_sheet": context_store.format_sheet(sheet),
......
# Socratic Oranisator for managing initial prompts and topic catalog.
from __future__ import annotations
from functools import lru_cache
......
......@@ -21,6 +21,10 @@ TOPIC_MAP_PATH = TASKS_DIR / "_topic_to_index_map.yaml"
TASK_ASSET_URL_PREFIX = "/api/tasks/assets"
ParentRef = tuple[int, int, int, int]
# ---
# normalizer and parser
# ---
def _normalize_parent_ref_key(value: str) -> str:
return _normalize_topic_key(value)
......@@ -113,6 +117,10 @@ def _format_parent_ref_label(ref: ParentRef) -> str:
return f"Subsection {chap}.{sec}.{sub}"
return f"Subsubsection {chap}.{sec}.{sub}.{subsub}"
# ---
# topic map loading
# ---
def load_topic_map(path: Path = TOPIC_MAP_PATH) -> dict[str, ParentRef]:
if not path.exists():
......@@ -133,6 +141,9 @@ def load_topic_map(path: Path = TOPIC_MAP_PATH) -> dict[str, ParentRef]:
mapped[key] = _normalize_parent_ref(parsed)
return mapped
# ---
# topic summaries loading
# ---
def _extract_topic_summary(text: str) -> str:
body = text.replace("\r\n", "\n").strip()
......@@ -288,6 +299,10 @@ def _format_topic_label(value: str) -> str:
return cleaned.title()
# ---
# topic catalog
# ---
def build_topic_catalog(path: Path = TOPIC_MAP_PATH) -> list[dict[str, Any]]:
topic_map = load_topic_map(path)
topic_summaries = load_topic_summaries()
......@@ -305,6 +320,10 @@ def build_topic_catalog(path: Path = TOPIC_MAP_PATH) -> list[dict[str, Any]]:
return response
# ---
# text helpers
# ---
def _match_score(query_text: str, candidate_text: str) -> int:
query_tokens = _tokenize(query_text)
if not query_tokens:
......@@ -322,6 +341,10 @@ def _slugify(value: str) -> str:
return collapsed.strip("-")
# ---
# task image and block normalization
# ---
def _normalize_block_images(images_raw: list[dict[str, str]]) -> list[dict[str, str]]:
normalized_images: list[dict[str, str]] = []
for item in images_raw:
......@@ -369,6 +392,10 @@ def _extract_text_and_images(blocks: Any) -> tuple[list[str], list[dict[str, str
return text_parts, images
# ---
# task yaml normalization
# ---
def _normalize_yaml_task_entry(task_entry: Any, position: int) -> dict[str, Any] | None:
if not isinstance(task_entry, dict):
return None
......@@ -437,6 +464,10 @@ def _normalize_yaml_task_file(content: Any, path: Path) -> dict[str, Any] | None
}
# ---
# task file loading
# ---
def load_task_files(tasks_dir: Path = TASKS_DIR) -> list[dict[str, Any]]:
if not tasks_dir.exists():
return []
......@@ -459,6 +490,10 @@ def load_cached_task_files() -> list[dict[str, Any]]:
return load_task_files()
# ---
# task lookup
# ---
def _find_task_file(task_files: list[dict[str, Any]], file_id: str) -> dict[str, Any] | None:
for task_file in task_files:
if str(task_file.get("_file_id", "")) == file_id:
......@@ -502,6 +537,10 @@ def find_task_details(
}
# ---
# selected task and topic state
# ---
def _normalize_task_images(task_entry: dict[str, Any]) -> list[dict[str, str]]:
images_raw = task_entry.get("images", [])
if not isinstance(images_raw, list):
......@@ -674,6 +713,10 @@ def get_selected_task_parent_refs(sheet: dict[str, Any]) -> list[ParentRef]:
return sorted(refs)
# ---
# task selection for chat context
# ---
def select_task_for_context(
sheet: dict[str, Any],
query_text: str,
......@@ -737,6 +780,10 @@ def select_task_for_context(
return best_file, best_task
# ---
# public catalogs
# ---
def build_task_catalog(task_files: list[dict[str, Any]] | None = None) -> list[dict[str, Any]]:
catalog = task_files if task_files is not None else load_cached_task_files()
catalog = sorted(
......
# logger for the tools while the programm is running.
from __future__ import annotations
from contextvars import ContextVar, Token
......
# Logger for tool calls, saving them to JSON files in a structured way.
import json
import os
from datetime import datetime
......
# Vector Store implementation using PostgreSQL with pgvector extension.
from __future__ import annotations
import hashlib
......@@ -17,7 +19,7 @@ import app.config
embedding_dim = app.config.get_embedding_settings().target_dim
# --------------------------------------------------------------------------------------------------------------------
# Einlesen der Dokumente
# Reading of Documents
# --------------------------------------------------------------------------------------------------------------------
......@@ -124,7 +126,7 @@ def load_docs(base_dir: Path) -> List[DocRecord]:
return docs
# --------------------------------------------------------------------------------------------------------------------
# Init der Databse
# Init of the database
# --------------------------------------------------------------------------------------------------------------------
......@@ -173,7 +175,7 @@ def init_db(pg_url: str) -> None:
conn.commit()
# --------------------------------------------------------------------------------------------------------------------
# Einfügen der Dokumente und Embeddings
# Insert and update of documents and embeddings
# --------------------------------------------------------------------------------------------------------------------
......@@ -274,7 +276,7 @@ def embed_query(embedder: EmbeddingLike, text: str) -> List[float]:
return embedder.embed_query(text)
# --------------------------------------------------------------------------------------------------------------------
# Retrival der Dokumente
# Retrieval of Documents
# --------------------------------------------------------------------------------------------------------------------
......@@ -856,7 +858,7 @@ def retrieve(
return sorted(sources, key=lambda source: source.score, reverse=True)
# --------------------------------------------------------------------------------------------------------------------
# Retrival mit Parent Referenzen
# Retrieval with parent refs
# --------------------------------------------------------------------------------------------------------------------
......@@ -1058,7 +1060,7 @@ def merge_sources(primary: List[Source], additional: List[Source]) -> List[Sourc
# --------------------------------------------------------------------------------------------------------------------
# Retrival in Sources umwandeln
# transform retrieval results to sources
# --------------------------------------------------------------------------------------------------------------------
......@@ -1140,7 +1142,7 @@ def _retrivla_to_sources(retrievd: Dict[str, List[Retrieved]]) -> List[Source]:
return sources
# --------------------------------------------------------------------------------------------------------------------
# Listen für Filterung
# Lists for filtering
# --------------------------------------------------------------------------------------------------------------------
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment