Skip to content

Conversation

@syedriko
Copy link
Contributor

@syedriko syedriko commented Oct 28, 2025

Description

Update Llama Stack to 0.2.22 and the rest of the Python deps accordingly.

Type of change

  • Refactor
  • New feature
  • Bug fix
  • CVE fix
  • Optimization
  • Documentation Update
  • Configuration Update
  • Bump-up service version
  • Bump-up dependent library
  • Bump-up library or tool used for development (does not change the final image)
  • CI configuration change
  • Konflux configuration change
  • Unit tests improvement
  • Integration tests improvement
  • End to end tests improvement

Related Tickets & Documents

  • Related Issue #
  • Closes #

Checklist before requesting a review

  • I have performed a self-review of my code.
  • PR has passed all pre-merge test jobs.
  • If it is a core feature, I have added thorough tests.

Testing

  • Please provide detailed steps to perform tests related to this code change.
  • How were the fix/results from this change verified? Please provide relevant screenshots or results.

Summary by CodeRabbit

  • Chores

    • Relaxed strict dependency pins to minimum-version ranges for greater compatibility.
    • Added mypy configuration improvements for better type checking.
    • Updated client library path usages to align with reorganized modules.
  • Bug Fixes

    • Improved retrieval handling: non-text or unexpected items are skipped and now produce clear error responses when requested.
    • Single-item results now validate type and emit warnings/errors for unsupported types.
    • Refined typing and annotations in document processing for more reliable behavior.

@coderabbitai
Copy link

coderabbitai bot commented Oct 28, 2025

Walkthrough

Adds mypy config and relaxes dependency pins in pyproject.toml. Tightens runtime type checks and JSON error paths in scripts/query_rag.py to accept only TextNode / NodeWithScore where appropriate. Removes # type: ignore and corrects a llama-stack import in src/lightspeed_rag_content/document_processor.py.

Changes

Cohort / File(s) Summary
Dependency Management
pyproject.toml
Adds mypy settings (mypy_path = ["src"], namespace_packages = true, explicit_package_bases = true). Changes exact pins to minimum-version constraints for several packages (e.g., PyYAML>=6.0.2, llama-index>=0.12.51, faiss-cpu>=1.11.0.post1, torch>=2.7.1, aiosqlite>=0.21.0, sqlite-vec>=0.1.6) and bumps llama-stack/llama-stack-client to 0.2.22.
Node type checks & output
scripts/query_rag.py
Imports NodeWithScore and TextNode. Single-node flow now only proceeds for TextNode (otherwise logs warning and returns JSON error with exit code 1 when JSON mode). Multi-node flow appends only NodeWithScore items, skips others with debug logs; JSON error pathways added for unexpected types. Also switches llama-stack client usage to core import.
Typing and import fixes
src/lightspeed_rag_content/document_processor.py
Removes # type: ignore on document_class, client_class, and documents annotation. Corrects LlamaStack client import path from llama_stack.distribution.library_clientllama_stack.core.library_client.

Sequence Diagram(s)

sequenceDiagram
  participant CLI as Query Script
  participant Retriever as LlamaIndex Retriever
  participant Formatter as Output Formatter
  note over CLI,Retriever: User issues RAG query
  CLI->>Retriever: retrieve()
  Retriever-->>CLI: nodes[]
  alt single-node
    CLI->>CLI: check node type
    alt TextNode
      CLI->>Formatter: format TextNode -> JSON/plain
      Formatter-->>CLI: output
    else not TextNode
      CLI-->>CLI: log warning
      CLI-->>CLI: return JSON error & exit(1)
    end
  else multi-node
    CLI->>CLI: iterate nodes
    CLI->>CLI: if NodeWithScore -> append
    CLI-->>CLI: skip others (debug)
    CLI->>Formatter: format list -> JSON/plain
    Formatter-->>CLI: output
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Pay attention to the updated llama-stack import and removed # type: ignore spots in document_processor.py.
  • Review JSON error/exiting behavior and logging in scripts/query_rag.py to ensure CLI semantics are preserved.
  • Verify dependency loosening in pyproject.toml matches intended reproducibility/compatibility requirements.

Possibly related PRs

