Skip to content

Commit 08df46f

Browse files
committed
Cleanup and update readme
1 parent 1b347e7 commit 08df46f

24 files changed

Lines changed: 208 additions & 476 deletions

README.md

Lines changed: 157 additions & 247 deletions
Large diffs are not rendered by default.

backend/config.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class Settings(BaseSettings):
1818
together_api_key: str = ""
1919
openai_api_key: str = ""
2020

21-
llm_provider: str = "ollama" # ollama | gemini | groq | together | openai
21+
llm_provider: str = "ollama" # ollama | gemini | groq | together
2222

2323
# Separate provider for translation — defaults to ollama (no rate limits, runs locally).
2424
# Set TRANSLATION_PROVIDER=groq in .env only if you have a paid Groq account with
@@ -34,10 +34,10 @@ class Settings(BaseSettings):
3434
# Per-step Ollama model overrides
3535
grade_model: str = "" # e.g. "llama3.2:1b" — falls back to ollama_llm_model
3636
query_gen_model: str = "" # e.g. "llama3.2:3b"
37-
synth_model: str = "" # e.g. "qwen2.5:7b" — recommended for fewer hallucinations
37+
synth_model: str = "" # e.g. "qwen2.5:7b" for fewer hallucinations
3838
judge_model: str = "" # e.g. "llama3.2:3b"
39-
translation_model: str = "" # e.g. "qwen2.5:7b" — strong multilingual on M4 Metal
40-
fact_check_model: str = "" # e.g. "qwen2.5:7b" — used to compare claim vs web snippet
39+
translation_model: str = "" # e.g. "qwen2.5:7b" for multilingual on Metal
40+
fact_check_model: str = "" # e.g. "qwen2.5:7b" compares claim vs snippet
4141

4242
# Post-synthesis web fact-check for COMPLEX fields (etymology, cultural_info, fun_fact).
4343
# Runs a targeted DDG search per field, compares the synthesized claim to the top snippet,

backend/log_config.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,3 @@ def configure_logging() -> None:
2222
logger_factory=structlog.PrintLoggerFactory(),
2323
cache_logger_on_first_use=True,
2424
)
25-
26-
27-
logger = structlog.get_logger()

backend/logging.py

Lines changed: 0 additions & 19 deletions
This file was deleted.

backend/models.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,15 @@ class Flower(Base):
6060
DateTime(timezone=True), server_default=func.now(), onupdate=func.now()
6161
)
6262

63-
raw_sources: Mapped[list["RawSource"]] = relationship(back_populates="flower", cascade="all, delete-orphan")
64-
embeddings: Mapped[list["SourceEmbedding"]] = relationship(back_populates="flower", cascade="all, delete-orphan")
65-
translations: Mapped[list["Translation"]] = relationship(back_populates="flower", cascade="all, delete-orphan")
63+
raw_sources: Mapped[list["RawSource"]] = relationship(
64+
back_populates="flower", cascade="all, delete-orphan"
65+
)
66+
embeddings: Mapped[list["SourceEmbedding"]] = relationship(
67+
back_populates="flower", cascade="all, delete-orphan"
68+
)
69+
translations: Mapped[list["Translation"]] = relationship(
70+
back_populates="flower", cascade="all, delete-orphan"
71+
)
6672

6773

6874
class RawSource(Base):

backend/routers/flowers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from pathlib import Path
55

6-
from database import async_session_factory, get_db
6+
from database import get_db
77
from fastapi import APIRouter, Depends, HTTPException
88
from fastapi.responses import FileResponse
99
from models import Flower
@@ -109,7 +109,7 @@ async def run_image_pipeline(flower_id: int, db: AsyncSession = Depends(get_db))
109109
from config import settings
110110
from services.images.lock_gen import generate_lock_image
111111
from services.images.processor import process_info_image, process_main_image
112-
from services.images.wikimedia import find_images
112+
from services.images.search import find_images
113113

114114
flower = await db.get(Flower, flower_id)
115115
if not flower:

backend/services/images/wikimedia.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -282,16 +282,3 @@ def _add(imgs: list[WikimediaImage]) -> None:
282282

283283
return candidates
284284

