hdsp-jupyter-extension 2.0.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.
Files changed (121) hide show
  1. agent_server/__init__.py +8 -0
  2. agent_server/core/__init__.py +92 -0
  3. agent_server/core/api_key_manager.py +427 -0
  4. agent_server/core/code_validator.py +1238 -0
  5. agent_server/core/context_condenser.py +308 -0
  6. agent_server/core/embedding_service.py +254 -0
  7. agent_server/core/error_classifier.py +577 -0
  8. agent_server/core/llm_client.py +95 -0
  9. agent_server/core/llm_service.py +649 -0
  10. agent_server/core/notebook_generator.py +274 -0
  11. agent_server/core/prompt_builder.py +35 -0
  12. agent_server/core/rag_manager.py +742 -0
  13. agent_server/core/reflection_engine.py +489 -0
  14. agent_server/core/retriever.py +248 -0
  15. agent_server/core/state_verifier.py +452 -0
  16. agent_server/core/summary_generator.py +484 -0
  17. agent_server/core/task_manager.py +198 -0
  18. agent_server/knowledge/__init__.py +9 -0
  19. agent_server/knowledge/watchdog_service.py +352 -0
  20. agent_server/main.py +160 -0
  21. agent_server/prompts/__init__.py +60 -0
  22. agent_server/prompts/file_action_prompts.py +113 -0
  23. agent_server/routers/__init__.py +9 -0
  24. agent_server/routers/agent.py +591 -0
  25. agent_server/routers/chat.py +188 -0
  26. agent_server/routers/config.py +100 -0
  27. agent_server/routers/file_resolver.py +293 -0
  28. agent_server/routers/health.py +42 -0
  29. agent_server/routers/rag.py +163 -0
  30. agent_server/schemas/__init__.py +60 -0
  31. hdsp_agent_core/__init__.py +158 -0
  32. hdsp_agent_core/factory.py +252 -0
  33. hdsp_agent_core/interfaces.py +203 -0
  34. hdsp_agent_core/knowledge/__init__.py +31 -0
  35. hdsp_agent_core/knowledge/chunking.py +356 -0
  36. hdsp_agent_core/knowledge/libraries/dask.md +188 -0
  37. hdsp_agent_core/knowledge/libraries/matplotlib.md +164 -0
  38. hdsp_agent_core/knowledge/libraries/polars.md +68 -0
  39. hdsp_agent_core/knowledge/loader.py +337 -0
  40. hdsp_agent_core/llm/__init__.py +13 -0
  41. hdsp_agent_core/llm/service.py +556 -0
  42. hdsp_agent_core/managers/__init__.py +22 -0
  43. hdsp_agent_core/managers/config_manager.py +133 -0
  44. hdsp_agent_core/managers/session_manager.py +251 -0
  45. hdsp_agent_core/models/__init__.py +115 -0
  46. hdsp_agent_core/models/agent.py +316 -0
  47. hdsp_agent_core/models/chat.py +41 -0
  48. hdsp_agent_core/models/common.py +95 -0
  49. hdsp_agent_core/models/rag.py +368 -0
  50. hdsp_agent_core/prompts/__init__.py +63 -0
  51. hdsp_agent_core/prompts/auto_agent_prompts.py +1260 -0
  52. hdsp_agent_core/prompts/cell_action_prompts.py +98 -0
  53. hdsp_agent_core/services/__init__.py +18 -0
  54. hdsp_agent_core/services/agent_service.py +438 -0
  55. hdsp_agent_core/services/chat_service.py +205 -0
  56. hdsp_agent_core/services/rag_service.py +262 -0
  57. hdsp_agent_core/tests/__init__.py +1 -0
  58. hdsp_agent_core/tests/conftest.py +102 -0
  59. hdsp_agent_core/tests/test_factory.py +251 -0
  60. hdsp_agent_core/tests/test_services.py +326 -0
  61. hdsp_jupyter_extension-2.0.0.data/data/etc/jupyter/jupyter_server_config.d/hdsp_jupyter_extension.json +7 -0
  62. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/build_log.json +738 -0
  63. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/install.json +5 -0
  64. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/package.json +134 -0
  65. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/frontend_styles_index_js.2607ff74c74acfa83158.js +4369 -0
  66. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/frontend_styles_index_js.2607ff74c74acfa83158.js.map +1 -0
  67. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/lib_index_js.622c1a5918b3aafb2315.js +12496 -0
  68. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/lib_index_js.622c1a5918b3aafb2315.js.map +1 -0
  69. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/node_modules_emotion_use-insertion-effect-with-fallbacks_dist_emotion-use-insertion-effect-wi-3ba6b80.c095373419d05e6f141a.js +94 -0
  70. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/node_modules_emotion_use-insertion-effect-with-fallbacks_dist_emotion-use-insertion-effect-wi-3ba6b80.c095373419d05e6f141a.js.map +1 -0
  71. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/node_modules_emotion_use-insertion-effect-with-fallbacks_dist_emotion-use-insertion-effect-wi-3ba6b81.61e75fb98ecff46cf836.js +94 -0
  72. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/node_modules_emotion_use-insertion-effect-with-fallbacks_dist_emotion-use-insertion-effect-wi-3ba6b81.61e75fb98ecff46cf836.js.map +1 -0
  73. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/remoteEntry.dae97cde171e13b8c834.js +623 -0
  74. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/remoteEntry.dae97cde171e13b8c834.js.map +1 -0
  75. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/style.js +4 -0
  76. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_babel_runtime_helpers_esm_extends_js-node_modules_emotion_serialize_dist-051195.e2553aab0c3963b83dd7.js +507 -0
  77. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_babel_runtime_helpers_esm_extends_js-node_modules_emotion_serialize_dist-051195.e2553aab0c3963b83dd7.js.map +1 -0
  78. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js-node_modules-782ee5.d9ed8645ef1d311657d8.js +2071 -0
  79. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js-node_modules-782ee5.d9ed8645ef1d311657d8.js.map +1 -0
  80. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.36b49c71871f98d4f549.js +1059 -0
  81. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.36b49c71871f98d4f549.js.map +1 -0
  82. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_styled_dist_emotion-styled_browser_development_esm_js.661fb5836f4978a7c6e1.js +376 -0
  83. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_styled_dist_emotion-styled_browser_development_esm_js.661fb5836f4978a7c6e1.js.map +1 -0
  84. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_index_js.985697e0162d8d088ca2.js +60336 -0
  85. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_index_js.985697e0162d8d088ca2.js.map +1 -0
  86. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_utils_createSvgIcon_js.2e13df4ea61496e95d45.js +7132 -0
  87. hdsp_jupyter_extension-2.0.0.data/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_utils_createSvgIcon_js.2e13df4ea61496e95d45.js.map +1 -0
  88. hdsp_jupyter_extension-2.0.0.dist-info/METADATA +152 -0
  89. hdsp_jupyter_extension-2.0.0.dist-info/RECORD +121 -0
  90. hdsp_jupyter_extension-2.0.0.dist-info/WHEEL +4 -0
  91. hdsp_jupyter_extension-2.0.0.dist-info/licenses/LICENSE +21 -0
  92. jupyter_ext/__init__.py +233 -0
  93. jupyter_ext/_version.py +4 -0
  94. jupyter_ext/config.py +111 -0
  95. jupyter_ext/etc/jupyter/jupyter_server_config.d/hdsp_jupyter_extension.json +7 -0
  96. jupyter_ext/handlers.py +632 -0
  97. jupyter_ext/labextension/build_log.json +738 -0
  98. jupyter_ext/labextension/package.json +134 -0
  99. jupyter_ext/labextension/static/frontend_styles_index_js.2607ff74c74acfa83158.js +4369 -0
  100. jupyter_ext/labextension/static/frontend_styles_index_js.2607ff74c74acfa83158.js.map +1 -0
  101. jupyter_ext/labextension/static/lib_index_js.622c1a5918b3aafb2315.js +12496 -0
  102. jupyter_ext/labextension/static/lib_index_js.622c1a5918b3aafb2315.js.map +1 -0
  103. jupyter_ext/labextension/static/node_modules_emotion_use-insertion-effect-with-fallbacks_dist_emotion-use-insertion-effect-wi-3ba6b80.c095373419d05e6f141a.js +94 -0
  104. jupyter_ext/labextension/static/node_modules_emotion_use-insertion-effect-with-fallbacks_dist_emotion-use-insertion-effect-wi-3ba6b80.c095373419d05e6f141a.js.map +1 -0
  105. jupyter_ext/labextension/static/node_modules_emotion_use-insertion-effect-with-fallbacks_dist_emotion-use-insertion-effect-wi-3ba6b81.61e75fb98ecff46cf836.js +94 -0
  106. jupyter_ext/labextension/static/node_modules_emotion_use-insertion-effect-with-fallbacks_dist_emotion-use-insertion-effect-wi-3ba6b81.61e75fb98ecff46cf836.js.map +1 -0
  107. jupyter_ext/labextension/static/remoteEntry.dae97cde171e13b8c834.js +623 -0
  108. jupyter_ext/labextension/static/remoteEntry.dae97cde171e13b8c834.js.map +1 -0
  109. jupyter_ext/labextension/static/style.js +4 -0
  110. jupyter_ext/labextension/static/vendors-node_modules_babel_runtime_helpers_esm_extends_js-node_modules_emotion_serialize_dist-051195.e2553aab0c3963b83dd7.js +507 -0
  111. jupyter_ext/labextension/static/vendors-node_modules_babel_runtime_helpers_esm_extends_js-node_modules_emotion_serialize_dist-051195.e2553aab0c3963b83dd7.js.map +1 -0
  112. jupyter_ext/labextension/static/vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js-node_modules-782ee5.d9ed8645ef1d311657d8.js +2071 -0
  113. jupyter_ext/labextension/static/vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js-node_modules-782ee5.d9ed8645ef1d311657d8.js.map +1 -0
  114. jupyter_ext/labextension/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.36b49c71871f98d4f549.js +1059 -0
  115. jupyter_ext/labextension/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.36b49c71871f98d4f549.js.map +1 -0
  116. jupyter_ext/labextension/static/vendors-node_modules_emotion_styled_dist_emotion-styled_browser_development_esm_js.661fb5836f4978a7c6e1.js +376 -0
  117. jupyter_ext/labextension/static/vendors-node_modules_emotion_styled_dist_emotion-styled_browser_development_esm_js.661fb5836f4978a7c6e1.js.map +1 -0
  118. jupyter_ext/labextension/static/vendors-node_modules_mui_material_index_js.985697e0162d8d088ca2.js +60336 -0
  119. jupyter_ext/labextension/static/vendors-node_modules_mui_material_index_js.985697e0162d8d088ca2.js.map +1 -0
  120. jupyter_ext/labextension/static/vendors-node_modules_mui_material_utils_createSvgIcon_js.2e13df4ea61496e95d45.js +7132 -0
  121. jupyter_ext/labextension/static/vendors-node_modules_mui_material_utils_createSvgIcon_js.2e13df4ea61496e95d45.js.map +1 -0
