youngjin-langchain-tools 0.1.2__tar.gz → 0.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {youngjin_langchain_tools-0.1.2 → youngjin_langchain_tools-0.1.3}/PKG-INFO +1 -1
- {youngjin_langchain_tools-0.1.2 → youngjin_langchain_tools-0.1.3}/pyproject.toml +1 -1
- {youngjin_langchain_tools-0.1.2 → youngjin_langchain_tools-0.1.3}/youngjin_langchain_tools/handlers/streamlit_langgraph_handler.py +78 -3
- {youngjin_langchain_tools-0.1.2 → youngjin_langchain_tools-0.1.3}/.gitignore +0 -0
- {youngjin_langchain_tools-0.1.2 → youngjin_langchain_tools-0.1.3}/LICENSE +0 -0
- {youngjin_langchain_tools-0.1.2 → youngjin_langchain_tools-0.1.3}/README.md +0 -0
- {youngjin_langchain_tools-0.1.2 → youngjin_langchain_tools-0.1.3}/youngjin_langchain_tools/__init__.py +0 -0
- {youngjin_langchain_tools-0.1.2 → youngjin_langchain_tools-0.1.3}/youngjin_langchain_tools/handlers/__init__.py +0 -0
- {youngjin_langchain_tools-0.1.2 → youngjin_langchain_tools-0.1.3}/youngjin_langchain_tools/utils/__init__.py +0 -0
- {youngjin_langchain_tools-0.1.2 → youngjin_langchain_tools-0.1.3}/youngjin_langchain_tools/utils/config.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: youngjin-langchain-tools
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: LangGraph utilities for Streamlit - StreamlitLanggraphHandler and more
|
|
5
5
|
Project-URL: Homepage, https://github.com/yourusername/youngjin-langchain-tools
|
|
6
6
|
Project-URL: Documentation, https://github.com/yourusername/youngjin-langchain-tools#readme
|
|
@@ -8,8 +8,8 @@ LangGraph agent responses in Streamlit applications.
|
|
|
8
8
|
Replaces the deprecated StreamlitCallbackHandler for LangGraph-based agents.
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
-
from typing import Any, Dict, List, Optional,
|
|
12
|
-
from dataclasses import dataclass
|
|
11
|
+
from typing import Any, Dict, List, Optional, Generator
|
|
12
|
+
from dataclasses import dataclass
|
|
13
13
|
import logging
|
|
14
14
|
import re
|
|
15
15
|
|
|
@@ -129,6 +129,13 @@ class StreamlitLanggraphHandlerConfig:
|
|
|
129
129
|
expand_new_thoughts: bool = True
|
|
130
130
|
"""Whether to expand the status container to show tool calls."""
|
|
131
131
|
|
|
132
|
+
collapse_completed_thoughts: bool = True
|
|
133
|
+
"""Whether to automatically collapse completed thought containers."""
|
|
134
|
+
|
|
135
|
+
max_thought_containers: int = 4
|
|
136
|
+
"""Maximum number of thought containers to show at once.
|
|
137
|
+
When exceeded, oldest thoughts are moved to a 'History' expander."""
|
|
138
|
+
|
|
132
139
|
max_tool_content_length: int = 2000
|
|
133
140
|
"""Maximum length of tool output to display before truncating."""
|
|
134
141
|
|
|
@@ -202,6 +209,8 @@ class StreamlitLanggraphHandler:
|
|
|
202
209
|
container: Any,
|
|
203
210
|
*,
|
|
204
211
|
expand_new_thoughts: bool = True,
|
|
212
|
+
collapse_completed_thoughts: bool = True,
|
|
213
|
+
max_thought_containers: int = 4,
|
|
205
214
|
max_tool_content_length: int = 2000,
|
|
206
215
|
show_tool_calls: bool = True,
|
|
207
216
|
show_tool_results: bool = True,
|
|
@@ -217,6 +226,11 @@ class StreamlitLanggraphHandler:
|
|
|
217
226
|
Usually st.container() or similar.
|
|
218
227
|
expand_new_thoughts: Whether to expand status container
|
|
219
228
|
to show tool calls. Defaults to True.
|
|
229
|
+
collapse_completed_thoughts: Whether to collapse completed
|
|
230
|
+
thought containers. Defaults to True.
|
|
231
|
+
max_thought_containers: Maximum number of thought containers
|
|
232
|
+
to show at once. Oldest are moved to
|
|
233
|
+
'History' expander. Defaults to 4.
|
|
220
234
|
max_tool_content_length: Maximum characters of tool output
|
|
221
235
|
to display. Defaults to 2000.
|
|
222
236
|
show_tool_calls: Whether to show tool call info. Defaults to True.
|
|
@@ -230,6 +244,8 @@ class StreamlitLanggraphHandler:
|
|
|
230
244
|
else:
|
|
231
245
|
self._config = StreamlitLanggraphHandlerConfig(
|
|
232
246
|
expand_new_thoughts=expand_new_thoughts,
|
|
247
|
+
collapse_completed_thoughts=collapse_completed_thoughts,
|
|
248
|
+
max_thought_containers=max_thought_containers,
|
|
233
249
|
max_tool_content_length=max_tool_content_length,
|
|
234
250
|
show_tool_calls=show_tool_calls,
|
|
235
251
|
show_tool_results=show_tool_results,
|
|
@@ -241,6 +257,9 @@ class StreamlitLanggraphHandler:
|
|
|
241
257
|
self._final_response: str = ""
|
|
242
258
|
self._status_container: Any = None
|
|
243
259
|
self._response_placeholder: Any = None
|
|
260
|
+
self._history_placeholder: Any = None # Placeholder for history expander
|
|
261
|
+
self._thought_history: List[Dict[str, Any]] = [] # History of old thoughts
|
|
262
|
+
self._current_thoughts: List[Dict[str, Any]] = [] # Current visible thoughts
|
|
244
263
|
|
|
245
264
|
@property
|
|
246
265
|
def config(self) -> StreamlitLanggraphHandlerConfig:
|
|
@@ -332,9 +351,13 @@ class StreamlitLanggraphHandler:
|
|
|
332
351
|
|
|
333
352
|
# Reset state
|
|
334
353
|
self._final_response = ""
|
|
354
|
+
self._thought_history = []
|
|
355
|
+
self._current_thoughts = []
|
|
335
356
|
|
|
336
357
|
# Create UI components
|
|
337
358
|
with self._container:
|
|
359
|
+
# History expander placeholder (will be shown when needed)
|
|
360
|
+
self._history_placeholder = st.empty()
|
|
338
361
|
self._status_container = st.status(
|
|
339
362
|
self._config.thinking_label,
|
|
340
363
|
expanded=self._config.expand_new_thoughts
|
|
@@ -405,6 +428,50 @@ class StreamlitLanggraphHandler:
|
|
|
405
428
|
|
|
406
429
|
yield {"type": "complete", "data": {"response": self._final_response}}
|
|
407
430
|
|
|
431
|
+
def _add_thought(self, thought_type: str, data: Dict[str, Any]) -> None:
|
|
432
|
+
"""Add a thought and manage history if max_thought_containers exceeded."""
|
|
433
|
+
import streamlit as st
|
|
434
|
+
|
|
435
|
+
thought = {"type": thought_type, "data": data}
|
|
436
|
+
self._current_thoughts.append(thought)
|
|
437
|
+
|
|
438
|
+
# Check if we need to move old thoughts to history
|
|
439
|
+
max_containers = self._config.max_thought_containers
|
|
440
|
+
if len(self._current_thoughts) > max_containers:
|
|
441
|
+
# Move oldest thoughts to history
|
|
442
|
+
while len(self._current_thoughts) > max_containers:
|
|
443
|
+
old_thought = self._current_thoughts.pop(0)
|
|
444
|
+
self._thought_history.append(old_thought)
|
|
445
|
+
|
|
446
|
+
# Update history expander
|
|
447
|
+
self._update_history_expander()
|
|
448
|
+
|
|
449
|
+
def _update_history_expander(self) -> None:
|
|
450
|
+
"""Update the history expander with old thoughts."""
|
|
451
|
+
import streamlit as st
|
|
452
|
+
|
|
453
|
+
if not self._thought_history:
|
|
454
|
+
return
|
|
455
|
+
|
|
456
|
+
with self._history_placeholder.container():
|
|
457
|
+
with st.expander(f"📜 History ({len(self._thought_history)} items)", expanded=False):
|
|
458
|
+
for thought in self._thought_history:
|
|
459
|
+
if thought["type"] == "tool_call":
|
|
460
|
+
st.markdown(
|
|
461
|
+
f"{self._config.tool_call_emoji} "
|
|
462
|
+
f"**{thought['data']['name']}**: `{thought['data']['args']}`"
|
|
463
|
+
)
|
|
464
|
+
elif thought["type"] == "tool_result":
|
|
465
|
+
st.markdown(
|
|
466
|
+
f"{self._config.tool_complete_emoji} "
|
|
467
|
+
f"**{thought['data']['name']}** 완료"
|
|
468
|
+
)
|
|
469
|
+
content = thought['data']['content']
|
|
470
|
+
if len(content) > 200: # Shorter preview in history
|
|
471
|
+
st.code(content[:200] + "\n... (truncated)", language="text")
|
|
472
|
+
else:
|
|
473
|
+
st.code(content, language="text")
|
|
474
|
+
|
|
408
475
|
def _handle_updates(
|
|
409
476
|
self,
|
|
410
477
|
data: Dict[str, Any]
|
|
@@ -428,6 +495,9 @@ class StreamlitLanggraphHandler:
|
|
|
428
495
|
tool_name = tc.get('name', 'tool')
|
|
429
496
|
tool_args = tc.get('args', {})
|
|
430
497
|
|
|
498
|
+
# Add to thought tracking
|
|
499
|
+
self._add_thought("tool_call", {"name": tool_name, "args": tool_args})
|
|
500
|
+
|
|
431
501
|
with self._status_container:
|
|
432
502
|
st.write(
|
|
433
503
|
f"{self._config.tool_call_emoji} "
|
|
@@ -445,12 +515,17 @@ class StreamlitLanggraphHandler:
|
|
|
445
515
|
tool_name = msg.name
|
|
446
516
|
tool_content = str(msg.content) if hasattr(msg, 'content') else ""
|
|
447
517
|
|
|
518
|
+
# Add to thought tracking
|
|
519
|
+
self._add_thought("tool_result", {"name": tool_name, "content": tool_content})
|
|
520
|
+
|
|
448
521
|
with self._status_container:
|
|
449
522
|
st.write(
|
|
450
523
|
f"{self._config.tool_complete_emoji} "
|
|
451
524
|
f"**{tool_name}** 완료"
|
|
452
525
|
)
|
|
453
|
-
|
|
526
|
+
# Collapse based on config
|
|
527
|
+
expanded = not self._config.collapse_completed_thoughts
|
|
528
|
+
with st.expander(f"📋 {tool_name} 결과 보기", expanded=expanded):
|
|
454
529
|
if len(tool_content) > self._config.max_tool_content_length:
|
|
455
530
|
st.code(
|
|
456
531
|
tool_content[:self._config.max_tool_content_length]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|