omarsol commited on
Commit
8eb9a27
·
1 Parent(s): 01e84f2

Refactor logging implementation and remove logfire dependency

Browse files

- Replaced logfire logging with standard Python logging across multiple scripts for improved consistency and maintainability.
- Updated AGENTS.md to clarify agent tracing and server logging practices.
- Removed logfire from dependencies in pyproject.toml and uv.lock, streamlining the project setup.
- Enhanced logging messages for better clarity and context in various components, including api.py, chat_service.py, and setup.py.

AGENTS.md CHANGED
@@ -29,7 +29,7 @@ ChromaDB for vectors; Cohere for embeddings/rerank; chat model is provider-confi
29
  | Gradio app + renderer | `scripts/main.py`, `scripts/gradio_presenter.py` |
30
  | Paths, models, startup downloads | `scripts/setup.py` |
31
  | **Sources — single source of truth** | `data/scraping_scripts/source_registry.py` |
32
- | Tracing (LangSmith + Logfire) | `scripts/agent_tracing.py`, `scripts/setup.py` |
33
  | Data pipeline / workflows (deep guide) | `data/scraping_scripts/README.md` |
34
  | KB design + wiki maintainer workflow (deep guide) | `data/kb/MAINTAINER.md` |
35
 
 
29
  | Gradio app + renderer | `scripts/main.py`, `scripts/gradio_presenter.py` |
30
  | Paths, models, startup downloads | `scripts/setup.py` |
31
  | **Sources — single source of truth** | `data/scraping_scripts/source_registry.py` |
32
+ | Agent tracing (LangSmith) + server logging (stdlib `logging` → stdout) | `scripts/agent_tracing.py`, `scripts/setup.py` |
33
  | Data pipeline / workflows (deep guide) | `data/scraping_scripts/README.md` |
34
  | KB design + wiki maintainer workflow (deep guide) | `data/kb/MAINTAINER.md` |
35
 
pyproject.toml CHANGED
@@ -20,7 +20,6 @@ dependencies = [
20
  "langchain-google-genai",
21
  "langchain-openai",
22
  "llama-index",
23
- "logfire",
24
  "nbconvert",
25
  "nbformat",
26
  "openai",
 
20
  "langchain-google-genai",
21
  "langchain-openai",
22
  "llama-index",
 
23
  "nbconvert",
24
  "nbformat",
25
  "openai",
scripts/api.py CHANGED
@@ -1,13 +1,13 @@
1
  from __future__ import annotations
2
 
3
  import json
 
4
  import os
5
  from contextlib import asynccontextmanager
6
  from pathlib import Path
7
  from typing import Any, AsyncIterator
8
  from uuid import uuid4
9
 
10
- import logfire
11
  import uvicorn
12
  from fastapi import FastAPI, HTTPException
13
  from fastapi.middleware.cors import CORSMiddleware
@@ -34,6 +34,8 @@ from .setup import (
34
  SOURCE_UI_TO_KEY,
35
  )
36
 
 
 
37
 
38
  class ApiChatTurn(BaseModel):
39
  role: str
@@ -486,9 +488,9 @@ if FRONTEND_OUT_DIR.is_dir():
486
  name="frontend",
487
  )
488
  else:
489
- logfire.info(
490
- "Frontend static export not found; skipping static mount.",
491
- path=str(FRONTEND_OUT_DIR),
492
  )
493
 
494
 
 
1
  from __future__ import annotations
2
 
3
  import json
4
+ import logging
5
  import os
6
  from contextlib import asynccontextmanager
7
  from pathlib import Path
8
  from typing import Any, AsyncIterator
9
  from uuid import uuid4
10
 
 
11
  import uvicorn
12
  from fastapi import FastAPI, HTTPException
13
  from fastapi.middleware.cors import CORSMiddleware
 
34
  SOURCE_UI_TO_KEY,
35
  )
36
 
37
+ logger = logging.getLogger(__name__)
38
+
39
 
40
  class ApiChatTurn(BaseModel):
41
  role: str
 
488
  name="frontend",
489
  )
490
  else:
491
+ logger.info(
492
+ "Frontend static export not found; skipping static mount. path=%s",
493
+ FRONTEND_OUT_DIR,
494
  )