Suggested reviewers

  • tisnik
  • umago
  • lpiwowar

Poem

🐰 I hop through code with ears alert,
Pins loosened, types assert,
Llamas moved to proper lane,
Nodes checked clean — no stray refrain,
A tiny patch, a tidy burst.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "Update Llama Stack to 0.2.22" directly references a core change in the pull request, which updates llama-stack and llama-stack-client from version 0.2.16 to 0.2.22 in the pyproject.toml file. The title is clear, specific, and accurately describes this primary driver of the changeset. While the PR also includes updates to other dependencies, adds mypy configuration, and modifies code logic for type checking, these are secondary changes that follow from the main version bump. The title appropriately highlights the most significant change without being misleading or vague.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
pyproject.toml (1)

40-52: Consider using compatible release constraints instead of minimum version constraints.

The dependency specifications have been relaxed from exact pins (==) to minimum version constraints (>=) for most packages. While this provides flexibility, it can introduce instability by allowing breaking changes from future releases to be pulled in automatically. This is especially risky for packages like llama-index, torch, and faiss-cpu, which can have breaking API changes between releases.

Consider using compatible release constraints (~=) instead of minimum versions:

-    "PyYAML>=6.0.2",
+    "PyYAML~=6.0.2",
     "huggingface_hub>=0.33.4",
-    "llama-index>=0.12.51",
-    "llama-index-vector-stores-faiss>=0.3.0",
-    "llama-index-embeddings-huggingface>=0.4.0",
-    "llama-index-readers-file>=0.4.11",
-    "faiss-cpu>=1.11.0.post1",
+    "llama-index~=0.12.51",
+    "llama-index-vector-stores-faiss~=0.3.0",
+    "llama-index-embeddings-huggingface~=0.4.0",
+    "llama-index-readers-file~=0.4.11",
+    "faiss-cpu~=1.11.0",
     "llama-index-vector-stores-postgres>=0.5.4",
-    "torch>=2.7.1",
+    "torch~=2.7.1",
     "llama-stack==0.2.22",
     "llama-stack-client==0.2.22",
-    "aiosqlite>=0.21.0",
-    "sqlite-vec>=0.1.6",
+    "aiosqlite~=0.21.0",
+    "sqlite-vec~=0.1.6",

The ~= operator allows patch-level updates but prevents minor/major version changes that could introduce breaking changes. For example, ~=0.12.51 allows 0.12.52 but not 0.13.0.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0d4c9c8 and d8de1b2.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • pyproject.toml (2 hunks)
  • scripts/query_rag.py (3 hunks)
  • src/lightspeed_rag_content/document_processor.py (1 hunks)
🔇 Additional comments (3)
src/lightspeed_rag_content/document_processor.py (1)

283-283: LGTM: Type annotations cleaned up.

The removal of # type: ignore comments indicates that llama-stack 0.2.22 now properly exports type information for RAGDocument, and the mypy configuration updates in pyproject.toml enable proper type checking for these imports. This is a positive improvement for type safety.

Also applies to: 288-289

pyproject.toml (1)

23-25: LGTM: Mypy configuration for namespace packages.

The added mypy configuration properly enables namespace package support, which allows mypy to correctly resolve types from the src directory structure. This explains why # type: ignore comments could be removed in other files.

scripts/query_rag.py (1)

14-14: Imports are compatible; no issue exists with this code.

NodeWithScore and TextNode are available in llama_index.core.schema for v0.12.51, which matches the pinned dependency (llama-index>=0.12.51).

While llama-stack 0.2.22 uses an older Node/TextNode shape incompatible with modern LlamaIndex, this incompatibility does not affect the script. The code has two separate execution paths:

  1. _llama_index_query() (FAISS): Uses NodeWithScore/TextNode exclusively with LlamaIndex—llama-stack is not involved.
  2. _llama_stack_query() (llama-stack): Uses only llama-stack APIs and does not reference the imported types.

These paths are mutually exclusive (determined at line 218-224 by args.vector_store_type), so the incompatibility between libraries never manifests at runtime.

Likely an incorrect or invalid review comment.

