Unpin langgraph stack; upgrade langchain-core instead (#14)
Unit Tests / test (push) Successful in 9s

Closes #10

## Summary
- Remove force-pins on `langgraph==1.0.4` / `langgraph-checkpoint==3.0.1` / `langgraph-prebuilt==1.0.5` / `langgraph-sdk==0.2.14`
- Upgrade langchain stack so current langgraph-checkpoint (4.x) works with `Reviver(allowed_objects=...)`
- Keep direct `langgraph>=1.2.5,<1.3.0` (matches langchain 1.3.x); checkpoint/prebuilt/sdk resolve transitively
- Adapt `BaseMessage.text()` → `.text` property for langchain-core 1.5.x

## Resolved versions (uv.lock)
| Package | Before | After |
|---|---|---|
| langchain-core | 1.1.1 | 1.5.1 |
| langchain | 1.1.2 | 1.3.14 |
| langgraph | 1.0.4 | 1.2.9 |
| langgraph-checkpoint | 3.0.1 | 4.1.1 |
| langgraph-prebuilt | 1.0.5 | 1.1.0 |
| langgraph-sdk | 0.2.14 | 0.4.2 |

## Test plan
- [x] `uv sync --frozen`
- [x] `uv run python manage.py test` — 248 OK (6 skipped)
- [x] Import `consumers_graph` CompiledStateGraph OK
- [x] Confirm `Reviver.__init__` accepts `allowed_objects`
- [ ] Manual smoke: WebSocket chat + graph path (`consumers_graph`)

## References
- Issue: #10
- Prior pin: #9Reviewed-on: #14
This commit was merged in pull request #14.
This commit is contained in:
2026-07-26 05:11:39 -07:00
parent 0525f9559b
commit 85637e3db6
4 changed files with 97 additions and 135 deletions
+2 -2
View File
@@ -126,7 +126,7 @@ class AsyncLLMService(LLMService):
# return "\n".join(
# f"{'User' if prompt.is_user else 'AI'}: {prompt.text}" for prompt in prompts
# )
return "\n".join([f"{"User" if prompt.type=="human" else "AI"}: {prompt.text()}" for prompt in conversation])
return "\n".join([f"{"User" if prompt.type=="human" else "AI"}: {prompt.text}" for prompt in conversation])
async def _get_recent_messages(self, conversation: list) -> str:
"""Async version of format conversation history."""
@@ -139,7 +139,7 @@ class AsyncLLMService(LLMService):
# return "\n".join(
# f"{'User' if prompt.is_user else 'AI'}: {prompt.text}" for prompt in prompts
# )
return "\n".join([f"{"User" if prompt.type=="human" else "AI"}: {prompt.text()}" for prompt in conversation])
return "\n".join([f"{"User" if prompt.type=="human" else "AI"}: {prompt.text}" for prompt in conversation])
async def generate_response(
self, conversation: Conversation, query: str, conversation_id: int, **kwargs
+1 -1
View File
@@ -330,7 +330,7 @@ class AsyncRAGService(RAGService):
"""Format conversation history for the prompt."""
return "\n".join(
[
f'{"User" if prompt.type == "human" else "AI"}: {prompt.text()}'
f'{"User" if prompt.type == "human" else "AI"}: {prompt.text}'
for prompt in conversation
]
)