495
 
496
 
scripts/chat_service.py CHANGED
@@ -1,6 +1,7 @@
1
  from __future__ import annotations
2
 
3
  import json
 
4
  import os
5
  import shlex
6
  from dataclasses import dataclass
@@ -9,7 +10,6 @@ from threading import Lock
9
  from typing import Any, AsyncIterator
10
  from uuid import uuid4
11
 
12
- import logfire
13
  from langchain.agents import create_agent
14
  from langchain.agents.middleware import (
15
  AgentMiddleware,
@@ -55,6 +55,8 @@ from .setup import (
55
  ensure_local_vector_db,
56
  )
57
 
 
 
58
  SOURCES_HEADER = "📝 Here are the sources I used to answer your question:"
59
  ACTIVITY_BLOCK_START = "<!-- MODEL_ACTIVITY_START -->"
60
  ACTIVITY_BLOCK_END = "<!-- MODEL_ACTIVITY_END -->"
@@ -121,9 +123,9 @@ def warm_up_retriever() -> None:
121
  try:
122
  get_retriever()
123
  except Exception as exc: # pragma: no cover - diagnostic logging only
124
- logfire.warn(
125
- "Retriever warm-up failed; first retrieval call may retry.",
126
- error=str(exc),
127
  )
128
 
129
 
@@ -201,7 +203,7 @@ def run_kb_command(
201
  try:
202
  ensure_local_vector_db()
203
  except Exception as exc: # pragma: no cover - diagnostic only
204
- logfire.warn("KB artifact download/check failed.", error=str(exc))
205
  try:
206
  result = execute_kb_command(
207
  command,
@@ -1046,7 +1048,7 @@ async def stream_chat(request: ChatRequest) -> AsyncIterator[ChatEvent]:
1046
  google_search_queries: list[str] = []
1047
  google_search_match_count = 0
1048
 
1049
- logfire.info("Running query", query=request.query)
1050
  agent = build_agent(
1051
  request.model_name,
1052
  enabled_tools=tuple(request.enabled_tools),
 
1
  from __future__ import annotations
2
 
3
  import json
4
+ import logging
5
  import os
6
  import shlex
7
  from dataclasses import dataclass
 
10
  from typing import Any, AsyncIterator
11
  from uuid import uuid4
12
 
 
13
  from langchain.agents import create_agent
14
  from langchain.agents.middleware import (
15
  AgentMiddleware,
 
55
  ensure_local_vector_db,
56
  )
57
 
58
+ logger = logging.getLogger(__name__)
59
+
60
  SOURCES_HEADER = "📝 Here are the sources I used to answer your question:"
61
  ACTIVITY_BLOCK_START = "<!-- MODEL_ACTIVITY_START -->"
62
  ACTIVITY_BLOCK_END = "<!-- MODEL_ACTIVITY_END -->"
 
123
  try:
124
  get_retriever()
125
  except Exception as exc: # pragma: no cover - diagnostic logging only
126
+ logger.warning(
127
+ "Retriever warm-up failed; first retrieval call may retry. error=%s",
128
+ exc,
129
  )
130
 
131
 
 
203
  try:
204
  ensure_local_vector_db()
205
  except Exception as exc: # pragma: no cover - diagnostic only
206
+ logger.warning("KB artifact download/check failed. error=%s", exc)
207
  try:
208
  result = execute_kb_command(
209
  command,
 
1048
  google_search_queries: list[str] = []
1049
  google_search_match_count = 0
1050
 
1051
+ logger.info("Running query: %s", request.query)
1052
  agent = build_agent(
1053
  request.model_name,
1054
  enabled_tools=tuple(request.enabled_tools),
scripts/chroma_rag.py CHANGED
@@ -1,6 +1,7 @@
1
  from __future__ import annotations
2
 
3
  import json
 
4
  import math
5
  import os
6
  import pickle
@@ -16,10 +17,11 @@ from urllib.parse import unquote, urlparse
16
 
17
  import chromadb
18
  import cohere
19
- import logfire
20
  import tiktoken
21
  from tqdm.auto import tqdm
22
 
 
 
23
 
24
  DEFAULT_CHUNK_SIZE = 800
25
  DEFAULT_CHUNK_OVERLAP = 100
@@ -1381,5 +1383,5 @@ def parse_tool_payload(content: str) -> list[SearchResult]:
1381
  try:
1382
  parsed.append(SearchResult(**match))
1383
  except TypeError:
1384
- logfire.warn("Skipping malformed retrieval payload entry")
1385
  return parsed
 
1
  from __future__ import annotations
2
 
3
  import json
4
+ import logging
5
  import math
6
  import os
7
  import pickle
 
17
 
18
  import chromadb
19
  import cohere
 
20
  import tiktoken
21
  from tqdm.auto import tqdm
22
 
23
+ logger = logging.getLogger(__name__)
24
+
25
 
26
  DEFAULT_CHUNK_SIZE = 800
27
  DEFAULT_CHUNK_OVERLAP = 100
 
1383
  try:
1384
  parsed.append(SearchResult(**match))
1385
  except TypeError:
1386
+ logger.warning("Skipping malformed retrieval payload entry")
1387
  return parsed
scripts/setup.py CHANGED
@@ -1,7 +1,7 @@
 
1
  import os
2
  from pathlib import Path
3
 
4
- import logfire
5
  from dotenv import load_dotenv
6
 
7
  from data.scraping_scripts.source_registry import (
@@ -19,15 +19,21 @@ from .utils import init_mongo_db
19
 
20
  load_dotenv(override=True)
21
  configure_langsmith_environment()
22
- try:
23
- logfire.configure()
24
- except Exception:
25
- pass
 
 
 
 
 
 
26
 
27
  if langsmith_tracing_enabled():
28
- logfire.info(
29
- "LangSmith tracing enabled.",
30
- project=os.getenv("LANGSMITH_PROJECT", "default"),
31
  )
32
 
33
  VECTOR_DB_DIR = "data/chroma-db-all_sources"
@@ -69,7 +75,7 @@ def ensure_local_vector_db() -> None:
69
  and os.path.exists(KB_INDEX_PATH)
70
  )
71
  if needs_download:
72
- logfire.warn(
73
  "Vector database does not exist locally, downloading from Hugging Face"
74
  )
75
  from huggingface_hub import snapshot_download
@@ -82,11 +88,11 @@ def ensure_local_vector_db() -> None:
82
  ensure_kb_agents_md()
83
 
84
 
85
- mongo_db = (
86
- init_mongo_db(uri=MONGODB_URI, db_name="towardsai-buster")
87
- if MONGODB_URI
88
- else logfire.warn("No mongodb uri found, you will not be able to save data.")
89
- )
90
 
91
  __all__ = [
92
  "AVAILABLE_MODELS",
 
1
+ import logging
2
  import os
3
  from pathlib import Path
4
 
 
5
  from dotenv import load_dotenv
6
 
7
  from data.scraping_scripts.source_registry import (
 
19
 
20
  load_dotenv(override=True)
21
  configure_langsmith_environment()
22
+
23
+ # Operational/server logging goes to stdout (captured by the Hugging Face Space
24
+ # logs). This is separate from LangSmith, which traces agent runs; see
25
+ # scripts/agent_tracing.py. basicConfig is a no-op if logging is already
26
+ # configured (e.g. by a data-pipeline entry point), so it won't clobber callers.
27
+ logging.basicConfig(
28
+ level=logging.INFO,
29
+ format="%(asctime)s %(levelname)s [%(name)s] %(message)s",
30
+ )
31
+ logger = logging.getLogger(__name__)
32
 
33
  if langsmith_tracing_enabled():
34
+ logger.info(
35
+ "LangSmith tracing enabled. project=%s",
36
+ os.getenv("LANGSMITH_PROJECT", "default"),
37
  )
38
 
39
  VECTOR_DB_DIR = "data/chroma-db-all_sources"
 
75
  and os.path.exists(KB_INDEX_PATH)
76
  )
77
  if needs_download:
78
+ logger.warning(
79
  "Vector database does not exist locally, downloading from Hugging Face"
80
  )
81
  from huggingface_hub import snapshot_download
 
88
  ensure_kb_agents_md()
89
 
90
 
91
+ if MONGODB_URI:
92
+ mongo_db = init_mongo_db(uri=MONGODB_URI, db_name="towardsai-buster")
93
+ else:
94
+ logger.warning("No mongodb uri found, you will not be able to save data.")
95
+ mongo_db = None
96
 
97
  __all__ = [
98
  "AVAILABLE_MODELS",
uv.lock CHANGED
@@ -30,7 +30,6 @@ dependencies = [
30
  { name = "langchain-google-genai" },
31
  { name = "langchain-openai" },
32
  { name = "llama-index" },
33
- { name = "logfire" },
34
  { name = "nbconvert" },
35
  { name = "nbformat" },
36
  { name = "openai" },
@@ -66,7 +65,6 @@ requires-dist = [
66
  { name = "langchain-google-genai" },
67
  { name = "langchain-openai" },
68
  { name = "llama-index" },
69
- { name = "logfire" },
70
  { name = "nbconvert" },
71
  { name = "nbformat" },
72
  { name = "openai" },
@@ -1961,24 +1959,6 @@ wheels = [
1961
  { url = "https://files.pythonhosted.org/packages/71/5f/385231406d777cb4b608fd8ebe3577dbd90962770717181e6b91b44fb1b8/llama_index_workflows-2.20.0-py3-none-any.whl", hash = "sha256:36f6b6ace77f837d9907078aea7e830251afe96a58daecff5ed090c88c55095d", size = 121238, upload-time = "2026-04-24T14:54:40.455Z" },
1962
  ]
1963
 
1964
- [[package]]
1965
- name = "logfire"
1966
- version = "4.35.0"
1967
- source = { registry = "https://pypi.org/simple" }
1968
- dependencies = [
1969
- { name = "executing" },
1970
- { name = "opentelemetry-exporter-otlp-proto-http" },
1971
- { name = "opentelemetry-instrumentation" },
1972
- { name = "opentelemetry-sdk" },
1973
- { name = "protobuf" },
1974
- { name = "rich" },
1975
- { name = "typing-extensions" },
1976
- ]
1977
- sdist = { url = "https://files.pythonhosted.org/packages/7c/20/9508c92ad4ec2ed4ad63a20d72f08427c24117273541ec97c630332855c3/logfire-4.35.0.tar.gz", hash = "sha256:6542aa4ac5e2d2369587deab57a0d1bb9cf6da49634c8cd9c5dbd7c7581f3d51", size = 1148150, upload-time = "2026-06-02T14:55:56.792Z" }
1978
- wheels = [
1979
- { url = "https://files.pythonhosted.org/packages/77/37/a3631d0b7e4fcb19df4705c7c7e17164c5446e144f034723cf6277749973/logfire-4.35.0-py3-none-any.whl", hash = "sha256:9ae5c3f2dd81144ccf1ec6dba1a5de84aff5b2e2b8dd2190e53e87e47bc63711", size = 347012, upload-time = "2026-06-02T14:55:53.244Z" },
1980
- ]
1981
-
1982
  [[package]]
1983
  name = "markdown-it-py"
1984
  version = "4.2.0"
@@ -2476,39 +2456,6 @@ wheels = [
2476
  { url = "https://files.pythonhosted.org/packages/89/2b/28ba5b128f47fe8c3bab541000d6feb4b5a9bd26623ca013406f01c0fb60/opentelemetry_exporter_otlp_proto_grpc-1.42.1-py3-none-any.whl", hash = "sha256:0ae1177e2038b18a929b3098215243631ef91136cba26b7e2b12790ceb7e87cc", size = 19617, upload-time = "2026-05-21T16:32:34.278Z" },
2477
  ]
2478
 
2479
- [[package]]
2480
- name = "opentelemetry-exporter-otlp-proto-http"
2481
- version = "1.42.1"
2482
- source = { registry = "https://pypi.org/simple" }
2483
- dependencies = [
2484
- { name = "googleapis-common-protos" },
2485
- { name = "opentelemetry-api" },
2486
- { name = "opentelemetry-exporter-otlp-proto-common" },
2487
- { name = "opentelemetry-proto" },
2488
- { name = "opentelemetry-sdk" },
2489
- { name = "requests" },
2490
- { name = "typing-extensions" },
2491
- ]
2492
- sdist = { url = "https://files.pythonhosted.org/packages/77/32/826bfa1d80ecea24f47808de03cd4a0d13c17ecc07712f45123f0f61e4ac/opentelemetry_exporter_otlp_proto_http-1.42.1.tar.gz", hash = "sha256:bf142a21035d7571ac3a09cb2e5639f49886f243972883cfe777ed3bf02b734d", size = 25406, upload-time = "2026-05-21T16:32:56.807Z" }
2493
- wheels = [
2494
- { url = "https://files.pythonhosted.org/packages/d3/96/82cb223a1502f0787d4bbff12907f5f8d870a50731febcd5818d93ef9555/opentelemetry_exporter_otlp_proto_http-1.42.1-py3-none-any.whl", hash = "sha256:00a16da1b312a1d6c7233d600d557c91df71125af73020f3b9a7765bd699d59d", size = 21793, upload-time = "2026-05-21T16:32:35.277Z" },
2495
- ]
2496
-
2497
- [[package]]
2498
- name = "opentelemetry-instrumentation"
2499
- version = "0.63b1"
2500
- source = { registry = "https://pypi.org/simple" }
2501
- dependencies = [
2502
- { name = "opentelemetry-api" },
2503
- { name = "opentelemetry-semantic-conventions" },
2504
- { name = "packaging" },
2505
- { name = "wrapt" },
2506
- ]
2507
- sdist = { url = "https://files.pythonhosted.org/packages/da/6d/4de72d97ff54db1ed270c7a59c9b904b917c0ac7af429c086c388b824ddb/opentelemetry_instrumentation-0.63b1.tar.gz", hash = "sha256:32368d6ae52c8de20aa790a6ad86b10a76f09956092337ae37d675773990e541", size = 41081, upload-time = "2026-05-21T16:36:14.206Z" }
2508
- wheels = [
2509
- { url = "https://files.pythonhosted.org/packages/35/a1/9314e621c143e4d82a5bf7a43c2ff7a745d31023506336857607c8c543cc/opentelemetry_instrumentation-0.63b1-py3-none-any.whl", hash = "sha256:f1986716d52cc316ea5f60189098726a9071d8ecc0eee96c9ed110be08bade9c", size = 35577, upload-time = "2026-05-21T16:34:56.818Z" },
2510
- ]
2511
-
2512
  [[package]]
2513
  name = "opentelemetry-proto"
2514
  version = "1.42.1"
 
30
  { name = "langchain-google-genai" },
31
  { name = "langchain-openai" },
32
  { name = "llama-index" },
 
33
  { name = "nbconvert" },
34
  { name = "nbformat" },
35
  { name = "openai" },
 
65
  { name = "langchain-google-genai" },
66
  { name = "langchain-openai" },
67
  { name = "llama-index" },
 
68
  { name = "nbconvert" },
69
  { name = "nbformat" },
70
  { name = "openai" },
 
1959
  { url = "https://files.pythonhosted.org/packages/71/5f/385231406d777cb4b608fd8ebe3577dbd90962770717181e6b91b44fb1b8/llama_index_workflows-2.20.0-py3-none-any.whl", hash = "sha256:36f6b6ace77f837d9907078aea7e830251afe96a58daecff5ed090c88c55095d", size = 121238, upload-time = "2026-04-24T14:54:40.455Z" },
1960
  ]
1961
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1962
  [[package]]
1963
  name = "markdown-it-py"
1964
  version = "4.2.0"
 
2456
  { url = "https://files.pythonhosted.org/packages/89/2b/28ba5b128f47fe8c3bab541000d6feb4b5a9bd26623ca013406f01c0fb60/opentelemetry_exporter_otlp_proto_grpc-1.42.1-py3-none-any.whl", hash = "sha256:0ae1177e2038b18a929b3098215243631ef91136cba26b7e2b12790ceb7e87cc", size = 19617, upload-time = "2026-05-21T16:32:34.278Z" },
2457
  ]
2458
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2459
  [[package]]
2460
  name = "opentelemetry-proto"
2461
  version = "1.42.1"