@syedriko syedriko force-pushed the syedriko-update-llama-stack-version branch from d8de1b2 to 256c5d7 Compare October 28, 2025 03:43
@syedriko syedriko force-pushed the syedriko-update-llama-stack-version branch from 256c5d7 to c10d224 Compare October 28, 2025 03:54
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/query_rag.py (1)

83-97: Guard threshold compare against missing/None scores.

nodes[0].score can be None in some retrievers; None < float raises TypeError.

-        if args.threshold > 0.0 and nodes[0].score < args.threshold:
+        top_score = getattr(nodes[0], "score", None)
+        if args.threshold > 0.0 and (top_score is None or top_score < args.threshold):
🧹 Nitpick comments (4)
scripts/query_rag.py (3)

156-158: Import the submodule explicitly to avoid attribute lookup issues on the package.

Top-level import_module("llama_stack") doesn’t guarantee core is loaded. Import the submodule.

-    stack_lib = importlib.import_module("llama_stack")
-    client = stack_lib.core.library_client.LlamaStackAsLibraryClient(cfg_file)
+    lib_client_mod = importlib.import_module("llama_stack.core.library_client")
+    client = lib_client_mod.LlamaStackAsLibraryClient(cfg_file)

197-211: Mirror the threshold None-guard for llama-stack results.

md["scores"][0] may be a plain float or an object with .score; it may also be missing/None. Guard before comparing.

-    if threshold > 0.0 and md.get("scores") and md["scores"][0].score < threshold:
+    top = None
+    if md.get("scores"):
+        s0 = md["scores"][0]
+        top = s0.score if hasattr(s0, "score") else s0
+    if threshold > 0.0 and (top is None or top < threshold):

66-66: Prefer sys.exit over exit for scripts.

exit() is intended for interactive shells; use sys.exit() consistently.

pyproject.toml (1)

40-52: Constrain fast‑moving libs to a safe range; unify Hugging Face package name.

  • The llama-index family moves fast; add an upper bound to avoid surprise breaks.
  • Use the canonical PyPI name “huggingface-hub” (hyphen) for consistency.
-    "PyYAML>=6.0.2",
-    "huggingface_hub>=0.33.4",
-    "llama-index>=0.12.51",
-    "llama-index-vector-stores-faiss>=0.3.0",
-    "llama-index-embeddings-huggingface>=0.4.0",
-    "llama-index-readers-file>=0.4.11",
+    "PyYAML>=6.0.2",
+    "huggingface-hub>=0.33.4",
+    "llama-index>=0.12.51,<0.13",
+    "llama-index-vector-stores-faiss>=0.3.0,<0.4",
+    "llama-index-embeddings-huggingface>=0.4.0,<0.5",
+    "llama-index-readers-file>=0.4.11,<0.5",

Optionally consider similar upper bounds for faiss-cpu to the next minor.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 256c5d7 and c10d224.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • pyproject.toml (2 hunks)
  • scripts/query_rag.py (4 hunks)
  • src/lightspeed_rag_content/document_processor.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lightspeed_rag_content/document_processor.py
🔇 Additional comments (2)
pyproject.toml (2)

23-25: mypy path/namespace tweaks look good.

Enables proper namespace package resolution under src/. LGTM.


48-50: Original concern is unwarranted; torch>=2.7.1 is available and satisfiable.

Latest stable PyTorch CPU wheel for Python 3.12 is 2.8.0+cpu, available at https://download.pytorch.org/whl/cpu. Since 2.8.0 exists, the pinned constraint torch>=2.7.1 is fully resolvable and will install without issue. No changes needed.