@@ -0,0 +1,274 @@
1
+ """
2
+ Notebook Generator - Creates Jupyter notebooks from prompts using LLM
3
+ """
4
+
5
+ import json
6
+ import os
7
+ import re
8
+ from datetime import datetime
9
+ from pathlib import Path
10
+ from typing import Any, Dict, List, Optional
11
+
12
+
13
+ class NotebookGenerator:
14
+ """Generate Jupyter notebooks from natural language prompts"""
15
+
16
+ def __init__(self, llm_service, task_manager):
17
+ self.llm_service = llm_service
18
+ self.task_manager = task_manager
19
+
20
+ def _extract_json_from_response(self, response_text: str) -> Optional[Dict]:
21
+ """Extract JSON object from LLM response text"""
22
+ content = response_text.strip()
23
+ json_match = re.search(r"\{.*\}", content, re.DOTALL)
24
+ if json_match:
25
+ try:
26
+ return json.loads(json_match.group())
27
+ except json.JSONDecodeError:
28
+ return None
29
+ return None
30
+
31
+ async def _call_llm_for_json(self, prompt: str, fallback: dict) -> dict:
32
+ """Call LLM and extract JSON response, with fallback"""
33
+ response_text = await self.llm_service.generate_response(prompt)
34
+ result = self._extract_json_from_response(response_text)
35
+ return result if result else fallback
36
+
37
+ def _remove_code_block_markers(self, content: str) -> str:
38
+ """Remove markdown code block markers from content"""
39
+ content = re.sub(r"^```python\n", "", content)
40
+ content = re.sub(r"^```\n", "", content)
41
+ content = re.sub(r"\n```$", "", content)
42
+ return content.strip()
43
+
44
+ async def generate_notebook(
45
+ self, task_id: str, prompt: str, output_dir: str = None
46
+ ) -> str:
47
+ """
48
+ Generate a notebook from a prompt
49
+
50
+ Args:
51
+ task_id: Task ID for progress tracking
52
+ prompt: Natural language prompt for notebook generation
53
+ output_dir: Directory to save the notebook (default: current directory)
54
+
55
+ Returns:
56
+ Path to generated notebook
57
+ """
58
+ try:
59
+ self.task_manager.start_task(task_id)
60
+
61
+ # Step 1: Analyze prompt (10%)
62
+ self.task_manager.update_progress(task_id, 10, "프롬프트 분석 중...")
63
+ analysis = await self._analyze_prompt(prompt)
64
+
65
+ # Step 2: Generate notebook structure (20%)
66
+ self.task_manager.update_progress(task_id, 20, "노트북 구조 생성 중...")
67
+ notebook_plan = await self._create_notebook_plan(prompt, analysis)
68
+
69
+ # Step 3: Generate cells (30-80%)
70
+ self.task_manager.update_progress(task_id, 30, "셀 생성 중...")
71
+ cells = await self._generate_cells(task_id, notebook_plan)
72
+
73
+ # Step 4: Create notebook file (90%)
74
+ self.task_manager.update_progress(task_id, 90, "노트북 저장 중...")
75
+ notebook_path = await self._save_notebook(
76
+ cells, output_dir, analysis.get("title", "generated")
77
+ )
78
+
79
+ # Step 5: Complete (100%)
80
+ self.task_manager.complete_task(task_id, notebook_path)
81
+
82
+ return notebook_path
83
+
84
+ except Exception as e:
85
+ self.task_manager.fail_task(task_id, str(e))
86
+ raise
87
+
88
+ async def _analyze_prompt(self, prompt: str) -> Dict[str, Any]:
89
+ """Analyze the prompt to understand requirements"""
90
+ analysis_prompt = f"""다음 요청을 분석하고 JSON 형식으로 응답해주세요:
91
+
92
+ 요청: {prompt}
93
+
94
+ 다음 정보를 추출해주세요:
95
+ 1. 노트북 제목 (title)
96
+ 2. 주요 작업 목표 (objective)
97
+ 3. 사용할 라이브러리들 (libraries) - 배열
98
+ 4. 예상되는 셀 개수 (estimated_cells)
99
+ 5. 데이터 분석 유형 (analysis_type: exploration, modeling, visualization, etc.)
100
+
101
+ JSON만 응답하세요:"""
102
+
103
+ fallback = {
104
+ "title": "Generated Notebook",
105
+ "objective": prompt,
106
+ "libraries": ["pandas", "numpy"],
107
+ "estimated_cells": 10,
108
+ "analysis_type": "general",
109
+ }
110
+ return await self._call_llm_for_json(analysis_prompt, fallback)
111
+
112
+ async def _create_notebook_plan(
113
+ self, prompt: str, analysis: Dict[str, Any]
114
+ ) -> Dict[str, Any]:
115
+ """Create a structured plan for the notebook"""
116
+ plan_prompt = f"""다음 요청에 대한 Jupyter 노트북 계획을 작성해주세요:
117
+
118
+ 요청: {prompt}
119
+
120
+ 분석 결과:
121
+ - 목표: {analysis['objective']}
122
+ - 라이브러리: {', '.join(analysis['libraries'])}
123
+ - 분석 유형: {analysis['analysis_type']}
124
+
125
+ 노트북의 각 셀에 대한 계획을 JSON 형식으로 작성해주세요:
126
+ {{
127
+ "cells": [
128
+ {{
129
+ "type": "markdown",
130
+ "purpose": "제목 및 개요",
131
+ "content_hint": "간단한 설명"
132
+ }},
133
+ {{
134
+ "type": "code",
135
+ "purpose": "라이브러리 임포트",
136
+ "content_hint": "import 문들"
137
+ }},
138
+ ...
139
+ ]
140
+ }}
141
+
142
+ JSON만 응답하세요:"""
143
+
144
+ fallback = {
145
+ "cells": [
146
+ {
147
+ "type": "markdown",
148
+ "purpose": "제목",
149
+ "content_hint": analysis["title"],
150
+ },
151
+ {
152
+ "type": "code",
153
+ "purpose": "라이브러리 임포트",
154
+ "content_hint": "import pandas, numpy",
155
+ },
156
+ {"type": "code", "purpose": "데이터 로드", "content_hint": "load data"},
157
+ {"type": "code", "purpose": "분석", "content_hint": "analysis code"},
158
+ ]
159
+ }
160
+ return await self._call_llm_for_json(plan_prompt, fallback)
161
+
162
+ async def _generate_cells(
163
+ self, task_id: str, plan: Dict[str, Any]
164
+ ) -> List[Dict[str, Any]]:
165
+ """Generate actual cell content based on plan"""
166
+ cells = []
167
+ planned_cells = plan.get("cells", [])
168
+ total_cells = len(planned_cells)
169
+
170
+ for idx, cell_plan in enumerate(planned_cells):
171
+ # Update progress (30% -> 80%)
172
+ progress = 30 + int((idx / total_cells) * 50)
173
+ self.task_manager.update_progress(
174
+ task_id, progress, f"셀 생성 중... ({idx+1}/{total_cells})"
175
+ )
176
+
177
+ cell_type = cell_plan.get("type", "code")
178
+ purpose = cell_plan.get("purpose", "")
179
+ content_hint = cell_plan.get("content_hint", "")
180
+
181
+ if cell_type == "markdown":
182
+ content = await self._generate_markdown_cell(purpose, content_hint)
183
+ else:
184
+ content = await self._generate_code_cell(purpose, content_hint)
185
+
186
+ # Jupyter notebook source requires each line to end with \n (except the last line)
187
+ lines = content.split("\n")
188
+ source_lines = (
189
+ [line + "\n" for line in lines[:-1]] + [lines[-1]] if lines else []
190
+ )
191
+
192
+ cells.append(
193
+ {"cell_type": cell_type, "metadata": {}, "source": source_lines}
194
+ )
195
+
196
+ # Add execution_count for code cells
197
+ if cell_type == "code":
198
+ cells[-1]["execution_count"] = None
199
+ cells[-1]["outputs"] = []
200
+
201
+ return cells
202
+
203
+ async def _generate_markdown_cell(self, purpose: str, hint: str) -> str:
204
+ """Generate markdown cell content"""
205
+ prompt = f"""다음 Jupyter 노트북 마크다운 셀을 작성해주세요:
206
+
207
+ 목적: {purpose}
208
+ 힌트: {hint}
209
+
210
+ 마크다운만 작성하고, 코드 블록이나 다른 설명 없이 내용만 응답하세요:"""
211
+
212
+ response_text = await self.llm_service.generate_response(prompt)
213
+ return response_text.strip()
214
+
215
+ async def _generate_code_cell(self, purpose: str, hint: str) -> str:
216
+ """Generate code cell content"""
217
+ prompt = f"""다음 Jupyter 노트북 코드 셀을 작성해주세요:
218
+
219
+ 목적: {purpose}
220
+ 힌트: {hint}
221
+
222
+ 실행 가능한 Python 코드만 작성하고, 설명이나 마크다운 없이 코드만 응답하세요.
223
+ 주석은 한국어로 간단히 작성하세요:"""
224
+
225
+ response_text = await self.llm_service.generate_response(prompt)
226
+ return self._remove_code_block_markers(response_text.strip())
227
+
228
+ async def _save_notebook(
229
+ self, cells: List[Dict], output_dir: str, base_name: str
230
+ ) -> str:
231
+ """Save notebook to file"""
232
+ # Prepare output directory
233
+ if output_dir is None:
234
+ output_dir = os.getcwd()
235
+
236
+ output_path = Path(output_dir)
237
+ output_path.mkdir(parents=True, exist_ok=True)
238
+
239
+ # Generate filename
240
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
241
+ safe_name = re.sub(r"[^\w\s-]", "", base_name)
242
+ safe_name = re.sub(r"[\s_]+", "_", safe_name)
243
+ filename = f"{safe_name}_{timestamp}.ipynb"
244
+
245
+ notebook_path = output_path / filename
246
+
247
+ # Create notebook structure
248
+ notebook = {
249
+ "cells": cells,
250
+ "metadata": {
251
+ "kernelspec": {
252
+ "display_name": "Python 3",
253
+ "language": "python",
254
+ "name": "python3",
255
+ },
256
+ "language_info": {
257
+ "codemirror_mode": {"name": "ipython", "version": 3},
258
+ "file_extension": ".py",
259
+ "mimetype": "text/x-python",
260
+ "name": "python",
261
+ "nbconvert_exporter": "python",
262
+ "pygments_lexer": "ipython3",
263
+ "version": "3.8.0",
264
+ },
265
+ },
266
+ "nbformat": 4,
267
+ "nbformat_minor": 4,
268
+ }
269
+
270
+ # Save to file
271
+ with open(notebook_path, "w", encoding="utf-8") as f:
272
+ json.dump(notebook, f, indent=2, ensure_ascii=False)
273
+
274
+ return str(notebook_path)
@@ -0,0 +1,35 @@
1
+ """
2
+ Prompt Builder - Construct prompts for different actions
3
+ 프롬프트 템플릿은 prompts 모듈에서 관리됨
4
+ """
5
+
6
+ from hdsp_agent_core.prompts.cell_action_prompts import (
7
+ format_chat_prompt,
8
+ format_custom_prompt,
9
+ format_explain_prompt,
10
+ format_fix_prompt,
11
+ )
12
+
13
+
14
+ class PromptBuilder:
15
+ """Build LLM prompts based on action types"""
16
+
17
+ @staticmethod
18
+ def build_explain_prompt(cell_content: str) -> str:
19
+ """Build prompt for explaining code"""
20
+ return format_explain_prompt(cell_content)
21
+
22
+ @staticmethod
23
+ def build_fix_prompt(cell_content: str) -> str:
24
+ """Build prompt for fixing code errors"""
25
+ return format_fix_prompt(cell_content)
26
+
27
+ @staticmethod
28
+ def build_custom_prompt(custom_prompt: str, cell_content: str) -> str:
29
+ """Build prompt for custom user request"""
30
+ return format_custom_prompt(custom_prompt, cell_content)
31
+
32
+ @staticmethod
33
+ def build_chat_prompt(message: str, context: dict = None) -> str:
34
+ """Build prompt for general chat"""
35
+ return format_chat_prompt(message, context)