285-
286-
# ---------------------------------------------------------------------------
287-
# Legacy API — kept for backwards compatibility with existing callers
288-
# ---------------------------------------------------------------------------
289-
290-
async def find_images(latin_name: str) -> ImagePair:
291-
"""Return the best (info, blossom) pair from Wikimedia Commons.
292-
293-
DEPRECATED: Use search.find_images() instead for multi-source results.
294-
Kept for backwards compatibility.
295-
"""
296-
from services.images.search import find_images as _find
297-
return await _find(latin_name)

backend/services/llm/provider.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,6 @@ def get_provider(
4949
elif name == "together":
5050
from services.llm.together import TogetherProvider
5151
return TogetherProvider()
52-
elif name == "openai":
53-
from services.llm.openai import OpenAIProvider
54-
return OpenAIProvider()
5552
else:
5653
from services.llm.ollama import OllamaProvider
5754
return OllamaProvider(model_override=step_model)

backend/services/observability.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ def on_end(self, span: ReadableSpan) -> None:
164164
import mlflow
165165
if not mlflow.active_run():
166166
return
167+
if span.end_time is None or span.start_time is None:
168+
return
167169
duration_s = (span.end_time - span.start_time) / 1_000_000_000.0
168170
name = span.name
169171
attrs = span.attributes or {}
@@ -181,7 +183,7 @@ def on_end(self, span: ReadableSpan) -> None:
181183
metrics: dict[str, float] = {f"trace_{name}_s": duration_s}
182184
for key in ("tokens_used", "llm_calls", "api_calls", "chunks_in", "chunks_out"):
183185
v = attrs.get(key)
184-
if v:
186+
if isinstance(v, (int, float)):
185187
# Normalize "tokens_used" → "tokens" for backward-compatible metric names.
186188
metric_key = "tokens" if key == "tokens_used" else key
187189
metrics[f"trace_{name}_{metric_key}"] = float(v)
@@ -216,6 +218,8 @@ def on_start(self, span: Span, parent_context: Context | None = None) -> None:
216218

217219
def on_end(self, span: ReadableSpan) -> None:
218220
trace_id = span.context.trace_id
221+
if span.end_time is None or span.start_time is None:
222+
return
219223
duration_s = (span.end_time - span.start_time) / 1_000_000_000.0
220224
attrs = span.attributes or {}
221225
entry = self.flowers[trace_id]
@@ -226,8 +230,10 @@ def on_end(self, span: ReadableSpan) -> None:
226230
entry["total_s"] = duration_s
227231
return
228232

229-
tokens = int(attrs.get("tokens_used", 0) or 0)
230-
calls = int(attrs.get("llm_calls", 0) or 0)
233+
raw_tokens = attrs.get("tokens_used", 0) or 0
234+
raw_calls = attrs.get("llm_calls", 0) or 0
235+
tokens = int(raw_tokens) if isinstance(raw_tokens, (int, float)) else 0
236+
calls = int(raw_calls) if isinstance(raw_calls, (int, float)) else 0
231237
entry["steps"][span.name] = {
232238
"duration_s": duration_s,
233239
"tokens": tokens,

backend/services/rag/embedder.py

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -74,26 +74,6 @@ async def embed_and_store(
7474
return results
7575

7676

77-
async def embed_all_sources(
78-
flower_id: int,
79-
embed_provider: EmbeddingProvider,
80-
session: AsyncSession,
81-
) -> list[SourceEmbedding]:
82-
"""Embed all raw sources for a flower that don't yet have embeddings."""
83-
result = await session.execute(
84-
select(RawSource).where(RawSource.flower_id == flower_id)
85-
)
86-
sources = result.scalars().all()
87-
88-
all_embeddings: list[SourceEmbedding] = []
89-
for src in sources:
90-
if not src.raw_content and not src.parsed_content:
91-
continue
92-
embs = await embed_and_store(flower_id, src, embed_provider, session)
93-
all_embeddings.extend(embs)
94-
return all_embeddings
95-
96-
9777
def _build_chunk_text(raw_source: RawSource) -> str:
9878
"""Concatenate available text from a raw source into a single string."""
9979
parts: list[str] = []

0 commit comments

Comments
 (0)