Comment on lines 37 to +43
if args.node is not None:
node = storage_context.docstore.get_node(args.node)
result = {
"query": args.query,
"type": "single_node",
"node_id": args.node,
"node": {
"id": node.node_id,
"text": node.text,
"metadata": node.metadata if hasattr(node, "metadata") else {},
},
}
if args.json:
print(json.dumps(result, indent=2))
if isinstance(node, TextNode):
result = {
"query": args.query,
"type": "single_node",
"node_id": args.node,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Handle “node not found” explicitly and avoid ambiguous type message; also prefer sys.exit.

docstore.get_node can raise KeyError or return None. Treat that as “not found” instead of “not a TextNode”, and exit via sys.exit to be safe in non-interactive runs.

-    if args.node is not None:
-        node = storage_context.docstore.get_node(args.node)
+    if args.node is not None:
+        try:
+            node = storage_context.docstore.get_node(args.node)
+        except KeyError:
+            msg = f"Node {args.node} not found"
+            logging.warning(msg)
+            if args.json:
+                print(json.dumps({
+                    "query": args.query,
+                    "type": "single_node",
+                    "node_id": args.node,
+                    "error": msg,
+                }, indent=2))
+            sys.exit(1)
         if isinstance(node, TextNode):
           ...
-        else:
+        else:
             logging.warning(
                 f"Node {args.node} is not a TextNode, type: {type(node).__name__}"
             )
             if args.json:
                 result = {
                     "query": args.query,
                     "type": "single_node",
                     "node_id": args.node,
                     "error": f"Node is not a TextNode (type: {type(node).__name__})",
                 }
                 print(json.dumps(result, indent=2))
-            exit(1)
+            sys.exit(1)

Also applies to: 55-66

🤖 Prompt for AI Agents
In scripts/query_rag.py around lines 37-43 (and similarly 55-66), handle the
case where storage_context.docstore.get_node may raise KeyError or return None:
wrap the get_node call in a try/except KeyError (and check for None) and if
missing print/log a clear "node not found" message and call sys.exit(1); if the
node is present but not a TextNode print/log a clear "node is not a TextNode"
message and call sys.exit(1) instead of falling through to ambiguous behavior.
Ensure sys is imported at the top if not already.

Comment on lines 105 to +117
for node in nodes: # type: ignore
node_data = {
"id": node.node_id,
"score": node.score,
"text": node.text,
"metadata": node.metadata if hasattr(node, "metadata") else {},
}
result["nodes"].append(node_data)
if isinstance(node, NodeWithScore):
node_data = {
"id": node.node_id,
"score": node.score,
"text": node.text,
"metadata": node.metadata if hasattr(node, "metadata") else {},
}
result["nodes"].append(node_data)
else:
logging.debug(
f"Skipping node of type {type(node).__name__}, expected NodeWithScore"
)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Access fields via NodeWithScore.node to avoid AttributeError across versions; drop the loop’s type: ignore.

In llama-index 0.12, NodeWithScore holds the node in .node. Accessing .node_id, .text, .metadata directly on the wrapper may fail.

-        for node in nodes:  # type: ignore
-            if isinstance(node, NodeWithScore):
-                node_data = {
-                    "id": node.node_id,
-                    "score": node.score,
-                    "text": node.text,
-                    "metadata": node.metadata if hasattr(node, "metadata") else {},
-                }
-                result["nodes"].append(node_data)
+        from typing import Sequence, cast
+        retrieved = cast(Sequence[NodeWithScore], nodes)
+        for nw in retrieved:
+            if isinstance(nw, NodeWithScore):
+                base = nw.node
+                # Prefer get_content() to work for non-TextNode nodes too
+                text = getattr(base, "text", None)
+                if text is None and hasattr(base, "get_content"):
+                    text = base.get_content() or ""
+                node_data = {
+                    "id": getattr(base, "node_id", getattr(base, "id_", "")),
+                    "score": nw.score,
+                    "text": text,
+                    "metadata": getattr(base, "metadata", {}) or {},
+                }
+                result["nodes"].append(node_data)
             else:
                 logging.debug(
                     f"Skipping node of type {type(node).__name__}, expected NodeWithScore"
                 )

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In scripts/query_rag.py around lines 105–117, the loop currently assumes
NodeWithScore exposes node_id/text/metadata directly and uses a "# type:
ignore"; change it to handle both wrapper and plain Node without ignoring types:
if isinstance(node, NodeWithScore) set inner = node.node else set inner = node,
then read inner.node_id, inner.score (from wrapper), inner.text and
inner.metadata; remove the "# type: ignore" comment and ensure you use the
wrapper's score when present so the code works for llama-index 0.12+ and earlier
versions.

Copy link
Collaborator

@tisnik tisnik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why they are changes made in source code? Should not it be just one line in pyproject.toml and re-generated uv.lock?

Copy link
Collaborator

@tisnik tisnik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants