codebuff-agent 2.1.74__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.
- codebuff_agent-2.1.74.data/data/etc/jupyter/jupyter_server_config.d/codebuff_agent.json +7 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/package.json +157 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/104.2b8f20f9d1ac2c9db01b.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/150.39fa98117cc8ca590465.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/166.386ff9b2c37ac865fdee.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/216.25cf81131bf7274dabf4.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/353.581bd1cb00746399b62e.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/367.575f9621b63c9a641aa9.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/421.11dac223a2c2da1b09f5.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/432.8513b4c6cc1d1232d165.js +2 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/432.8513b4c6cc1d1232d165.js.LICENSE.txt +19 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/439.ba5b5ef70ec6de214b8c.js +2 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/439.ba5b5ef70ec6de214b8c.js.LICENSE.txt +8 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/481.cc2dec9fa869d66f1407.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/487.0796e931d6e651482c14.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/49.d326f554b6f9ccde6580.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/541.26897ea32845659e36be.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/579.e569d3edd8391fd8fbb3.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/58.eb7cc679f7535cc8a2f1.js +2 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/58.eb7cc679f7535cc8a2f1.js.LICENSE.txt +8 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/666.d9bfdb23f98489d0a188.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/677.d266c39dbed33bc388b3.js +2 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/677.d266c39dbed33bc388b3.js.LICENSE.txt +8 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/68.26b6f59c8454adb17f20.js +204 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/694.4ac443814260057e68f7.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/791.61affb8d3480d3d60e0d.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/848.4d2db09cfbb09374b299.js +2 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/848.4d2db09cfbb09374b299.js.LICENSE.txt +9 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/868.5cfe7e1a348ec5af1b8c.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/97.ea559a5b8a9a09f17c6b.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/remoteEntry.5292fc9c6df7e7920cc8.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/style.js +4 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/third-party-licenses.json +724 -0
- codebuff_agent-2.1.74.dist-info/METADATA +142 -0
- codebuff_agent-2.1.74.dist-info/RECORD +217 -0
- codebuff_agent-2.1.74.dist-info/WHEEL +4 -0
- codebuff_agent-2.1.74.dist-info/licenses/LICENSE +21 -0
- codebuff_core/__init__.py +153 -0
- codebuff_core/codebuff_config_defaults.json +64 -0
- codebuff_core/core/__init__.py +35 -0
- codebuff_core/core/code_validator.py +1238 -0
- codebuff_core/core/error_classifier.py +579 -0
- codebuff_core/core/exceptions.py +49 -0
- codebuff_core/data/tiktoken_cache/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +100256 -0
- codebuff_core/directory_policy.py +32 -0
- codebuff_core/factory.py +155 -0
- codebuff_core/interfaces.py +197 -0
- codebuff_core/knowledge/__init__.py +31 -0
- codebuff_core/knowledge/chunking.py +375 -0
- codebuff_core/knowledge/loader.py +339 -0
- codebuff_core/knowledge/watchdog_service.py +354 -0
- codebuff_core/legacy_paths.py +69 -0
- codebuff_core/llm/__init__.py +13 -0
- codebuff_core/llm/service.py +407 -0
- codebuff_core/managers/__init__.py +22 -0
- codebuff_core/managers/config_manager.py +690 -0
- codebuff_core/managers/remote_config.py +673 -0
- codebuff_core/managers/remote_skills.py +539 -0
- codebuff_core/managers/session_manager.py +255 -0
- codebuff_core/middleware/__init__.py +3 -0
- codebuff_core/middleware/error_recovery.py +394 -0
- codebuff_core/middleware/logging_utils.py +33 -0
- codebuff_core/models/__init__.py +111 -0
- codebuff_core/models/agent.py +306 -0
- codebuff_core/models/chat.py +57 -0
- codebuff_core/models/common.py +82 -0
- codebuff_core/models/rag.py +300 -0
- codebuff_core/platform_rules.py +127 -0
- codebuff_core/prompts/__init__.py +44 -0
- codebuff_core/prompts/auto_agent_prompts.py +1278 -0
- codebuff_core/services/__init__.py +30 -0
- codebuff_core/services/agent_service.py +345 -0
- codebuff_core/services/analytics_aggregate.py +837 -0
- codebuff_core/services/chat_service.py +898 -0
- codebuff_core/services/context_condenser.py +306 -0
- codebuff_core/services/pii_guardrail.py +393 -0
- codebuff_core/services/rag_chat_agent.py +2993 -0
- codebuff_core/services/rag_collections.py +2740 -0
- codebuff_core/services/rag_manager.py +890 -0
- codebuff_core/services/rag_service.py +145 -0
- codebuff_core/services/retriever.py +260 -0
- codebuff_core/services/vllm_embedding_service.py +290 -0
- codebuff_core/tests/__init__.py +1 -0
- codebuff_core/tests/conftest.py +81 -0
- codebuff_core/tests/test_error_recovery.py +647 -0
- codebuff_core/tests/test_factory.py +135 -0
- codebuff_core/tests/test_services.py +150 -0
- jupyter_ext/__init__.py +266 -0
- jupyter_ext/_version.py +4 -0
- jupyter_ext/agent/__init__.py +49 -0
- jupyter_ext/agent/agent_factory.py +2270 -0
- jupyter_ext/agent/ast_tools.py +451 -0
- jupyter_ext/agent/autofix_middleware.py +481 -0
- jupyter_ext/agent/background_procs.py +372 -0
- jupyter_ext/agent/code_history_middleware.py +211 -0
- jupyter_ext/agent/codex_autofix.py +160 -0
- jupyter_ext/agent/codex_bridge.py +3339 -0
- jupyter_ext/agent/codex_hooks.py +320 -0
- jupyter_ext/agent/codex_slash.py +685 -0
- jupyter_ext/agent/codex_threads.py +114 -0
- jupyter_ext/agent/content_injection.py +377 -0
- jupyter_ext/agent/continuation_middleware.py +548 -0
- jupyter_ext/agent/custom_skills.py +335 -0
- jupyter_ext/agent/file_diffs.py +99 -0
- jupyter_ext/agent/git_history.py +188 -0
- jupyter_ext/agent/guardrail_middleware.py +421 -0
- jupyter_ext/agent/json_repair_utils.py +54 -0
- jupyter_ext/agent/langchain_tools.py +2673 -0
- jupyter_ext/agent/mermaid_fixer.py +289 -0
- jupyter_ext/agent/mermaid_middleware.py +135 -0
- jupyter_ext/agent/middleware.py +359 -0
- jupyter_ext/agent/middleware_prompts.py +53 -0
- jupyter_ext/agent/observability.py +334 -0
- jupyter_ext/agent/patch_tool_calls.py +57 -0
- jupyter_ext/agent/prompts.py +112 -0
- jupyter_ext/agent/skill_middleware.py +257 -0
- jupyter_ext/agent/skills/airflow_dag_development.md +36 -0
- jupyter_ext/agent/skills/anomaly_detection.md +12 -0
- jupyter_ext/agent/skills/athena_sql.md +156 -0
- jupyter_ext/agent/skills/bdp_table_search.md +33 -0
- jupyter_ext/agent/skills/bigquery.md +65 -0
- jupyter_ext/agent/skills/bigquery_oracle.md +231 -0
- jupyter_ext/agent/skills/bigquery_tuning.md +307 -0
- jupyter_ext/agent/skills/classification_evaluation.md +11 -0
- jupyter_ext/agent/skills/clustering_analysis.md +12 -0
- jupyter_ext/agent/skills/comprehensive_eda.md +11 -0
- jupyter_ext/agent/skills/data_analysis.md +236 -0
- jupyter_ext/agent/skills/data_cleaning_pipeline.md +12 -0
- jupyter_ext/agent/skills/data_loading.md +158 -0
- jupyter_ext/agent/skills/data_quality_report.md +13 -0
- jupyter_ext/agent/skills/dimensionality_reduction.md +12 -0
- jupyter_ext/agent/skills/emr_script_development.md +17 -0
- jupyter_ext/agent/skills/experiment_tracking.md +13 -0
- jupyter_ext/agent/skills/feature_importance_analysis.md +10 -0
- jupyter_ext/agent/skills/hyperparameter_tuning.md +12 -0
- jupyter_ext/agent/skills/hypothesis_testing.md +12 -0
- jupyter_ext/agent/skills/imbalanced_data_handling.md +12 -0
- jupyter_ext/agent/skills/inference.md +392 -0
- jupyter_ext/agent/skills/lambda_function_development.md +19 -0
- jupyter_ext/agent/skills/model_comparison.md +11 -0
- jupyter_ext/agent/skills/model_explainability.md +12 -0
- jupyter_ext/agent/skills/model_training.md +318 -0
- jupyter_ext/agent/skills/pyspark.md +352 -0
- jupyter_ext/agent/skills/python_code_quality.md +35 -0
- jupyter_ext/agent/skills/regression_evaluation.md +12 -0
- jupyter_ext/agent/skills/spring_java_development.md +35 -0
- jupyter_ext/agent/skills/text_preprocessing.md +12 -0
- jupyter_ext/agent/skills/time_series_analysis.md +13 -0
- jupyter_ext/agent/skills/unit_testing.md +203 -0
- jupyter_ext/agent/todo_prompts.py +57 -0
- jupyter_ext/agent/tool_report.py +45 -0
- jupyter_ext/analytics_ingest.py +599 -0
- jupyter_ext/etc/jupyter/jupyter_server_config.d/codebuff_agent.json +7 -0
- jupyter_ext/handlers/__init__.py +8 -0
- jupyter_ext/handlers/analytics_handler.py +170 -0
- jupyter_ext/handlers/benchmark_handler.py +794 -0
- jupyter_ext/handlers/eda_benchmark_handler.py +1328 -0
- jupyter_ext/handlers/rag_admin_handler.py +689 -0
- jupyter_ext/handlers/websocket.py +497 -0
- jupyter_ext/http_handlers.py +8744 -0
- jupyter_ext/idle_monitor.py +346 -0
- jupyter_ext/labextension/package.json +157 -0
- jupyter_ext/labextension/static/104.2b8f20f9d1ac2c9db01b.js +1 -0
- jupyter_ext/labextension/static/150.39fa98117cc8ca590465.js +1 -0
- jupyter_ext/labextension/static/166.386ff9b2c37ac865fdee.js +1 -0
- jupyter_ext/labextension/static/216.25cf81131bf7274dabf4.js +1 -0
- jupyter_ext/labextension/static/353.581bd1cb00746399b62e.js +1 -0
- jupyter_ext/labextension/static/367.575f9621b63c9a641aa9.js +1 -0
- jupyter_ext/labextension/static/421.11dac223a2c2da1b09f5.js +1 -0
- jupyter_ext/labextension/static/432.8513b4c6cc1d1232d165.js +2 -0
- jupyter_ext/labextension/static/432.8513b4c6cc1d1232d165.js.LICENSE.txt +19 -0
- jupyter_ext/labextension/static/439.ba5b5ef70ec6de214b8c.js +2 -0
- jupyter_ext/labextension/static/439.ba5b5ef70ec6de214b8c.js.LICENSE.txt +8 -0
- jupyter_ext/labextension/static/481.cc2dec9fa869d66f1407.js +1 -0
- jupyter_ext/labextension/static/487.0796e931d6e651482c14.js +1 -0
- jupyter_ext/labextension/static/49.d326f554b6f9ccde6580.js +1 -0
- jupyter_ext/labextension/static/541.26897ea32845659e36be.js +1 -0
- jupyter_ext/labextension/static/579.e569d3edd8391fd8fbb3.js +1 -0
- jupyter_ext/labextension/static/58.eb7cc679f7535cc8a2f1.js +2 -0
- jupyter_ext/labextension/static/58.eb7cc679f7535cc8a2f1.js.LICENSE.txt +8 -0
- jupyter_ext/labextension/static/666.d9bfdb23f98489d0a188.js +1 -0
- jupyter_ext/labextension/static/677.d266c39dbed33bc388b3.js +2 -0
- jupyter_ext/labextension/static/677.d266c39dbed33bc388b3.js.LICENSE.txt +8 -0
- jupyter_ext/labextension/static/68.26b6f59c8454adb17f20.js +204 -0
- jupyter_ext/labextension/static/694.4ac443814260057e68f7.js +1 -0
- jupyter_ext/labextension/static/791.61affb8d3480d3d60e0d.js +1 -0
- jupyter_ext/labextension/static/848.4d2db09cfbb09374b299.js +2 -0
- jupyter_ext/labextension/static/848.4d2db09cfbb09374b299.js.LICENSE.txt +9 -0
- jupyter_ext/labextension/static/868.5cfe7e1a348ec5af1b8c.js +1 -0
- jupyter_ext/labextension/static/97.ea559a5b8a9a09f17c6b.js +1 -0
- jupyter_ext/labextension/static/remoteEntry.5292fc9c6df7e7920cc8.js +1 -0
- jupyter_ext/labextension/static/style.js +4 -0
- jupyter_ext/labextension/static/third-party-licenses.json +724 -0
- jupyter_ext/log_paths.py +113 -0
- jupyter_ext/resource_usage.py +519 -0
- jupyter_ext/secrets_bootstrap.py +116 -0
- jupyter_ext/team_access.py +105 -0
- jupyter_ext/tests/__init__.py +1 -0
- jupyter_ext/tests/test_context.py +234 -0
- jupyter_ext/tests/test_factory.py +563 -0
- jupyter_ext/tests/test_file_finder.py +139 -0
- jupyter_ext/tests/test_handlers.py +58 -0
- jupyter_ext/tests/test_mcp_selftest.py +204 -0
- jupyter_ext/tests/test_mermaid_fixer.py +272 -0
- jupyter_ext/tests/test_resource_tiers.py +298 -0
- jupyter_ext/tools/__init__.py +15 -0
- jupyter_ext/tools/base.py +90 -0
- jupyter_ext/tools/context.py +268 -0
- jupyter_ext/tools/dir_complete.py +86 -0
- jupyter_ext/tools/file_finder.py +303 -0
- jupyter_ext/tools/file_tools.py +244 -0
- jupyter_ext/tools/jupyter_tools.py +296 -0
- jupyter_ext/tools/registry.py +159 -0
- jupyter_ext/tools/search_tools.py +230 -0
- jupyter_ext/tools/security_tools.py +657 -0
- jupyter_ext/tools/shell_tools.py +109 -0
- jupyter_ext/tools/user_tools.py +132 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
"""
|
|
2
|
+
RAG 설정 및 API Pydantic 모델
|
|
3
|
+
|
|
4
|
+
로컬 RAG 시스템을 위한 설정 스키마 정의:
|
|
5
|
+
- Qdrant 벡터 데이터베이스 설정
|
|
6
|
+
- 임베딩 모델 설정
|
|
7
|
+
- 문서 청킹 설정
|
|
8
|
+
- 파일 감시(watchdog) 설정
|
|
9
|
+
- 검색 API 요청/응답 모델
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
from typing import Optional, List, Literal, Dict, Any
|
|
14
|
+
from pydantic import BaseModel, Field
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class QdrantConfig(BaseModel):
|
|
18
|
+
"""Qdrant 벡터 데이터베이스 설정"""
|
|
19
|
+
|
|
20
|
+
mode: Literal["local", "server", "cloud"] = Field(
|
|
21
|
+
default="local",
|
|
22
|
+
description="배포 모드: local (파일 기반), server (Docker), cloud",
|
|
23
|
+
)
|
|
24
|
+
# 로컬 모드 설정
|
|
25
|
+
local_path: Optional[str] = Field(
|
|
26
|
+
default=None,
|
|
27
|
+
description="로컬 Qdrant 저장소 경로. 기본값: $QDRANT_PATH, 없으면 $CODEBUFF_HOME/qdrant, 없으면 ~/.codebuff/qdrant",
|
|
28
|
+
)
|
|
29
|
+
# 서버 모드 설정
|
|
30
|
+
url: Optional[str] = Field(
|
|
31
|
+
default="http://localhost:6333",
|
|
32
|
+
description="server/cloud 모드용 Qdrant 서버 URL",
|
|
33
|
+
)
|
|
34
|
+
api_key: Optional[str] = Field(default=None, description="cloud 모드용 API 키")
|
|
35
|
+
# 컬렉션 설정
|
|
36
|
+
collection_name: str = Field(
|
|
37
|
+
default="hdsp_knowledge", description="벡터 컬렉션 이름"
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
def get_mode(self) -> str:
|
|
41
|
+
"""Qdrant 배포 모드 반환"""
|
|
42
|
+
return self.mode
|
|
43
|
+
|
|
44
|
+
def get_url(self) -> str:
|
|
45
|
+
"""Qdrant 서버 URL 반환"""
|
|
46
|
+
return self.url or "http://localhost:6333"
|
|
47
|
+
|
|
48
|
+
def get_local_path(self) -> str:
|
|
49
|
+
"""해석된 로컬 경로 반환"""
|
|
50
|
+
if self.local_path:
|
|
51
|
+
return os.path.expanduser(self.local_path)
|
|
52
|
+
from codebuff_core.legacy_paths import resolve_home
|
|
53
|
+
|
|
54
|
+
return str(resolve_home("qdrant"))
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class EmbeddingConfig(BaseModel):
|
|
58
|
+
"""임베딩 모델 설정"""
|
|
59
|
+
|
|
60
|
+
model_name: str = Field(
|
|
61
|
+
default="intfloat/multilingual-e5-small",
|
|
62
|
+
description="임베딩용 HuggingFace 모델 이름",
|
|
63
|
+
)
|
|
64
|
+
device: Literal["cpu", "cuda", "mps"] = Field(
|
|
65
|
+
default="cpu", description="임베딩 계산용 디바이스"
|
|
66
|
+
)
|
|
67
|
+
batch_size: int = Field(default=32, description="임베딩 생성 배치 크기")
|
|
68
|
+
cache_folder: Optional[str] = Field(
|
|
69
|
+
default=None, description="모델 캐시 폴더. 기본값: ~/.cache/huggingface"
|
|
70
|
+
)
|
|
71
|
+
# 모델별 설정
|
|
72
|
+
normalize_embeddings: bool = Field(
|
|
73
|
+
default=True, description="코사인 유사도를 위한 임베딩 정규화"
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
def get_model_name(self) -> str:
|
|
77
|
+
"""임베딩 모델 이름 반환"""
|
|
78
|
+
return self.model_name
|
|
79
|
+
|
|
80
|
+
def get_device(self) -> str:
|
|
81
|
+
"""임베딩 계산 디바이스 반환"""
|
|
82
|
+
return self.device
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class ChunkingConfig(BaseModel):
|
|
86
|
+
"""문서 청킹 설정"""
|
|
87
|
+
|
|
88
|
+
chunk_size: int = Field(default=512, description="목표 청크 크기 (문자 단위)")
|
|
89
|
+
chunk_overlap: int = Field(default=50, description="청크 간 중첩 (문자 단위)")
|
|
90
|
+
split_by_header: bool = Field(
|
|
91
|
+
default=True, description="의미적 경계를 위해 마크다운을 헤더 기준으로 분할"
|
|
92
|
+
)
|
|
93
|
+
min_chunk_size: int = Field(default=100, description="포함할 최소 청크 크기")
|
|
94
|
+
max_chunk_size: int = Field(default=2000, description="최대 청크 크기 (하드 리밋)")
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class WatchdogConfig(BaseModel):
|
|
98
|
+
"""파일 모니터링 설정"""
|
|
99
|
+
|
|
100
|
+
enabled: bool = Field(default=True, description="파일 시스템 모니터링 활성화")
|
|
101
|
+
debounce_seconds: float = Field(
|
|
102
|
+
default=2.0, description="파일 변경 이벤트 디바운스 시간"
|
|
103
|
+
)
|
|
104
|
+
patterns: List[str] = Field(
|
|
105
|
+
default=["*.md", "*.py", "*.txt", "*.json"], description="모니터링할 파일 패턴"
|
|
106
|
+
)
|
|
107
|
+
ignore_patterns: List[str] = Field(
|
|
108
|
+
default=[".*", "__pycache__", "*.pyc", "*.egg-info"], description="무시할 패턴"
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class RAGConfig(BaseModel):
|
|
113
|
+
"""메인 RAG 시스템 설정"""
|
|
114
|
+
|
|
115
|
+
enabled: bool = Field(default=True, description="RAG 시스템 활성화")
|
|
116
|
+
knowledge_base_path: Optional[str] = Field(
|
|
117
|
+
default=None, description="지식 베이스 경로. 기본값: 내장 libraries/"
|
|
118
|
+
)
|
|
119
|
+
qdrant: QdrantConfig = Field(default_factory=QdrantConfig)
|
|
120
|
+
embedding: EmbeddingConfig = Field(default_factory=EmbeddingConfig)
|
|
121
|
+
chunking: ChunkingConfig = Field(default_factory=ChunkingConfig)
|
|
122
|
+
watchdog: WatchdogConfig = Field(default_factory=WatchdogConfig)
|
|
123
|
+
|
|
124
|
+
# 검색 설정
|
|
125
|
+
top_k: int = Field(default=5, description="검색할 청크 수")
|
|
126
|
+
score_threshold: float = Field(default=0.3, description="최소 유사도 점수 임계값")
|
|
127
|
+
max_context_tokens: int = Field(
|
|
128
|
+
default=1500, description="RAG 컨텍스트 주입 최대 토큰"
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
def is_enabled(self) -> bool:
|
|
132
|
+
"""RAG 활성화 여부 확인"""
|
|
133
|
+
return self.enabled
|
|
134
|
+
|
|
135
|
+
def get_knowledge_base_path(self) -> Optional[str]:
|
|
136
|
+
"""지식 베이스 경로 반환"""
|
|
137
|
+
if self.knowledge_base_path:
|
|
138
|
+
return os.path.expanduser(self.knowledge_base_path)
|
|
139
|
+
return None # 내장 기본값 사용
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
# ============ API 요청/응답 모델 ============
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class SearchRequest(BaseModel):
|
|
146
|
+
"""명시적 RAG 검색 요청 본문"""
|
|
147
|
+
|
|
148
|
+
query: str = Field(description="검색 쿼리")
|
|
149
|
+
top_k: Optional[int] = Field(default=None, description="기본 top_k 오버라이드")
|
|
150
|
+
filters: Optional[Dict[str, Any]] = Field(
|
|
151
|
+
default=None, description="메타데이터 필터 (예: {'source_type': 'library'})"
|
|
152
|
+
)
|
|
153
|
+
include_score: bool = Field(default=True, description="결과에 관련성 점수 포함")
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class SearchResult(BaseModel):
|
|
157
|
+
"""단일 검색 결과"""
|
|
158
|
+
|
|
159
|
+
content: str = Field(description="청크 내용")
|
|
160
|
+
score: float = Field(description="관련성 점수 (0-1)")
|
|
161
|
+
metadata: Dict[str, Any] = Field(description="청크 메타데이터 (소스, 유형 등)")
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
class SearchResponse(BaseModel):
|
|
165
|
+
"""RAG 검색 응답 본문"""
|
|
166
|
+
|
|
167
|
+
results: List[SearchResult] = Field(description="관련성순으로 정렬된 검색 결과")
|
|
168
|
+
query: str = Field(description="원본 쿼리")
|
|
169
|
+
total_results: int = Field(description="총 일치 청크 수")
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class IndexStatusResponse(BaseModel):
|
|
173
|
+
"""인덱스 상태 응답 본문"""
|
|
174
|
+
|
|
175
|
+
ready: bool = Field(description="RAG 시스템 준비 여부")
|
|
176
|
+
total_documents: int = Field(default=0, description="총 인덱싱된 문서 수")
|
|
177
|
+
total_chunks: int = Field(default=0, description="총 인덱싱된 청크 수")
|
|
178
|
+
last_updated: Optional[str] = Field(
|
|
179
|
+
default=None, description="마지막 인덱스 업데이트 타임스탬프"
|
|
180
|
+
)
|
|
181
|
+
knowledge_base_path: Optional[str] = Field(
|
|
182
|
+
default=None, description="현재 지식 베이스 경로"
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class ReindexRequest(BaseModel):
|
|
187
|
+
"""수동 재인덱싱 요청 본문"""
|
|
188
|
+
|
|
189
|
+
force: bool = Field(
|
|
190
|
+
default=False, description="파일이 변경되지 않아도 전체 재인덱싱 강제"
|
|
191
|
+
)
|
|
192
|
+
path: Optional[str] = Field(
|
|
193
|
+
default=None, description="재인덱싱할 특정 파일 또는 디렉토리"
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
class ReindexResponse(BaseModel):
|
|
198
|
+
"""재인덱싱 작업 응답 본문"""
|
|
199
|
+
|
|
200
|
+
success: bool = Field(description="재인덱싱 성공 여부")
|
|
201
|
+
indexed: int = Field(description="인덱싱된 파일 수")
|
|
202
|
+
skipped: int = Field(description="건너뛴 파일 수 (변경 없음)")
|
|
203
|
+
errors: List[Dict[str, str]] = Field(default=[], description="인덱싱 오류 목록")
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
# ============ 디버그 모델 ============
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
class ChunkDebugInfo(BaseModel):
|
|
210
|
+
"""디버깅용 청크 상세 점수 정보"""
|
|
211
|
+
|
|
212
|
+
chunk_id: str
|
|
213
|
+
content_preview: str # 처음 200자
|
|
214
|
+
score: float # 벡터 유사도 점수 (0-1)
|
|
215
|
+
rank: int # 순위
|
|
216
|
+
metadata: Dict[str, Any] # source, section 등
|
|
217
|
+
passed_threshold: bool # 임계값 통과 여부
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
class LibraryDetectionDebug(BaseModel):
|
|
221
|
+
"""라이브러리 감지 단계 디버그 정보"""
|
|
222
|
+
|
|
223
|
+
input_query: str
|
|
224
|
+
imported_libraries: List[str]
|
|
225
|
+
available_libraries: List[str]
|
|
226
|
+
detected_libraries: List[str]
|
|
227
|
+
detection_method: str
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
class SearchConfigDebug(BaseModel):
|
|
231
|
+
"""검색 설정 정보"""
|
|
232
|
+
|
|
233
|
+
top_k: int
|
|
234
|
+
score_threshold: float
|
|
235
|
+
max_context_tokens: int
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
class DebugSearchRequest(BaseModel):
|
|
239
|
+
"""디버그 검색 요청"""
|
|
240
|
+
|
|
241
|
+
query: str = Field(description="디버깅용 검색 쿼리")
|
|
242
|
+
imported_libraries: List[str] = Field(
|
|
243
|
+
default=[], description="검색 필터링을 위한 import된 라이브러리 목록"
|
|
244
|
+
)
|
|
245
|
+
top_k: Optional[int] = Field(default=None, description="기본 top_k 오버라이드")
|
|
246
|
+
include_full_content: bool = Field(
|
|
247
|
+
default=False, description="미리보기 대신 전체 내용 포함"
|
|
248
|
+
)
|
|
249
|
+
simulate_plan_context: bool = Field(
|
|
250
|
+
default=True, description="계획 생성 시와 같은 포맷된 컨텍스트 생성"
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
class DebugSearchResponse(BaseModel):
|
|
255
|
+
"""디버그 검색 응답"""
|
|
256
|
+
|
|
257
|
+
library_detection: LibraryDetectionDebug
|
|
258
|
+
config: SearchConfigDebug
|
|
259
|
+
chunks: List[ChunkDebugInfo]
|
|
260
|
+
total_candidates: int
|
|
261
|
+
total_passed_threshold: int
|
|
262
|
+
search_ms: float # 벡터 검색 시간 (밀리초)
|
|
263
|
+
formatted_context: str
|
|
264
|
+
context_char_count: int
|
|
265
|
+
estimated_context_tokens: int
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
# ============ 팩토리 함수 ============
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def get_default_rag_config() -> RAGConfig:
|
|
272
|
+
"""ConfigManager JSON에서 RAG 설정 로드"""
|
|
273
|
+
from codebuff_core.managers.config_manager import get_config_manager
|
|
274
|
+
|
|
275
|
+
cfg = get_config_manager().get_config()
|
|
276
|
+
rag = cfg.get("rag", {})
|
|
277
|
+
|
|
278
|
+
# 환경변수 우선 → config 파일 폴백
|
|
279
|
+
qdrant_mode = os.environ.get("QDRANT_MODE", "") or rag.get("qdrantMode", "local")
|
|
280
|
+
qdrant_url = os.environ.get("QDRANT_URL", "") or rag.get("qdrantUrl", "http://localhost:6333")
|
|
281
|
+
qdrant_path = os.environ.get("QDRANT_PATH", "") or rag.get("qdrantPath")
|
|
282
|
+
qdrant_api_key = os.environ.get("QDRANT_API_KEY", "") or rag.get("qdrantApiKey")
|
|
283
|
+
|
|
284
|
+
return RAGConfig(
|
|
285
|
+
enabled=rag.get("enabled", True),
|
|
286
|
+
knowledge_base_path=rag.get("knowledgeBasePath"),
|
|
287
|
+
qdrant=QdrantConfig(
|
|
288
|
+
mode=qdrant_mode,
|
|
289
|
+
url=qdrant_url,
|
|
290
|
+
local_path=qdrant_path or None,
|
|
291
|
+
api_key=qdrant_api_key or None,
|
|
292
|
+
collection_name=rag.get("collectionName", "hdsp_knowledge"),
|
|
293
|
+
),
|
|
294
|
+
embedding=EmbeddingConfig(
|
|
295
|
+
model_name=rag.get("embeddingModel", "intfloat/multilingual-e5-small"),
|
|
296
|
+
device=rag.get("embeddingDevice", "cpu"),
|
|
297
|
+
),
|
|
298
|
+
chunking=ChunkingConfig(),
|
|
299
|
+
watchdog=WatchdogConfig(),
|
|
300
|
+
)
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""사내 BDP 플랫폼(HDSP 노트북) 실행 환경 규칙 — 두 엔진이 같이 쓰는 정본 (이슈 #120).
|
|
2
|
+
|
|
3
|
+
HDSP 노트북 pod 에서는 boto3 를 직접 쓸 수 없다. 기본 자격증명·SSL 경로가 막혀 있어서
|
|
4
|
+
(`secrets_bootstrap.py` 주석 참고) 미리 설치된 bdpengine 의 클라이언트 팩토리를 거쳐야
|
|
5
|
+
Athena·S3·SageMaker·MinIO 에 닿는다. 모델이 이것을 모르면 boto3 로 코드를 쓴다.
|
|
6
|
+
|
|
7
|
+
그래서 세 가지를 여기 한 곳에 둔다:
|
|
8
|
+
- 판정 `is_bdp_platform()` — `HDSP_ENV` 가 dev/prod 면 사내다. `CODEBUFF_BDP_RULES=1/0` 이 우선한다
|
|
9
|
+
(로컬에서 켜 보거나, 운영에서 문구가 틀렸을 때 재배포 없이 끄는 스위치).
|
|
10
|
+
- 규칙 텍스트 `platform_rules_block()` — 지시문에 붙인다. 사내가 아니면 빈 문자열이라
|
|
11
|
+
로컬 동작은 한 글자도 안 바뀐다. centri 키 `prompts.bdp_platform_rules`(이슈 #178), 없으면
|
|
12
|
+
`~/.codebuff/bdp_rules.md` 가 내장 텍스트를 대체한다.
|
|
13
|
+
- 가드 `tool_call_violation()` — 도구 인자에서 boto3 직접 사용을 찾아 bdpengine 안내를 돌려준다.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import os
|
|
19
|
+
import re
|
|
20
|
+
from typing import Any, Dict, Optional
|
|
21
|
+
|
|
22
|
+
BDP_RULES_ENV = "CODEBUFF_BDP_RULES"
|
|
23
|
+
BDP_RULES_PATH = "~/.codebuff/bdp_rules.md"
|
|
24
|
+
|
|
25
|
+
_PLATFORM_ENVS = ("dev", "prod")
|
|
26
|
+
|
|
27
|
+
#: 내장 규칙 문구는 스냅샷 `prompts.bdp_platform_rules` 다 (이슈 #218 — 코드 상수 없음).
|
|
28
|
+
#: 저장소에서 확인된 bdpengine 함수는 `start_query`·`get_boto3_client` 둘뿐이다
|
|
29
|
+
#: (`secrets_bootstrap.py`, `http_handlers.py`, `mock_packages/bdpengine`). 나머지는 지어내지
|
|
30
|
+
#: 않고 모델이 직접 확인하게 한다. 사내 관리자는 `~/.codebuff/bdp_rules.md` 로 바꾼다.
|
|
31
|
+
|
|
32
|
+
BDP_GUARD_MESSAGE = (
|
|
33
|
+
"이 환경(HDSP 노트북)에서는 boto3 를 직접 쓸 수 없습니다 (감지: `{line}`). "
|
|
34
|
+
"`from bdpengine.functions import ...` 로 다시 작성하세요 — Athena 는 "
|
|
35
|
+
"`start_query(query=...)`, AWS 클라이언트가 필요하면 `get_boto3_client('<service>')`."
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# 코드: 줄 머리의 import 와 클라이언트 직접 생성. `get_boto3_client` 는 `_` 가 단어 문자라
|
|
39
|
+
# `\bboto3` 경계가 서지 않아 걸리지 않는다.
|
|
40
|
+
_CODE_IMPORT = re.compile(r"^\s*(?:import|from)\s+boto3\b")
|
|
41
|
+
_CLIENT_CALL = re.compile(r"\bboto3\.(?:client|resource|Session|session)\s*\(")
|
|
42
|
+
# 셸: `python -c "import boto3"` 처럼 import 가 줄 가운데 온다.
|
|
43
|
+
_SHELL_IMPORT = re.compile(r"\b(?:import|from)\s+boto3\b")
|
|
44
|
+
# 검색은 실행이 아니다 — `grep "import boto3"` 는 boto3 를 옮기는 작업의 첫 수다.
|
|
45
|
+
_SHELL_SEARCH = re.compile(r"^\s*(?:grep|egrep|rg|ag|ack|git\s+grep)\b")
|
|
46
|
+
_SWITCH_ON = ("1", "true", "yes", "on")
|
|
47
|
+
_SWITCH_OFF = ("0", "false", "no", "off")
|
|
48
|
+
_MAX_REPORTED = 200
|
|
49
|
+
|
|
50
|
+
#: 도구 이름 → (코드가 실리는 인자, 셸 명령인가). 두 엔진의 쓰기·실행 도구를 다 적는다
|
|
51
|
+
#: — codex: write_file·edit_file·execute_command, client: jupyter_cell·file_write·write_file·edit_file.
|
|
52
|
+
_TOOL_CODE_FIELDS = {
|
|
53
|
+
"write_file": ("content", False),
|
|
54
|
+
"edit_file": ("new_string", False),
|
|
55
|
+
"execute_command": ("command", True),
|
|
56
|
+
"jupyter_cell": ("code", False),
|
|
57
|
+
"file_write": ("content", False),
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def is_bdp_platform() -> bool:
|
|
62
|
+
switch = os.environ.get(BDP_RULES_ENV, "").strip().lower()
|
|
63
|
+
if switch in _SWITCH_ON or switch in _SWITCH_OFF:
|
|
64
|
+
return switch in _SWITCH_ON
|
|
65
|
+
return os.environ.get("HDSP_ENV", "").strip().lower() in _PLATFORM_ENVS
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def platform_rules_block() -> str:
|
|
69
|
+
"""사내면 지시문에 붙일 규칙, 아니면 빈 문자열.
|
|
70
|
+
|
|
71
|
+
문구는 centri 키 `prompts.bdp_platform_rules` > `~/.codebuff/bdp_rules.md` > 스냅샷 기본값
|
|
72
|
+
순이다 (이슈 #178, #218). 키는 문구만 바꾼다 — 사내가 아니면 키가 있어도 붙이지 않는다.
|
|
73
|
+
"""
|
|
74
|
+
if not is_bdp_platform():
|
|
75
|
+
return ""
|
|
76
|
+
from codebuff_core.managers.config_manager import configured_prompt
|
|
77
|
+
|
|
78
|
+
configured = configured_prompt("bdp_platform_rules")
|
|
79
|
+
if configured:
|
|
80
|
+
return configured
|
|
81
|
+
try:
|
|
82
|
+
with open(os.path.expanduser(BDP_RULES_PATH), encoding="utf-8") as f:
|
|
83
|
+
custom = f.read().strip()
|
|
84
|
+
if custom:
|
|
85
|
+
return custom
|
|
86
|
+
except (OSError, UnicodeDecodeError):
|
|
87
|
+
# 관리자 파일 하나가 두 엔진의 시작을 막지 않게 내장 문구로 돌아간다
|
|
88
|
+
pass
|
|
89
|
+
from codebuff_core.managers.remote_config import snapshot_prompt
|
|
90
|
+
|
|
91
|
+
return snapshot_prompt("bdp_platform_rules")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def find_direct_boto3(text: str, shell: bool = False) -> Optional[str]:
|
|
95
|
+
"""boto3 를 직접 쓰는 첫 줄(최대 200자)을 돌려준다. 없으면 None.
|
|
96
|
+
|
|
97
|
+
`#` 뒤 주석은 보지 않는다. 문자열·docstring 안의 `boto3.client(` 는 잡는다(오탐).
|
|
98
|
+
`import os, boto3` 처럼 줄 머리가 아닌 import 는 못 잡는다(미탐) — 앵커를 풀면
|
|
99
|
+
주석·문자열 오탐이 늘어서 이쪽을 택했다. 한계는 테스트가 고정한다.
|
|
100
|
+
"""
|
|
101
|
+
imports = _SHELL_IMPORT if shell else _CODE_IMPORT
|
|
102
|
+
for line in (text or "").splitlines():
|
|
103
|
+
code = line.split("#", 1)[0]
|
|
104
|
+
if not code.strip() or (shell and _SHELL_SEARCH.search(code)):
|
|
105
|
+
continue
|
|
106
|
+
if imports.search(code) or _CLIENT_CALL.search(code):
|
|
107
|
+
return line.strip()[:_MAX_REPORTED]
|
|
108
|
+
return None
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def tool_call_violation(tool_name: str, args: Dict[str, Any]) -> Optional[str]:
|
|
112
|
+
"""사내에서 도구 인자가 boto3 를 직접 쓰면 모델에 돌려줄 오류 문구, 아니면 None."""
|
|
113
|
+
field = _TOOL_CODE_FIELDS.get(tool_name)
|
|
114
|
+
if field is None or not is_bdp_platform():
|
|
115
|
+
return None
|
|
116
|
+
key, shell = field
|
|
117
|
+
value = (args or {}).get(key)
|
|
118
|
+
if not isinstance(value, str):
|
|
119
|
+
return None
|
|
120
|
+
line = find_direct_boto3(value, shell=shell)
|
|
121
|
+
return BDP_GUARD_MESSAGE.format(line=line) if line else None
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def with_platform_rules(prompt: str) -> str:
|
|
125
|
+
"""사내면 프롬프트 뒤에 규칙을 붙인다. 아니면 그대로 돌려준다."""
|
|
126
|
+
rules = platform_rules_block()
|
|
127
|
+
return prompt + "\n\n" + rules if rules else prompt
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Codebuff Core - Prompts
|
|
3
|
+
|
|
4
|
+
Prompt templates for Auto-Agent.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .auto_agent_prompts import (
|
|
8
|
+
ADAPTIVE_REPLAN_PROMPT,
|
|
9
|
+
CODE_GENERATION_PROMPT,
|
|
10
|
+
ERROR_ANALYSIS_PROMPT,
|
|
11
|
+
ERROR_REFINEMENT_PROMPT,
|
|
12
|
+
FINAL_ANSWER_PROMPT,
|
|
13
|
+
PIP_INDEX_OPTION,
|
|
14
|
+
PLAN_GENERATION_PROMPT,
|
|
15
|
+
REFLECTION_PROMPT,
|
|
16
|
+
STRUCTURED_PLAN_PROMPT,
|
|
17
|
+
format_error_analysis_prompt,
|
|
18
|
+
format_final_answer_prompt,
|
|
19
|
+
format_plan_prompt,
|
|
20
|
+
format_refine_prompt,
|
|
21
|
+
format_reflection_prompt,
|
|
22
|
+
format_replan_prompt,
|
|
23
|
+
format_structured_plan_prompt,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
__all__ = [
|
|
27
|
+
# Auto-Agent Prompts
|
|
28
|
+
"PLAN_GENERATION_PROMPT",
|
|
29
|
+
"CODE_GENERATION_PROMPT",
|
|
30
|
+
"ERROR_REFINEMENT_PROMPT",
|
|
31
|
+
"ADAPTIVE_REPLAN_PROMPT",
|
|
32
|
+
"STRUCTURED_PLAN_PROMPT",
|
|
33
|
+
"REFLECTION_PROMPT",
|
|
34
|
+
"FINAL_ANSWER_PROMPT",
|
|
35
|
+
"ERROR_ANALYSIS_PROMPT",
|
|
36
|
+
"PIP_INDEX_OPTION",
|
|
37
|
+
"format_plan_prompt",
|
|
38
|
+
"format_refine_prompt",
|
|
39
|
+
"format_final_answer_prompt",
|
|
40
|
+
"format_replan_prompt",
|
|
41
|
+
"format_structured_plan_prompt",
|
|
42
|
+
"format_reflection_prompt",
|
|
43
|
+
"format_error_analysis_prompt",
|
|
44
|
+
]
|