youngjin-langchain-tools 0.1.4__py3-none-any.whl → 0.2.0__py3-none-any.whl
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/handlers/streamlit_langgraph_handler.py +94 -59
- {youngjin_langchain_tools-0.1.4.dist-info → youngjin_langchain_tools-0.2.0.dist-info}/METADATA +1 -1
- {youngjin_langchain_tools-0.1.4.dist-info → youngjin_langchain_tools-0.2.0.dist-info}/RECORD +5 -5
- {youngjin_langchain_tools-0.1.4.dist-info → youngjin_langchain_tools-0.2.0.dist-info}/WHEEL +0 -0
- {youngjin_langchain_tools-0.1.4.dist-info → youngjin_langchain_tools-0.2.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -124,13 +124,22 @@ def _parse_error(error: Exception) -> Dict[str, Any]:
|
|
|
124
124
|
|
|
125
125
|
@dataclass
|
|
126
126
|
class StreamlitLanggraphHandlerConfig:
|
|
127
|
-
"""Configuration for StreamlitLanggraphHandler.
|
|
127
|
+
"""Configuration for StreamlitLanggraphHandler.
|
|
128
|
+
|
|
129
|
+
Attributes:
|
|
130
|
+
expand_new_thoughts: 도구 결과 expander를 펼친 상태로 표시할지 여부.
|
|
131
|
+
collapse_completed_thoughts: 완료 시 status container를 접을지 여부.
|
|
132
|
+
max_thought_containers: 표시할 최대 사고 과정 수 (초과 시 History로 이동).
|
|
133
|
+
max_tool_content_length: 도구 결과 최대 표시 문자 수.
|
|
134
|
+
show_tool_calls: 도구 호출 정보 표시 여부.
|
|
135
|
+
show_tool_results: 도구 실행 결과 표시 여부.
|
|
136
|
+
"""
|
|
128
137
|
|
|
129
138
|
expand_new_thoughts: bool = True
|
|
130
|
-
"""Whether to
|
|
139
|
+
"""Whether to show tool result expanders in expanded state."""
|
|
131
140
|
|
|
132
141
|
collapse_completed_thoughts: bool = True
|
|
133
|
-
"""Whether to
|
|
142
|
+
"""Whether to collapse the status container when agent completes."""
|
|
134
143
|
|
|
135
144
|
max_thought_containers: int = 4
|
|
136
145
|
"""Maximum number of thought containers to show at once.
|
|
@@ -257,9 +266,9 @@ class StreamlitLanggraphHandler:
|
|
|
257
266
|
self._final_response: str = ""
|
|
258
267
|
self._status_container: Any = None
|
|
259
268
|
self._response_placeholder: Any = None
|
|
260
|
-
self._thoughts_placeholder: Any = None # Placeholder for thoughts area
|
|
261
269
|
self._thought_history: List[Dict[str, Any]] = [] # History of old thoughts
|
|
262
270
|
self._current_thoughts: List[Dict[str, Any]] = [] # Current visible thoughts
|
|
271
|
+
self._thought_counter: int = 0 # Unique ID counter for thoughts
|
|
263
272
|
|
|
264
273
|
@property
|
|
265
274
|
def config(self) -> StreamlitLanggraphHandlerConfig:
|
|
@@ -353,24 +362,23 @@ class StreamlitLanggraphHandler:
|
|
|
353
362
|
self._final_response = ""
|
|
354
363
|
self._thought_history = []
|
|
355
364
|
self._current_thoughts = []
|
|
365
|
+
self._thought_counter = 0
|
|
356
366
|
|
|
357
367
|
# Create UI components
|
|
358
368
|
with self._container:
|
|
359
|
-
# Thoughts area placeholder (manages history + current thoughts)
|
|
360
|
-
self._thoughts_placeholder = st.empty()
|
|
361
369
|
self._status_container = st.status(
|
|
362
370
|
self._config.thinking_label,
|
|
363
|
-
expanded=
|
|
371
|
+
expanded=True # Always start expanded during processing
|
|
364
372
|
)
|
|
365
373
|
self._response_placeholder = st.empty()
|
|
366
374
|
|
|
367
375
|
# Stream from agent with error handling
|
|
368
|
-
|
|
376
|
+
agent_config = config or {}
|
|
369
377
|
|
|
370
378
|
try:
|
|
371
379
|
for stream_mode, data in agent.stream(
|
|
372
380
|
input,
|
|
373
|
-
config=
|
|
381
|
+
config=agent_config,
|
|
374
382
|
stream_mode=["messages", "updates"]
|
|
375
383
|
):
|
|
376
384
|
if stream_mode == "updates":
|
|
@@ -378,11 +386,11 @@ class StreamlitLanggraphHandler:
|
|
|
378
386
|
elif stream_mode == "messages":
|
|
379
387
|
yield from self._handle_messages(data)
|
|
380
388
|
|
|
381
|
-
# Mark as complete
|
|
389
|
+
# Mark as complete - collapse based on config
|
|
382
390
|
self._status_container.update(
|
|
383
391
|
label=self._config.complete_label,
|
|
384
392
|
state="complete",
|
|
385
|
-
expanded=
|
|
393
|
+
expanded=not self._config.collapse_completed_thoughts
|
|
386
394
|
)
|
|
387
395
|
|
|
388
396
|
except Exception as e:
|
|
@@ -430,67 +438,84 @@ class StreamlitLanggraphHandler:
|
|
|
430
438
|
|
|
431
439
|
def _add_thought(self, thought_type: str, data: Dict[str, Any]) -> None:
|
|
432
440
|
"""Add a thought and manage history if max_thought_containers exceeded."""
|
|
433
|
-
|
|
441
|
+
self._thought_counter += 1
|
|
442
|
+
thought = {
|
|
443
|
+
"id": self._thought_counter,
|
|
444
|
+
"type": thought_type,
|
|
445
|
+
"data": data
|
|
446
|
+
}
|
|
434
447
|
self._current_thoughts.append(thought)
|
|
435
448
|
|
|
436
449
|
# Check if we need to move old thoughts to history
|
|
437
450
|
max_containers = self._config.max_thought_containers
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
old_thought = self._current_thoughts.pop(0)
|
|
442
|
-
self._thought_history.append(old_thought)
|
|
451
|
+
while len(self._current_thoughts) > max_containers:
|
|
452
|
+
old_thought = self._current_thoughts.pop(0)
|
|
453
|
+
self._thought_history.append(old_thought)
|
|
443
454
|
|
|
444
|
-
|
|
445
|
-
self
|
|
455
|
+
def _render_thought_item(
|
|
456
|
+
self,
|
|
457
|
+
thought: Dict[str, Any],
|
|
458
|
+
st_module: Any,
|
|
459
|
+
in_history: bool = False
|
|
460
|
+
) -> None:
|
|
461
|
+
"""Render a single thought item.
|
|
446
462
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
463
|
+
Args:
|
|
464
|
+
thought: The thought dict with id, type, data.
|
|
465
|
+
st_module: The streamlit module reference.
|
|
466
|
+
in_history: Whether this thought is in history section.
|
|
467
|
+
"""
|
|
468
|
+
thought_type = thought["type"]
|
|
469
|
+
thought_data = thought["data"]
|
|
470
|
+
|
|
471
|
+
if thought_type == "tool_call":
|
|
472
|
+
# Tool call display: 🔧 tool_name: {args}
|
|
473
|
+
st_module.markdown(
|
|
474
|
+
f"{self._config.tool_call_emoji} "
|
|
475
|
+
f"**{thought_data['name']}**: `{thought_data['args']}`"
|
|
476
|
+
)
|
|
450
477
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
f"**{thought['data']['name']}**: `{thought['data']['args']}`"
|
|
456
|
-
)
|
|
457
|
-
elif thought["type"] == "tool_result":
|
|
458
|
-
if self._config.show_tool_results:
|
|
459
|
-
tool_name = thought['data']['name']
|
|
460
|
-
content = thought['data']['content']
|
|
461
|
-
|
|
462
|
-
st.markdown(
|
|
463
|
-
f"{self._config.tool_complete_emoji} "
|
|
464
|
-
f"**{tool_name}** 완료"
|
|
465
|
-
)
|
|
466
|
-
|
|
467
|
-
if in_history:
|
|
468
|
-
# Shorter preview in history
|
|
469
|
-
max_len = 200
|
|
470
|
-
else:
|
|
471
|
-
max_len = self._config.max_tool_content_length
|
|
478
|
+
elif thought_type == "tool_result":
|
|
479
|
+
# Tool result display: ✅ tool_name 완료 + expander
|
|
480
|
+
tool_name = thought_data['name']
|
|
481
|
+
content = thought_data['content']
|
|
472
482
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
else:
|
|
478
|
-
st.code(content, language="text")
|
|
483
|
+
st_module.markdown(
|
|
484
|
+
f"{self._config.tool_complete_emoji} "
|
|
485
|
+
f"**{tool_name}** 완료"
|
|
486
|
+
)
|
|
479
487
|
|
|
480
|
-
|
|
481
|
-
|
|
488
|
+
# Determine max length and expand state
|
|
489
|
+
if in_history:
|
|
490
|
+
max_len = 200
|
|
491
|
+
should_expand = False # History items always collapsed
|
|
492
|
+
else:
|
|
493
|
+
max_len = self._config.max_tool_content_length
|
|
494
|
+
should_expand = self._config.expand_new_thoughts
|
|
495
|
+
|
|
496
|
+
with st_module.expander(f"📋 {tool_name} 결과 보기", expanded=should_expand):
|
|
497
|
+
if len(content) > max_len:
|
|
498
|
+
st_module.code(content[:max_len] + "\n... (truncated)", language="text")
|
|
499
|
+
else:
|
|
500
|
+
st_module.code(content, language="text")
|
|
501
|
+
|
|
502
|
+
def _render_thoughts_in_status(self) -> None:
|
|
503
|
+
"""Render all thoughts (history + current) inside the status container."""
|
|
482
504
|
import streamlit as st
|
|
483
505
|
|
|
484
|
-
with self.
|
|
506
|
+
with self._status_container:
|
|
485
507
|
# Render history expander if there are old thoughts
|
|
486
508
|
if self._thought_history:
|
|
487
|
-
with st.expander(
|
|
509
|
+
with st.expander(
|
|
510
|
+
f"📜 History ({len(self._thought_history)} items)",
|
|
511
|
+
expanded=False
|
|
512
|
+
):
|
|
488
513
|
for thought in self._thought_history:
|
|
489
|
-
self._render_thought_item(thought, in_history=True)
|
|
514
|
+
self._render_thought_item(thought, st, in_history=True)
|
|
490
515
|
|
|
491
516
|
# Render current thoughts
|
|
492
517
|
for thought in self._current_thoughts:
|
|
493
|
-
self._render_thought_item(thought, in_history=False)
|
|
518
|
+
self._render_thought_item(thought, st, in_history=False)
|
|
494
519
|
|
|
495
520
|
def _handle_updates(
|
|
496
521
|
self,
|
|
@@ -509,8 +534,13 @@ class StreamlitLanggraphHandler:
|
|
|
509
534
|
tool_name = tc.get('name', 'tool')
|
|
510
535
|
tool_args = tc.get('args', {})
|
|
511
536
|
|
|
512
|
-
#
|
|
513
|
-
self.
|
|
537
|
+
# Only add to thoughts if show_tool_calls is True
|
|
538
|
+
if self._config.show_tool_calls:
|
|
539
|
+
self._add_thought(
|
|
540
|
+
"tool_call",
|
|
541
|
+
{"name": tool_name, "args": tool_args}
|
|
542
|
+
)
|
|
543
|
+
self._render_thoughts_in_status()
|
|
514
544
|
|
|
515
545
|
# Update status label to show current action
|
|
516
546
|
self._status_container.update(
|
|
@@ -528,8 +558,13 @@ class StreamlitLanggraphHandler:
|
|
|
528
558
|
tool_name = msg.name
|
|
529
559
|
tool_content = str(msg.content) if hasattr(msg, 'content') else ""
|
|
530
560
|
|
|
531
|
-
#
|
|
532
|
-
self.
|
|
561
|
+
# Only add to thoughts if show_tool_results is True
|
|
562
|
+
if self._config.show_tool_results:
|
|
563
|
+
self._add_thought(
|
|
564
|
+
"tool_result",
|
|
565
|
+
{"name": tool_name, "content": tool_content}
|
|
566
|
+
)
|
|
567
|
+
self._render_thoughts_in_status()
|
|
533
568
|
|
|
534
569
|
# Update status to show thinking again
|
|
535
570
|
self._status_container.update(
|
{youngjin_langchain_tools-0.1.4.dist-info → youngjin_langchain_tools-0.2.0.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: youngjin-langchain-tools
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
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
|
{youngjin_langchain_tools-0.1.4.dist-info → youngjin_langchain_tools-0.2.0.dist-info}/RECORD
RENAMED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
youngjin_langchain_tools/__init__.py,sha256=S5GJtbYymhDuGtTibEG61Li9UvwvoFtnKm4mxjWNgnU,1310
|
|
2
2
|
youngjin_langchain_tools/handlers/__init__.py,sha256=-vGk-m1fqOipJSe02ogcScE0K3pdVwO9A_EqBovPRxo,397
|
|
3
|
-
youngjin_langchain_tools/handlers/streamlit_langgraph_handler.py,sha256=
|
|
3
|
+
youngjin_langchain_tools/handlers/streamlit_langgraph_handler.py,sha256=O2_B5I7E0OWqh1JdS014aGw_smQsCpT7NykxcH16Ql8,22599
|
|
4
4
|
youngjin_langchain_tools/utils/__init__.py,sha256=LgSd7Gz2n5WgIhxaKHqpmQVUaBUDT_TTTw63hzoWGgM,272
|
|
5
5
|
youngjin_langchain_tools/utils/config.py,sha256=hHvdxsn5ZFWRJvR6N7ODy94JbCkeJocsS58hmvxoK5I,1640
|
|
6
|
-
youngjin_langchain_tools-0.
|
|
7
|
-
youngjin_langchain_tools-0.
|
|
8
|
-
youngjin_langchain_tools-0.
|
|
9
|
-
youngjin_langchain_tools-0.
|
|
6
|
+
youngjin_langchain_tools-0.2.0.dist-info/METADATA,sha256=3zKlWZoqhkSKRxhFV89VL08pgwtfYxZgORGKWZM3N4Q,6959
|
|
7
|
+
youngjin_langchain_tools-0.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
8
|
+
youngjin_langchain_tools-0.2.0.dist-info/licenses/LICENSE,sha256=fENUlkDDxJEn5c0u8mhVcz5ek-rTg2L4Kby1tMNchI8,11342
|
|
9
|
+
youngjin_langchain_tools-0.2.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|