Skip to content

fix(chat): repair chain wiring and context handling#770

Merged
stranske merged 2 commits intomainfrom
codex/pretest-gap-fixes
Mar 16, 2026
Merged

fix(chat): repair chain wiring and context handling#770
stranske merged 2 commits intomainfrom
codex/pretest-gap-fixes

Conversation

@stranske
Copy link
Copy Markdown
Owner

Summary\n- repair chat chain construction/invocation so filing summary, holdings analysis, NL query, and RAG use the real chain contracts\n- normalize request context and propagate manager/date/cusip filters into NL query and RAG flows\n- add regression coverage for adapter-level routing and Postgres-safe RAG structured queries\n\n## Validation\n- python -m ruff check api/chat.py chains/nl_query.py chains/rag_search.py tests/test_chat_api.py tests/test_nl_query_chain.py tests/test_rag_search_chain.py\n- python -m black --check api/chat.py chains/nl_query.py chains/rag_search.py tests/test_chat_api.py tests/test_nl_query_chain.py tests/test_rag_search_chain.py\n- python -m pytest -q tests/test_chat_api.py tests/test_nl_query_chain.py tests/test_rag_search_chain.py\n- python -m pytest -q tests/test_feedback.py tests/test_research_ui.py tests/test_search.py\n- python -m mypy api/chat.py chains/nl_query.py chains/rag_search.py tests/test_chat_api.py tests/test_nl_query_chain.py tests/test_rag_search_chain.py tests/test_feedback.py tests/test_research_ui.py tests/test_search.py\n

- [x] construct real chat chains with the right dependencies\n- [x] normalize and propagate request context into NL query and RAG paths\n- [x] make RAG structured lookups work on Postgres placeholders\n- [x] add adapter-level regression coverage for chat routing
Copilot AI review requested due to automatic review settings March 16, 2026 00:54
@agents-workflows-bot
Copy link
Copy Markdown
Contributor

⚠️ Action Required: Unable to determine source issue for PR #770. The PR title, branch name, or body must contain the issue number (e.g. #123, branch: issue-123, or the hidden marker ).

@agents-workflows-bot
Copy link
Copy Markdown
Contributor

agents-workflows-bot bot commented Mar 16, 2026

🤖 Keepalive Loop Status

PR #770 | Agent: Codex | Iteration 0/5

Current State

Metric Value
Iteration progress [----------] 0/5
Action wait (missing-agent-label)
Disposition skipped (transient)
Gate success
Tasks 0/0 complete
Timeout 45 min (default)
Timeout usage 2m elapsed (5%, 43m remaining)
Keepalive ❌ disabled
Autofix ❌ disabled

🔍 Failure Classification

| Error type | infrastructure |
| Error category | resource |
| Suggested recovery | Confirm the referenced resource exists (repo, PR, branch, workflow, or file). |

@agents-workflows-bot
Copy link
Copy Markdown
Contributor

agents-workflows-bot bot commented Mar 16, 2026

Keepalive Work Log (click to expand)
# Time (UTC) Agent Action Result Files Tasks Progress Commit Gate
0 2026-03-16 00:56:49 Codex wait (missing-agent-label-transient) skipped 0 0/0 success
0 2026-03-16 01:07:29 Codex wait (missing-agent-label-transient) skipped 0 0/0 success

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Repairs chat-chain construction and context propagation so the chat API routes into the “real” chain contracts and carries manager/date/cusip filters into NL-to-SQL and RAG flows, with regression tests around adapter routing and Postgres-safe structured queries.

Changes:

  • Update api/chat.py chain building/running to normalize context and route filing-summary / holdings-analysis via their intended contracts.
  • Enhance chains/rag_search.py structured retrieval to support Postgres placeholders + optional table probing and merge explicit context filters.
  • Extend chains/nl_query.py prompts to include context filters; add regression tests for prompt/filter behavior and Postgres placeholder usage.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
