process-gpt-agent-sdk 0.2.0__py3-none-any.whl → 0.2.2__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.
Potentially problematic release.
This version of process-gpt-agent-sdk might be problematic. Click here for more details.
- {process_gpt_agent_sdk-0.2.0.dist-info → process_gpt_agent_sdk-0.2.2.dist-info}/METADATA +1 -1
- process_gpt_agent_sdk-0.2.2.dist-info/RECORD +18 -0
- processgpt_agent_sdk/core/database.py +460 -509
- processgpt_agent_sdk/server.py +28 -4
- processgpt_agent_sdk/tools/human_query_tool.py +42 -34
- processgpt_agent_sdk/tools/safe_tool_loader.py +31 -7
- processgpt_agent_sdk/utils/context_manager.py +8 -0
- processgpt_agent_sdk/utils/crewai_event_listener.py +6 -2
- processgpt_agent_sdk/utils/logger.py +10 -1
- processgpt_agent_sdk/utils/summarizer.py +146 -122
- process_gpt_agent_sdk-0.2.0.dist-info/RECORD +0 -18
- {process_gpt_agent_sdk-0.2.0.dist-info → process_gpt_agent_sdk-0.2.2.dist-info}/WHEEL +0 -0
- {process_gpt_agent_sdk-0.2.0.dist-info → process_gpt_agent_sdk-0.2.2.dist-info}/top_level.txt +0 -0
|
@@ -1,122 +1,146 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
"
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
"
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import json
|
|
6
|
+
import asyncio
|
|
7
|
+
from typing import Any, Tuple
|
|
8
|
+
|
|
9
|
+
import openai
|
|
10
|
+
from .logger import handle_application_error, write_log_message
|
|
11
|
+
|
|
12
|
+
# =============================================================================
|
|
13
|
+
# 요약기(Summarizer)
|
|
14
|
+
# 설명: 출력/피드백/현재 내용으로부터 OpenAI를 사용해 간단 요약을 생성한다.
|
|
15
|
+
# =============================================================================
|
|
16
|
+
|
|
17
|
+
async def summarize_async(outputs: Any, feedbacks: Any, contents: Any = None) -> Tuple[str, str]:
|
|
18
|
+
"""(output_summary, feedback_summary)를 비동기로 생성해 반환한다.
|
|
19
|
+
키 없음/오류 시 빈 문자열 폴백, 취소는 상위로 전파."""
|
|
20
|
+
outputs_str = _convert_to_string(outputs).strip()
|
|
21
|
+
feedbacks_str = _convert_to_string(feedbacks).strip()
|
|
22
|
+
contents_str = _convert_to_string(contents).strip()
|
|
23
|
+
|
|
24
|
+
output_summary = ""
|
|
25
|
+
feedback_summary = ""
|
|
26
|
+
|
|
27
|
+
if outputs_str:
|
|
28
|
+
write_log_message("요약 호출(이전결과물)")
|
|
29
|
+
output_prompt = _create_output_summary_prompt(outputs_str)
|
|
30
|
+
output_summary = await _call_openai_api_async(output_prompt, task_name="output")
|
|
31
|
+
|
|
32
|
+
if feedbacks_str or contents_str:
|
|
33
|
+
write_log_message("요약 호출(피드백)")
|
|
34
|
+
feedback_prompt = _create_feedback_summary_prompt(feedbacks_str, contents_str)
|
|
35
|
+
feedback_summary = await _call_openai_api_async(feedback_prompt, task_name="feedback")
|
|
36
|
+
|
|
37
|
+
return output_summary or "", feedback_summary or ""
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# =============================================================================
|
|
41
|
+
# 헬퍼: 문자열 변환
|
|
42
|
+
# =============================================================================
|
|
43
|
+
|
|
44
|
+
def _convert_to_string(data: Any) -> str:
|
|
45
|
+
"""임의 데이터를 안전하게 문자열로 변환한다."""
|
|
46
|
+
if data is None:
|
|
47
|
+
return ""
|
|
48
|
+
if isinstance(data, str):
|
|
49
|
+
return data
|
|
50
|
+
try:
|
|
51
|
+
return json.dumps(data, ensure_ascii=False)
|
|
52
|
+
except Exception:
|
|
53
|
+
return str(data)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# =============================================================================
|
|
57
|
+
# 헬퍼: 프롬프트 생성
|
|
58
|
+
# =============================================================================
|
|
59
|
+
|
|
60
|
+
def _create_output_summary_prompt(outputs_str: str) -> str:
|
|
61
|
+
"""결과물 요약용 사용자 프롬프트를 생성한다."""
|
|
62
|
+
return (
|
|
63
|
+
"다음 작업 결과를 정리해주세요:\n\n"
|
|
64
|
+
f"{outputs_str}\n\n"
|
|
65
|
+
"처리 방식:\n"
|
|
66
|
+
"- 짧은 내용은 요약하지 말고 그대로 유지 (정보 손실 방지)\n"
|
|
67
|
+
"- 긴 내용만 적절히 요약하여 핵심 정보 전달\n"
|
|
68
|
+
"- 수치, 목차, 인물명, 물건명, 날짜, 시간 등 객관적 정보는 반드시 포함\n"
|
|
69
|
+
"- 왜곡이나 의미 변경 금지, 원본 의미 보존\n"
|
|
70
|
+
"- 중복만 정리하고 핵심 내용은 모두 보존\n"
|
|
71
|
+
"- 하나의 통합된 문맥으로 작성"
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _create_feedback_summary_prompt(feedbacks_str: str, contents_str: str = "") -> str:
|
|
76
|
+
"""피드백/현재 결과물을 통합 요약하는 사용자 프롬프트를 생성한다."""
|
|
77
|
+
feedback_section = (
|
|
78
|
+
f"=== 피드백 내용 ===\n{feedbacks_str}" if feedbacks_str and feedbacks_str.strip() else ""
|
|
79
|
+
)
|
|
80
|
+
content_section = (
|
|
81
|
+
f"=== 현재 결과물/작업 내용 ===\n{contents_str}" if contents_str and contents_str.strip() else ""
|
|
82
|
+
)
|
|
83
|
+
return (
|
|
84
|
+
"다음은 사용자의 피드백과 결과물입니다. 이를 분석하여 통합된 피드백을 작성해주세요:\n\n"
|
|
85
|
+
f"{feedback_section}\n\n{content_section}\n\n"
|
|
86
|
+
"상황 분석 및 처리 방식:\n"
|
|
87
|
+
"- 현재 결과물을 보고 문제/개선 필요점 판단\n"
|
|
88
|
+
"- 최신 피드백을 최우선으로 반영\n"
|
|
89
|
+
"- 실행 가능한 개선사항 제시\n"
|
|
90
|
+
"- 하나의 통합된 문장으로 작성 (최대 2500자)"
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
# =============================================================================
|
|
95
|
+
# 헬퍼: 시스템 프롬프트 선택
|
|
96
|
+
# =============================================================================
|
|
97
|
+
|
|
98
|
+
def _get_system_prompt(task_name: str) -> str:
|
|
99
|
+
"""작업 종류에 맞는 시스템 프롬프트를 반환한다."""
|
|
100
|
+
if task_name == "feedback":
|
|
101
|
+
return (
|
|
102
|
+
"당신은 피드백 정리 전문가입니다. 최신 피드백을 우선 반영하고,"
|
|
103
|
+
" 문맥을 연결하여 하나의 완전한 요청으로 통합해 주세요."
|
|
104
|
+
)
|
|
105
|
+
return (
|
|
106
|
+
"당신은 결과물 요약 전문가입니다. 긴 내용만 요약하고,"
|
|
107
|
+
" 수치/고유명/날짜 등 객관 정보를 보존해 주세요."
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
# =============================================================================
|
|
112
|
+
# 외부 호출: OpenAI API
|
|
113
|
+
# =============================================================================
|
|
114
|
+
|
|
115
|
+
async def _call_openai_api_async(prompt: str, task_name: str) -> str:
|
|
116
|
+
"""OpenAI 비동기 API를 호출해 요약 텍스트를 생성한다."""
|
|
117
|
+
|
|
118
|
+
if not (os.getenv("OPENAI_API_KEY") or os.getenv("OPENAI_API_KEY_BETA")):
|
|
119
|
+
write_log_message("요약 비활성화: OPENAI_API_KEY 미설정")
|
|
120
|
+
return ""
|
|
121
|
+
|
|
122
|
+
client = openai.AsyncOpenAI()
|
|
123
|
+
system_prompt = _get_system_prompt(task_name)
|
|
124
|
+
model = os.getenv("OPENAI_SUMMARY_MODEL", "gpt-4o-mini")
|
|
125
|
+
|
|
126
|
+
for attempt in range(1, 4):
|
|
127
|
+
try:
|
|
128
|
+
resp = await client.chat.completions.create(
|
|
129
|
+
model=model,
|
|
130
|
+
messages=[
|
|
131
|
+
{"role": "system", "content": system_prompt},
|
|
132
|
+
{"role": "user", "content": prompt},
|
|
133
|
+
],
|
|
134
|
+
temperature=0.1,
|
|
135
|
+
timeout=30.0,
|
|
136
|
+
)
|
|
137
|
+
return (resp.choices[0].message.content or "").strip()
|
|
138
|
+
except asyncio.CancelledError:
|
|
139
|
+
raise
|
|
140
|
+
except Exception as e:
|
|
141
|
+
if attempt < 3:
|
|
142
|
+
handle_application_error("요약 호출 오류(재시도)", e, raise_error=False, extra={"attempt": attempt})
|
|
143
|
+
await asyncio.sleep(0.8 * (2 ** (attempt - 1)))
|
|
144
|
+
continue
|
|
145
|
+
handle_application_error("요약 호출 최종 실패", e, raise_error=False)
|
|
146
|
+
return ""
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
processgpt_agent_sdk/__init__.py,sha256=IvAL5WBZhI83LYQogRP6-i04bxZkhmkgmES4FRQY888,185
|
|
2
|
-
processgpt_agent_sdk/server.py,sha256=1RCUPNeuDJ7ZQfIiz4d0G9oWNKbYZGWls6SV2U8MR6I,8966
|
|
3
|
-
processgpt_agent_sdk/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
processgpt_agent_sdk/core/database.py,sha256=GSXYcJXADs0wCoFo54lu82MnqQPoEvqQ6n5BDXA8o60,18956
|
|
5
|
-
processgpt_agent_sdk/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
processgpt_agent_sdk/tools/human_query_tool.py,sha256=pntznVNt3FOsWunPe3-WIlRd7cB2ibyM6Tndyi6YQJk,10314
|
|
7
|
-
processgpt_agent_sdk/tools/knowledge_tools.py,sha256=AOtxvLypu343877ZzzELGq3At-E_2NiAqEw0Njlephg,8937
|
|
8
|
-
processgpt_agent_sdk/tools/safe_tool_loader.py,sha256=7WSR6tMxPdNodY4z-BRAO6hH6zTniY_qM5VlQIdqqjM,6132
|
|
9
|
-
processgpt_agent_sdk/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
-
processgpt_agent_sdk/utils/context_manager.py,sha256=QDL5ya4FfUPx4EKScSVIllJGKS1-zctYvxg2FZB2b0A,1383
|
|
11
|
-
processgpt_agent_sdk/utils/crewai_event_listener.py,sha256=343btAePWM19KbjDwElYb9K3FIbVm80_ZLLdOyFSsj4,8815
|
|
12
|
-
processgpt_agent_sdk/utils/event_handler.py,sha256=ogmKcfhD2PHVQCQHpjVevZOe6LThwKIsrJcWFYqGlPA,2337
|
|
13
|
-
processgpt_agent_sdk/utils/logger.py,sha256=2hX1GClkrE3ZVzvV61ORlZg4QDh59g-lr3qJyIRAfD4,948
|
|
14
|
-
processgpt_agent_sdk/utils/summarizer.py,sha256=j57R5TSr8QNy_INA-sh0tFEUCGcea07brT5sahHxATI,4567
|
|
15
|
-
process_gpt_agent_sdk-0.2.0.dist-info/METADATA,sha256=4cg2HqmrXfT0dd_qgQ4JDDh7a6N828NRmsblMiNanVM,12898
|
|
16
|
-
process_gpt_agent_sdk-0.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
17
|
-
process_gpt_agent_sdk-0.2.0.dist-info/top_level.txt,sha256=Xe6zrj3_3Vv7d0pl5RRtenVUckwOVBVLQn2P03j5REo,21
|
|
18
|
-
process_gpt_agent_sdk-0.2.0.dist-info/RECORD,,
|
|
File without changes
|
{process_gpt_agent_sdk-0.2.0.dist-info → process_gpt_agent_sdk-0.2.2.dist-info}/top_level.txt
RENAMED
|
File without changes
|