api/chat.py Normalizes request context, adjusts chain selection, and rewires chain instantiation/invocation.
chains/rag_search.py Adds DB-dialect placeholders, optional table checks, and context merge into structured search.
chains/nl_query.py Injects context filters into the NL-to-SQL prompt text.
tests/test_chat_api.py Adds regression tests for direct endpoints wiring + auto fallback routing.
tests/test_rag_search_chain.py Adds regression tests for Postgres placeholder usage and explicit context filters.
tests/test_nl_query_chain.py Adds regression test ensuring context filters appear in the prompt.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +752 to +758
if chain_name == "filing_summary":
filing_id = normalized_context.get("filing_id")
try:
if filing_id is None:
raise TypeError("missing filing_id")
result = chain.run(int(cast(Any, filing_id)))
except (TypeError, ValueError) as exc:
Comment on lines +763 to +769
elif chain_name == "holdings_analysis":
result = chain.run(
question,
manager_ids=_normalize_manager_ids(normalized_context.get("manager_ids")) or None,
cusips=_normalize_cusips(normalized_context.get("cusips")) or None,
date_range=_parse_date_range(normalized_context.get("date_range")),
)
Comment on lines 609 to +624
def _build_chain(chain_name: str, client_info: Any):
"""Instantiate a chain by name, falling back to local stubs when missing."""
module_path, class_name = DIRECT_CHAIN_PATHS[chain_name]
try:
module = importlib.import_module(module_path)
chain_cls = getattr(module, class_name)
except Exception:
chain_cls = FALLBACK_CHAINS[chain_name]
return FALLBACK_CHAINS[chain_name]()

db_conn = connect_db()
try:
return chain_cls(client_info.client if client_info else None)
if chain_name == "filing_summary":
return chain_cls(client_info=client_info, db_conn=db_conn)
if chain_name == "holdings_analysis":
return chain_cls(client_info=client_info, db_conn=db_conn)
return chain_cls(llm=client_info.client if client_info else None, db_conn=db_conn)
filters.append(f"- Restrict results to cusips={cusips}")
if not filters:
return ""
return "Context filters:\n" + "\n".join(filters) + "\n"
- [x] format structured filing and holdings results for ChatResponse\n- [x] align fallback chain signatures with real chain contracts\n- [x] guard context-derived prompt inputs against injection\n- [x] add regression coverage for review-raised edge cases
@stranske
Copy link
Copy Markdown
Owner Author

Addressed the Copilot review items in 681a516.\n\nChanges made:\n- format real filing-summary and holdings-analysis model results into non-empty text\n- align local fallback chain signatures with the real chain contracts used by \n- apply prompt-injection guards to context-derived NL query and RAG inputs, not just the primary question\n- add regression tests for the structured-response formatting, fallback signatures, and context-injection paths\n\nLocal validation rerun after the patch:\n- All checks passed!\n- \n- ........................................................................ [ 82%]
............... [100%]
=============================== warnings summary ===============================
../../../../../../../../opt/anaconda3/lib/python3.12/site-packages/langsmith/evaluation/_runner.py:56
/opt/anaconda3/lib/python3.12/site-packages/langsmith/evaluation/_runner.py:56: DeprecationWarning: ast.Str is deprecated and will be removed in Python 3.14; use ast.Constant instead
(ast.Str, ast.Constant) if hasattr(ast, "Str") else (ast.Constant,)

api/chat.py:1185
/Users/teacher/Library/CloudStorage/Dropbox/Learning/Code/Manager-Database-fixes-chat/api/chat.py:1185: DeprecationWarning:
on_event is deprecated, use lifespan event handlers instead.

      Read more about it in the
      [FastAPI docs for Lifespan Events](https://fastapi.tiangolo.com/advanced/events/).
      
@app.on_event("startup")

../../../../../../../../opt/anaconda3/lib/python3.12/site-packages/fastapi/applications.py:4599
../../../../../../../../opt/anaconda3/lib/python3.12/site-packages/fastapi/applications.py:4599
../../../../../../../../opt/anaconda3/lib/python3.12/site-packages/fastapi/applications.py:4599
/opt/anaconda3/lib/python3.12/site-packages/fastapi/applications.py:4599: DeprecationWarning:
on_event is deprecated, use lifespan event handlers instead.

      Read more about it in the
      [FastAPI docs for Lifespan Events](https://fastapi.tiangolo.com/advanced/events/).
      
return self.router.on_event(event_type)

api/chat.py:1480
/Users/teacher/Library/CloudStorage/Dropbox/Learning/Code/Manager-Database-fixes-chat/api/chat.py:1480: DeprecationWarning:
on_event is deprecated, use lifespan event handlers instead.

      Read more about it in the
      [FastAPI docs for Lifespan Events](https://fastapi.tiangolo.com/advanced/events/).
      
@app.on_event("shutdown")

api/chat.py:1487
/Users/teacher/Library/CloudStorage/Dropbox/Learning/Code/Manager-Database-fixes-chat/api/chat.py:1487: DeprecationWarning:
on_event is deprecated, use lifespan event handlers instead.

      Read more about it in the
      [FastAPI docs for Lifespan Events](https://fastapi.tiangolo.com/advanced/events/).
      
@app.on_event("shutdown")

../../../../../../../../opt/anaconda3/lib/python3.12/site-packages/huggingface_hub/file_download.py:943
/opt/anaconda3/lib/python3.12/site-packages/huggingface_hub/file_download.py:943: FutureWarning: resume_download is deprecated and will be removed in version 1.0.0. Downloads always resume when possible. If you want to force a new download, use force_download=True.
warnings.warn(

:488
:488: DeprecationWarning: Type google.protobuf.pyext._message.ScalarMapContainer uses PyType_Spec with a metaclass that has custom tp_new. This is deprecated and will no longer be allowed in Python 3.14.

:488
:488: DeprecationWarning: Type google.protobuf.pyext._message.MessageMapContainer uses PyType_Spec with a metaclass that has custom tp_new. This is deprecated and will no longer be allowed in Python 3.14.

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html\n- tests/test_research_ui.py:58: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked]
tests/test_research_ui.py:60: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked]
tests/test_research_ui.py:61: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked]
tests/test_research_ui.py:62: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked]
tests/test_research_ui.py:63: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked]
tests/test_research_ui.py:64: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked]
tests/test_research_ui.py:65: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked]
tests/test_research_ui.py:66: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked]
tests/test_rag_search_chain.py:144: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked]
tests/test_search.py:38: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked]
tests/test_search.py:615: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked]
tests/test_search.py:634: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked]
tests/test_search.py:635: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked]
tests/test_search.py:636: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked]
tests/test_search.py:637: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked]
tests/test_chat_api.py:247: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked]
tests/test_chat_api.py:279: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked]
tests/test_chat_api.py:300: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked]
tests/test_chat_api.py:337: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked]
tests/test_chat_api.py:414: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked]
tests/test_chat_api.py:482: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked]
Success: no issues found in 9 source files

@stranske
Copy link
Copy Markdown
Owner Author

Addressed the Copilot review items in 681a516.

Changes made:

  • format real filing-summary and holdings-analysis model results into non-empty ChatResponse answers
  • align local fallback chain signatures with the real chain contracts used by _run_chain
  • apply prompt-injection guards to context-derived NL query and RAG inputs, not just the primary question
  • add regression tests for the structured-response formatting, fallback signatures, and context-injection paths

Local validation rerun after the patch:

  • python -m ruff check api/chat.py chains/nl_query.py chains/rag_search.py tests/test_chat_api.py tests/test_nl_query_chain.py tests/test_rag_search_chain.py
  • python -m black --check api/chat.py chains/nl_query.py chains/rag_search.py tests/test_chat_api.py tests/test_nl_query_chain.py tests/test_rag_search_chain.py
  • python -m pytest -q tests/test_chat_api.py tests/test_nl_query_chain.py tests/test_rag_search_chain.py tests/test_feedback.py tests/test_research_ui.py tests/test_search.py
  • python -m mypy api/chat.py chains/nl_query.py chains/rag_search.py tests/test_chat_api.py tests/test_nl_query_chain.py tests/test_rag_search_chain.py tests/test_feedback.py tests/test_research_ui.py tests/test_search.py

@stranske stranske merged commit 581989c into main Mar 16, 2026
39 checks passed
@stranske stranske deleted the codex/pretest-gap-fixes branch March 16, 2026 01:13
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