process-gpt-agent-sdk 0.2.7__py3-none-any.whl → 0.2.9__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.9.dist-info/METADATA +1026 -0
- process_gpt_agent_sdk-0.2.9.dist-info/RECORD +19 -0
- processgpt_agent_sdk/__init__.py +11 -7
- processgpt_agent_sdk/core/database.py +464 -464
- processgpt_agent_sdk/server.py +313 -292
- processgpt_agent_sdk/simulator.py +231 -0
- processgpt_agent_sdk/tools/human_query_tool.py +211 -211
- processgpt_agent_sdk/tools/knowledge_tools.py +206 -206
- processgpt_agent_sdk/tools/safe_tool_loader.py +209 -209
- processgpt_agent_sdk/utils/context_manager.py +45 -45
- processgpt_agent_sdk/utils/crewai_event_listener.py +205 -205
- processgpt_agent_sdk/utils/event_handler.py +72 -72
- processgpt_agent_sdk/utils/logger.py +73 -39
- processgpt_agent_sdk/utils/summarizer.py +146 -146
- process_gpt_agent_sdk-0.2.7.dist-info/METADATA +0 -378
- process_gpt_agent_sdk-0.2.7.dist-info/RECORD +0 -18
- {process_gpt_agent_sdk-0.2.7.dist-info → process_gpt_agent_sdk-0.2.9.dist-info}/WHEEL +0 -0
- {process_gpt_agent_sdk-0.2.7.dist-info → process_gpt_agent_sdk-0.2.9.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,1026 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: process-gpt-agent-sdk
|
|
3
|
+
Version: 0.2.9
|
|
4
|
+
Summary: Supabase 기반 이벤트/작업 폴링으로 A2A AgentExecutor를 실행하는 SDK
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/your-org/process-gpt-agent-sdk
|
|
7
|
+
Project-URL: Issues, https://github.com/your-org/process-gpt-agent-sdk/issues
|
|
8
|
+
Keywords: agent,a2a,supabase,workflow,sdk,processgpt
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Requires-Python: >=3.9
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
Requires-Dist: supabase>=2.0.0
|
|
16
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
17
|
+
Requires-Dist: click>=8.0.0
|
|
18
|
+
Requires-Dist: asyncio-mqtt>=0.13.0
|
|
19
|
+
Requires-Dist: jsonschema>=4.0.0
|
|
20
|
+
Requires-Dist: structlog>=23.0.0
|
|
21
|
+
Requires-Dist: typing-extensions>=4.0.0
|
|
22
|
+
Requires-Dist: python-dateutil>=2.8.0
|
|
23
|
+
Requires-Dist: openai>=1.40.0
|
|
24
|
+
Requires-Dist: a2a-sdk==0.2.4
|
|
25
|
+
Requires-Dist: requests>=2.31.0
|
|
26
|
+
Requires-Dist: anyio>=4.4.0
|
|
27
|
+
Requires-Dist: pydantic>=2.7.0
|
|
28
|
+
Requires-Dist: crewai>=0.51.0
|
|
29
|
+
Requires-Dist: crewai-tools>=0.8.2
|
|
30
|
+
Requires-Dist: mem0ai>=0.1.0
|
|
31
|
+
Requires-Dist: mcp>=1.0.0
|
|
32
|
+
|
|
33
|
+
배포: ./release.sh 0.2.8 (버전은 pyproject.toml에서 확인 후 진행) 조금이라도 수정을 했다면, 버전은 계속 올려가면서 진행해야합니다.
|
|
34
|
+
|
|
35
|
+
# ProcessGPT Agent Framework
|
|
36
|
+
|
|
37
|
+
Google A2A SDK의 인터페이스를 활용하면서 웹소켓 대신 Supabase 실시간 DB를 사용하는 에이전트 실행 프레임워크입니다.
|
|
38
|
+
|
|
39
|
+
## 🏗️ 아키텍처 개요
|
|
40
|
+
|
|
41
|
+
이 프레임워크는 기존의 Google A2A SDK의 `AgentExecutor`와 `RequestContext` 인터페이스를 그대로 활용하되, 웹소켓 기반 통신 대신 Supabase 데이터베이스를 중간 매개체로 사용합니다.
|
|
42
|
+
|
|
43
|
+
### 핵심 구성 요소
|
|
44
|
+
|
|
45
|
+
1. **Supabase Database Tables**
|
|
46
|
+
- `todolist`: 에이전트가 처리해야 할 작업들을 저장
|
|
47
|
+
- `events`: 각 태스크의 실행 상태와 진행 과정을 추적
|
|
48
|
+
|
|
49
|
+
2. **ProcessGPT Server**
|
|
50
|
+
- Supabase `todolist` 테이블을 폴링하여 대기 중인 작업을 감지
|
|
51
|
+
- Google A2A SDK의 `AgentExecutor.execute()` 메서드를 호출
|
|
52
|
+
- 커스터마이즈된 `EventQueue`를 통해 이벤트를 Supabase에 저장
|
|
53
|
+
|
|
54
|
+
3. **Custom Classes**
|
|
55
|
+
- `ProcessGPTRequestContext`: todolist 데이터를 기반으로 한 RequestContext 구현
|
|
56
|
+
- `ProcessGPTEventQueue`: Supabase events 테이블에 이벤트를 저장하는 EventQueue 구현
|
|
57
|
+
|
|
58
|
+
## 🚀 빠른 시작 가이드
|
|
59
|
+
|
|
60
|
+
### 1. AgentExecutor 구현
|
|
61
|
+
|
|
62
|
+
먼저 비즈니스 로직을 처리할 사용자 정의 AgentExecutor를 구현합니다:
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
import asyncio
|
|
66
|
+
from typing import Any, Dict
|
|
67
|
+
from a2a.server.agent_execution import AgentExecutor, RequestContext
|
|
68
|
+
from a2a.server.events import EventQueue, Event
|
|
69
|
+
|
|
70
|
+
class MyBusinessAgentExecutor(AgentExecutor):
|
|
71
|
+
"""비즈니스 로직을 처리하는 사용자 정의 AgentExecutor"""
|
|
72
|
+
|
|
73
|
+
def __init__(self, config: Dict[str, Any] = None):
|
|
74
|
+
self.config = config or {}
|
|
75
|
+
self.is_cancelled = False
|
|
76
|
+
|
|
77
|
+
async def execute(self, context: RequestContext, event_queue: EventQueue) -> None:
|
|
78
|
+
"""메인 실행 로직"""
|
|
79
|
+
# 1. 사용자 입력 가져오기
|
|
80
|
+
user_input = context.get_user_input()
|
|
81
|
+
context_data = context.get_context_data()
|
|
82
|
+
|
|
83
|
+
# 2. 시작 이벤트 발송
|
|
84
|
+
start_event = Event(
|
|
85
|
+
type="task_started",
|
|
86
|
+
data={
|
|
87
|
+
"message": f"작업 시작: {user_input}",
|
|
88
|
+
"user_input": user_input,
|
|
89
|
+
"agent_type": "MyBusinessAgent"
|
|
90
|
+
}
|
|
91
|
+
)
|
|
92
|
+
event_queue.enqueue_event(start_event)
|
|
93
|
+
|
|
94
|
+
try:
|
|
95
|
+
# 3. 작업 단계별 처리
|
|
96
|
+
await self._process_business_logic(user_input, context_data, event_queue)
|
|
97
|
+
|
|
98
|
+
# 4. 성공 완료 이벤트
|
|
99
|
+
if not self.is_cancelled:
|
|
100
|
+
success_event = Event(
|
|
101
|
+
type="done",
|
|
102
|
+
data={
|
|
103
|
+
"message": "작업이 성공적으로 완료되었습니다",
|
|
104
|
+
"success": True
|
|
105
|
+
}
|
|
106
|
+
)
|
|
107
|
+
event_queue.enqueue_event(success_event)
|
|
108
|
+
|
|
109
|
+
except Exception as e:
|
|
110
|
+
# 5. 오류 이벤트
|
|
111
|
+
error_event = Event(
|
|
112
|
+
type="error",
|
|
113
|
+
data={
|
|
114
|
+
"message": f"작업 처리 중 오류 발생: {str(e)}",
|
|
115
|
+
"error": str(e)
|
|
116
|
+
}
|
|
117
|
+
)
|
|
118
|
+
event_queue.enqueue_event(error_event)
|
|
119
|
+
raise
|
|
120
|
+
|
|
121
|
+
async def cancel(self, context: RequestContext, event_queue: EventQueue) -> None:
|
|
122
|
+
"""작업 취소 처리"""
|
|
123
|
+
self.is_cancelled = True
|
|
124
|
+
|
|
125
|
+
cancel_event = Event(
|
|
126
|
+
type="cancelled",
|
|
127
|
+
data={
|
|
128
|
+
"message": "작업이 취소되었습니다",
|
|
129
|
+
"cancelled_by": "user_request"
|
|
130
|
+
}
|
|
131
|
+
)
|
|
132
|
+
event_queue.enqueue_event(cancel_event)
|
|
133
|
+
|
|
134
|
+
async def _process_business_logic(self, user_input: str, context_data: Dict[str, Any], event_queue: EventQueue):
|
|
135
|
+
"""실제 비즈니스 로직 처리"""
|
|
136
|
+
steps = [
|
|
137
|
+
("분석", "사용자 요청을 분석하고 있습니다..."),
|
|
138
|
+
("계획", "처리 계획을 수립하고 있습니다..."),
|
|
139
|
+
("실행", "작업을 실행하고 있습니다..."),
|
|
140
|
+
("검증", "결과를 검증하고 있습니다..."),
|
|
141
|
+
("완료", "최종 결과를 준비하고 있습니다...")
|
|
142
|
+
]
|
|
143
|
+
|
|
144
|
+
for i, (step_name, step_message) in enumerate(steps, 1):
|
|
145
|
+
if self.is_cancelled:
|
|
146
|
+
break
|
|
147
|
+
|
|
148
|
+
# 진행 상황 이벤트
|
|
149
|
+
progress_event = Event(
|
|
150
|
+
type="progress",
|
|
151
|
+
data={
|
|
152
|
+
"step": i,
|
|
153
|
+
"total_steps": len(steps),
|
|
154
|
+
"step_name": step_name,
|
|
155
|
+
"message": step_message,
|
|
156
|
+
"progress_percentage": (i / len(steps)) * 100
|
|
157
|
+
}
|
|
158
|
+
)
|
|
159
|
+
event_queue.enqueue_event(progress_event)
|
|
160
|
+
|
|
161
|
+
# 실제 작업 수행 (여기에 AI 모델 호출, 데이터 처리 등)
|
|
162
|
+
await asyncio.sleep(1.0) # 시뮬레이션용 지연
|
|
163
|
+
|
|
164
|
+
# 최종 결과 출력
|
|
165
|
+
if not self.is_cancelled:
|
|
166
|
+
result = await self._generate_final_result(user_input, context_data)
|
|
167
|
+
|
|
168
|
+
output_event = Event(
|
|
169
|
+
type="output",
|
|
170
|
+
data={
|
|
171
|
+
"content": result,
|
|
172
|
+
"final": True
|
|
173
|
+
}
|
|
174
|
+
)
|
|
175
|
+
event_queue.enqueue_event(output_event)
|
|
176
|
+
|
|
177
|
+
async def _generate_final_result(self, user_input: str, context_data: Dict[str, Any]) -> Dict[str, Any]:
|
|
178
|
+
"""최종 결과 생성"""
|
|
179
|
+
return {
|
|
180
|
+
"input": user_input,
|
|
181
|
+
"result": f"'{user_input}' 요청이 성공적으로 처리되었습니다.",
|
|
182
|
+
"processed_at": "2024-01-15T10:30:45Z",
|
|
183
|
+
"agent_type": "MyBusinessAgent",
|
|
184
|
+
"status": "completed"
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### 2. ProcessGPTAgentServer 생성 및 시작
|
|
189
|
+
|
|
190
|
+
AgentExecutor를 사용하여 ProcessGPT 서버를 생성하고 실행합니다:
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
import asyncio
|
|
194
|
+
import os
|
|
195
|
+
from processgpt_agent_sdk import ProcessGPTAgentServer
|
|
196
|
+
from my_custom_executor import MyBusinessAgentExecutor
|
|
197
|
+
|
|
198
|
+
async def main():
|
|
199
|
+
"""ProcessGPT 서버 메인 함수"""
|
|
200
|
+
|
|
201
|
+
# 1. 환경변수 확인
|
|
202
|
+
if not os.getenv("SUPABASE_URL") or not os.getenv("SUPABASE_ANON_KEY"):
|
|
203
|
+
print("오류: SUPABASE_URL과 SUPABASE_ANON_KEY 환경변수가 필요합니다.")
|
|
204
|
+
return
|
|
205
|
+
|
|
206
|
+
# 2. 사용자 정의 실행기 생성
|
|
207
|
+
executor = MyBusinessAgentExecutor(config={"timeout": 30})
|
|
208
|
+
|
|
209
|
+
# 3. ProcessGPT 서버 생성
|
|
210
|
+
server = ProcessGPTAgentServer(
|
|
211
|
+
executor=executor,
|
|
212
|
+
polling_interval=5, # 5초마다 폴링
|
|
213
|
+
agent_orch="my_business_agent" # 에이전트 타입 식별자
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
print("ProcessGPT 서버 시작...")
|
|
217
|
+
print(f"에이전트 타입: my_business_agent")
|
|
218
|
+
print(f"폴링 간격: 5초")
|
|
219
|
+
print("Ctrl+C로 서버를 중지할 수 있습니다.")
|
|
220
|
+
|
|
221
|
+
try:
|
|
222
|
+
# 4. 서버 실행 (무한 루프)
|
|
223
|
+
await server.run()
|
|
224
|
+
except KeyboardInterrupt:
|
|
225
|
+
print("\n서버 중지 요청...")
|
|
226
|
+
server.stop()
|
|
227
|
+
print("서버가 정상적으로 중지되었습니다.")
|
|
228
|
+
|
|
229
|
+
if __name__ == "__main__":
|
|
230
|
+
asyncio.run(main())
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
실행하기:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
# 서버 실행
|
|
237
|
+
python my_server.py
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### 3. Supabase 구성
|
|
241
|
+
|
|
242
|
+
#### 3.1 Supabase 프로젝트 설정
|
|
243
|
+
|
|
244
|
+
1. [Supabase](https://supabase.com) 에서 새 프로젝트 생성
|
|
245
|
+
2. 프로젝트 설정에서 API 키 복사
|
|
246
|
+
3. 환경변수 설정:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
# .env 파일 생성
|
|
250
|
+
echo "SUPABASE_URL=https://your-project.supabase.co" >> .env
|
|
251
|
+
echo "SUPABASE_ANON_KEY=your-anon-key-here" >> .env
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
#### 3.2 데이터베이스 스키마 생성
|
|
255
|
+
|
|
256
|
+
Supabase SQL Editor에서 다음 스키마를 실행:
|
|
257
|
+
|
|
258
|
+
```sql
|
|
259
|
+
-- 1. 테이블 타입 정의
|
|
260
|
+
CREATE TYPE todo_status AS ENUM (
|
|
261
|
+
'PENDING', 'IN_PROGRESS', 'DONE', 'CANCELLED', 'SUBMITTED'
|
|
262
|
+
);
|
|
263
|
+
|
|
264
|
+
CREATE TYPE agent_mode AS ENUM (
|
|
265
|
+
'DRAFT', 'COMPLETE'
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
CREATE TYPE agent_orch AS ENUM (
|
|
269
|
+
'my_business_agent', 'data_analyst', 'customer_service', 'project_manager'
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
CREATE TYPE draft_status AS ENUM (
|
|
273
|
+
'STARTED', 'COMPLETED', 'FB_REQUESTED'
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
-- 2. TodoList 테이블 생성
|
|
277
|
+
CREATE TABLE IF NOT EXISTS todolist (
|
|
278
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
279
|
+
user_id TEXT NOT NULL,
|
|
280
|
+
proc_inst_id TEXT,
|
|
281
|
+
proc_def_id TEXT,
|
|
282
|
+
activity_id TEXT,
|
|
283
|
+
activity_name TEXT NOT NULL,
|
|
284
|
+
start_date TIMESTAMP DEFAULT NOW(),
|
|
285
|
+
end_date TIMESTAMP,
|
|
286
|
+
description TEXT NOT NULL,
|
|
287
|
+
tool TEXT,
|
|
288
|
+
due_date TIMESTAMP,
|
|
289
|
+
tenant_id TEXT NOT NULL,
|
|
290
|
+
reference_ids TEXT[],
|
|
291
|
+
adhoc BOOLEAN DEFAULT FALSE,
|
|
292
|
+
assignees JSONB,
|
|
293
|
+
duration INTEGER,
|
|
294
|
+
output JSONB,
|
|
295
|
+
retry INTEGER DEFAULT 0,
|
|
296
|
+
consumer TEXT,
|
|
297
|
+
log TEXT,
|
|
298
|
+
draft JSONB,
|
|
299
|
+
project_id UUID,
|
|
300
|
+
feedback JSONB,
|
|
301
|
+
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
302
|
+
username TEXT,
|
|
303
|
+
status todo_status DEFAULT 'PENDING',
|
|
304
|
+
agent_mode agent_mode DEFAULT 'COMPLETE',
|
|
305
|
+
agent_orch agent_orch DEFAULT 'my_business_agent',
|
|
306
|
+
temp_feedback TEXT,
|
|
307
|
+
draft_status draft_status
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
-- 3. Events 테이블 생성
|
|
311
|
+
CREATE TABLE IF NOT EXISTS events (
|
|
312
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
313
|
+
todolist_id UUID NOT NULL REFERENCES todolist(id),
|
|
314
|
+
event_type VARCHAR(50) NOT NULL,
|
|
315
|
+
event_data JSONB NOT NULL,
|
|
316
|
+
context_id VARCHAR(255),
|
|
317
|
+
task_id VARCHAR(255),
|
|
318
|
+
message TEXT,
|
|
319
|
+
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
320
|
+
);
|
|
321
|
+
|
|
322
|
+
-- 4. 인덱스 생성
|
|
323
|
+
CREATE INDEX IF NOT EXISTS idx_todolist_status_agent ON todolist(status, agent_orch);
|
|
324
|
+
CREATE INDEX IF NOT EXISTS idx_todolist_proc_inst ON todolist(proc_inst_id);
|
|
325
|
+
CREATE INDEX IF NOT EXISTS idx_events_todolist_id ON events(todolist_id);
|
|
326
|
+
CREATE INDEX IF NOT EXISTS idx_events_created_at ON events(created_at);
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
#### 3.3 필수 함수 생성
|
|
330
|
+
|
|
331
|
+
프로젝트에 포함된 `function.sql` 파일을 Supabase에서 실행:
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
# SQL 파일 내용을 Supabase SQL Editor에 복사하여 실행
|
|
335
|
+
cat function.sql
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### 4. SQL Insert로 테스트
|
|
339
|
+
|
|
340
|
+
#### 4.1 직접 SQL 테스트
|
|
341
|
+
|
|
342
|
+
Supabase SQL Editor에서 테스트 작업 생성:
|
|
343
|
+
|
|
344
|
+
```sql
|
|
345
|
+
-- 테스트 작업 삽입
|
|
346
|
+
INSERT INTO todolist (
|
|
347
|
+
user_id,
|
|
348
|
+
proc_inst_id,
|
|
349
|
+
activity_name,
|
|
350
|
+
description,
|
|
351
|
+
tenant_id,
|
|
352
|
+
agent_orch,
|
|
353
|
+
status
|
|
354
|
+
) VALUES (
|
|
355
|
+
'test-user-001',
|
|
356
|
+
'proc-inst-' || gen_random_uuid()::text,
|
|
357
|
+
'data_analysis_task',
|
|
358
|
+
'월별 매출 데이터를 분석하고 트렌드를 파악해주세요',
|
|
359
|
+
'test-tenant-001',
|
|
360
|
+
'my_business_agent',
|
|
361
|
+
'IN_PROGRESS'
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
-- 삽입된 작업 확인
|
|
365
|
+
SELECT id, description, status, agent_orch, created_at
|
|
366
|
+
FROM todolist
|
|
367
|
+
ORDER BY created_at DESC
|
|
368
|
+
LIMIT 5;
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
#### 4.2 Python 클라이언트로 테스트
|
|
372
|
+
|
|
373
|
+
```python
|
|
374
|
+
import os
|
|
375
|
+
from supabase import create_client, Client
|
|
376
|
+
|
|
377
|
+
# Supabase 클라이언트 초기화
|
|
378
|
+
supabase: Client = create_client(
|
|
379
|
+
os.getenv("SUPABASE_URL"),
|
|
380
|
+
os.getenv("SUPABASE_ANON_KEY")
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
def create_test_task(description: str, agent_type: str = "my_business_agent"):
|
|
384
|
+
"""테스트 작업 생성"""
|
|
385
|
+
|
|
386
|
+
task_data = {
|
|
387
|
+
"user_id": "test-user-001",
|
|
388
|
+
"proc_inst_id": f"proc-inst-{os.urandom(8).hex()}",
|
|
389
|
+
"activity_name": "test_task",
|
|
390
|
+
"description": description,
|
|
391
|
+
"tenant_id": "test-tenant-001",
|
|
392
|
+
"agent_orch": agent_type,
|
|
393
|
+
"status": "IN_PROGRESS"
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
try:
|
|
397
|
+
result = supabase.table("todolist").insert(task_data).execute()
|
|
398
|
+
task_id = result.data[0]["id"]
|
|
399
|
+
print(f"✅ 작업 생성 성공: {task_id}")
|
|
400
|
+
print(f"📝 설명: {description}")
|
|
401
|
+
return task_id
|
|
402
|
+
except Exception as e:
|
|
403
|
+
print(f"❌ 작업 생성 실패: {e}")
|
|
404
|
+
return None
|
|
405
|
+
|
|
406
|
+
def monitor_task_progress(task_id: str):
|
|
407
|
+
"""작업 진행상황 모니터링"""
|
|
408
|
+
|
|
409
|
+
print(f"\n📊 작업 진행상황 모니터링: {task_id}")
|
|
410
|
+
|
|
411
|
+
try:
|
|
412
|
+
# 작업 상태 조회
|
|
413
|
+
task_result = supabase.table("todolist").select("*").eq("id", task_id).execute()
|
|
414
|
+
if task_result.data:
|
|
415
|
+
task = task_result.data[0]
|
|
416
|
+
print(f"상태: {task['status']}")
|
|
417
|
+
print(f"Draft 상태: {task.get('draft_status', 'None')}")
|
|
418
|
+
|
|
419
|
+
# 관련 이벤트 조회
|
|
420
|
+
events_result = supabase.table("events").select("*").eq("todolist_id", task_id).order("created_at").execute()
|
|
421
|
+
|
|
422
|
+
print(f"\n📋 이벤트 히스토리 ({len(events_result.data)}개):")
|
|
423
|
+
for event in events_result.data:
|
|
424
|
+
print(f" [{event['created_at']}] {event['event_type']}: {event.get('message', 'N/A')}")
|
|
425
|
+
|
|
426
|
+
except Exception as e:
|
|
427
|
+
print(f"❌ 모니터링 실패: {e}")
|
|
428
|
+
|
|
429
|
+
if __name__ == "__main__":
|
|
430
|
+
# 테스트 시나리오
|
|
431
|
+
test_cases = [
|
|
432
|
+
"월별 매출 데이터를 분석해주세요",
|
|
433
|
+
"고객 만족도 조사 보고서를 작성해주세요",
|
|
434
|
+
"고객 문의에 대한 응답을 준비해주세요",
|
|
435
|
+
"신제품 출시 프로젝트 계획을 수립해주세요"
|
|
436
|
+
]
|
|
437
|
+
|
|
438
|
+
print("🚀 ProcessGPT 테스트 시작\n")
|
|
439
|
+
|
|
440
|
+
for i, description in enumerate(test_cases, 1):
|
|
441
|
+
print(f"--- 테스트 {i} ---")
|
|
442
|
+
task_id = create_test_task(description)
|
|
443
|
+
|
|
444
|
+
if task_id:
|
|
445
|
+
# 잠시 대기 후 진행상황 확인
|
|
446
|
+
import time
|
|
447
|
+
time.sleep(2)
|
|
448
|
+
monitor_task_progress(task_id)
|
|
449
|
+
|
|
450
|
+
print("\n" + "="*50 + "\n")
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
실행하기:
|
|
454
|
+
|
|
455
|
+
```bash
|
|
456
|
+
python test_client.py
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
#### 4.3 실시간 모니터링
|
|
460
|
+
|
|
461
|
+
작업 진행상황을 실시간으로 모니터링:
|
|
462
|
+
|
|
463
|
+
```python
|
|
464
|
+
import asyncio
|
|
465
|
+
from supabase import create_client
|
|
466
|
+
|
|
467
|
+
async def real_time_monitor():
|
|
468
|
+
"""실시간 이벤트 모니터링"""
|
|
469
|
+
|
|
470
|
+
supabase = create_client(
|
|
471
|
+
os.getenv("SUPABASE_URL"),
|
|
472
|
+
os.getenv("SUPABASE_ANON_KEY")
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
print("📡 실시간 모니터링 시작...")
|
|
476
|
+
|
|
477
|
+
while True:
|
|
478
|
+
try:
|
|
479
|
+
# 최근 이벤트 조회
|
|
480
|
+
events = supabase.table("events")\
|
|
481
|
+
.select("*, todolist!inner(description)")\
|
|
482
|
+
.order("created_at", desc=True)\
|
|
483
|
+
.limit(5)\
|
|
484
|
+
.execute()
|
|
485
|
+
|
|
486
|
+
for event in events.data:
|
|
487
|
+
task_desc = event['todolist']['description'][:50] + "..."
|
|
488
|
+
print(f"[{event['created_at']}] {event['event_type']}: {task_desc}")
|
|
489
|
+
|
|
490
|
+
await asyncio.sleep(5) # 5초마다 체크
|
|
491
|
+
|
|
492
|
+
except KeyboardInterrupt:
|
|
493
|
+
print("\n모니터링 중지")
|
|
494
|
+
break
|
|
495
|
+
except Exception as e:
|
|
496
|
+
print(f"모니터링 오류: {e}")
|
|
497
|
+
await asyncio.sleep(5)
|
|
498
|
+
|
|
499
|
+
# 실행
|
|
500
|
+
asyncio.run(real_time_monitor())
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
---
|
|
504
|
+
|
|
505
|
+
## 🎮 ProcessGPT Agent Simulator
|
|
506
|
+
|
|
507
|
+
**데이터베이스 연결 없이** ProcessGPT 에이전트를 시뮬레이션할 수 있는 완전한 툴킷이 제공됩니다. 개발, 테스트, 데모 목적으로 사용할 수 있습니다.
|
|
508
|
+
|
|
509
|
+
### 🚀 빠른 시작
|
|
510
|
+
|
|
511
|
+
#### 독립적인 시뮬레이터 (추천)
|
|
512
|
+
|
|
513
|
+
```bash
|
|
514
|
+
# 기본 시뮬레이션 실행
|
|
515
|
+
python3 simulate_standalone.py "데이터를 분석해주세요"
|
|
516
|
+
|
|
517
|
+
# 빠른 실행 (지연 시간 단축)
|
|
518
|
+
python3 simulate_standalone.py "보고서를 작성해주세요" --delay 0.3
|
|
519
|
+
|
|
520
|
+
# 상세 로그와 함께
|
|
521
|
+
python3 simulate_standalone.py "고객 문의를 처리해주세요" --verbose
|
|
522
|
+
|
|
523
|
+
# 도움말 보기
|
|
524
|
+
python3 simulate_standalone.py --help
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
#### 의존성이 있는 시뮬레이터
|
|
528
|
+
|
|
529
|
+
```bash
|
|
530
|
+
# 간단한 시뮬레이션 실행
|
|
531
|
+
python processgpt_simulator_cli.py "데이터를 분석해주세요"
|
|
532
|
+
|
|
533
|
+
# 또는 shell script 사용
|
|
534
|
+
./simulate.sh "보고서를 작성해주세요"
|
|
535
|
+
|
|
536
|
+
# 고급 옵션
|
|
537
|
+
python processgpt_simulator_cli.py "프로젝트를 계획해주세요" --steps 8 --delay 0.5
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
### 🎯 주요 특징
|
|
541
|
+
|
|
542
|
+
- **데이터베이스 불필요**: Supabase 연결 없이 완전한 독립 실행
|
|
543
|
+
- **스마트 프로세스 선택**: 프롬프트 분석으로 자동 프로세스 결정
|
|
544
|
+
- **실시간 이벤트 출력**: JSON 형태로 진행상태를 stdout에 출력
|
|
545
|
+
- **사용자 정의 가능**: 자체 실행기 구현 지원
|
|
546
|
+
- **다양한 시뮬레이션 모드**: 단계별 진행, 지연 시간 조정 등
|
|
547
|
+
|
|
548
|
+
### 🧠 지원하는 프로세스 타입
|
|
549
|
+
|
|
550
|
+
시뮬레이터는 프롬프트를 분석하여 자동으로 적절한 프로세스를 선택합니다:
|
|
551
|
+
|
|
552
|
+
- **데이터 분석**: 데이터 수집 → 정제 → 분석 → 결과 생성 → 시각화
|
|
553
|
+
- **보고서 작성**: 요구사항 분석 → 구조 설계 → 내용 작성 → 검토
|
|
554
|
+
- **고객 서비스**: 문의 분석 → 솔루션 검색 → 응답 준비
|
|
555
|
+
- **프로젝트 관리**: 분석 → 계획 → 리소스 할당 → 위험 평가
|
|
556
|
+
- **일반 작업**: 작업 분석 → 처리 수행 → 결과 생성
|
|
557
|
+
|
|
558
|
+
### 📊 출력 형태
|
|
559
|
+
|
|
560
|
+
시뮬레이터는 각 이벤트를 JSON 형태로 stdout에 출력합니다:
|
|
561
|
+
|
|
562
|
+
```json
|
|
563
|
+
[EVENT] {
|
|
564
|
+
"timestamp": "2024-01-15T10:30:45.123456Z",
|
|
565
|
+
"task_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
566
|
+
"proc_inst_id": "550e8400-e29b-41d4-a716-446655440001",
|
|
567
|
+
"event": {
|
|
568
|
+
"type": "progress",
|
|
569
|
+
"data": {
|
|
570
|
+
"step": 2,
|
|
571
|
+
"total_steps": 5,
|
|
572
|
+
"step_name": "데이터 정제",
|
|
573
|
+
"message": "데이터를 정제하고 전처리하고 있습니다...",
|
|
574
|
+
"progress_percentage": 40.0,
|
|
575
|
+
"process_type": "데이터 분석"
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
#### 이벤트 타입
|
|
582
|
+
|
|
583
|
+
- `task_started`: 작업 시작
|
|
584
|
+
- `progress`: 진행 상황 업데이트
|
|
585
|
+
- `output`: 중간/최종 결과 출력
|
|
586
|
+
- `done`: 작업 완료
|
|
587
|
+
- `cancelled`: 작업 취소
|
|
588
|
+
- `error`: 오류 발생
|
|
589
|
+
|
|
590
|
+
### 📋 CLI 옵션
|
|
591
|
+
|
|
592
|
+
| 옵션 | 설명 | 기본값 |
|
|
593
|
+
|------|------|--------|
|
|
594
|
+
| `prompt` | 에이전트가 처리할 프롬프트 메시지 | (필수) |
|
|
595
|
+
| `--agent-orch` | 에이전트 오케스트레이션 타입 | `simulator` |
|
|
596
|
+
| `--activity-name` | 활동 이름 | `simulation_task` |
|
|
597
|
+
| `--user-id` | 사용자 ID | 자동 생성 |
|
|
598
|
+
| `--tenant-id` | 테넌트 ID | 자동 생성 |
|
|
599
|
+
| `--tool` | 사용할 도구 | `default` |
|
|
600
|
+
| `--feedback` | 피드백 메시지 | (빈 문자열) |
|
|
601
|
+
| `--steps` | 시뮬레이션 단계 수 | `5` (프로세스별 자동 결정) |
|
|
602
|
+
| `--delay` | 각 단계별 대기 시간(초) | `1.0` |
|
|
603
|
+
| `--verbose` | 상세한 로그 출력 | `false` |
|
|
604
|
+
|
|
605
|
+
### 시뮬레이터에서 사용자 정의 실행기 사용
|
|
606
|
+
|
|
607
|
+
```python
|
|
608
|
+
# 시뮬레이터에서 사용자 정의 실행기 사용 예제
|
|
609
|
+
from processgpt_agent_sdk.simulator import ProcessGPTAgentSimulator
|
|
610
|
+
from my_custom_executor import MyBusinessAgentExecutor
|
|
611
|
+
|
|
612
|
+
async def main():
|
|
613
|
+
# 사용자 정의 실행기 생성
|
|
614
|
+
executor = MyBusinessAgentExecutor(config={"timeout": 30})
|
|
615
|
+
|
|
616
|
+
# 시뮬레이터 생성
|
|
617
|
+
simulator = ProcessGPTAgentSimulator(
|
|
618
|
+
executor=executor,
|
|
619
|
+
agent_orch="my_business_agent"
|
|
620
|
+
)
|
|
621
|
+
|
|
622
|
+
# 시뮬레이션 실행
|
|
623
|
+
await simulator.run_simulation(
|
|
624
|
+
prompt="월별 매출 보고서를 작성해주세요",
|
|
625
|
+
activity_name="report_generation",
|
|
626
|
+
user_id="user123",
|
|
627
|
+
tenant_id="tenant456"
|
|
628
|
+
)
|
|
629
|
+
|
|
630
|
+
# 실행
|
|
631
|
+
if __name__ == "__main__":
|
|
632
|
+
asyncio.run(main())
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
### 📁 실제 사용 예제
|
|
636
|
+
|
|
637
|
+
#### 데이터 분석 시뮬레이션
|
|
638
|
+
|
|
639
|
+
```bash
|
|
640
|
+
# 독립적 시뮬레이터 사용
|
|
641
|
+
python3 simulate_standalone.py "월별 매출 데이터를 분석하고 트렌드를 파악해주세요" \
|
|
642
|
+
--agent-orch "data_analyst" \
|
|
643
|
+
--delay 0.5 \
|
|
644
|
+
--verbose
|
|
645
|
+
|
|
646
|
+
# 의존성 있는 시뮬레이터 사용
|
|
647
|
+
python processgpt_simulator_cli.py "고객 행동 패턴을 분석해주세요" \
|
|
648
|
+
--steps 6 \
|
|
649
|
+
--delay 2.0
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
#### 고객 서비스 시뮬레이션
|
|
653
|
+
|
|
654
|
+
```bash
|
|
655
|
+
python3 simulate_standalone.py "제품 반품 문의에 대한 응답을 준비해주세요" \
|
|
656
|
+
--agent-orch "customer_service" \
|
|
657
|
+
--activity-name "return_inquiry" \
|
|
658
|
+
--feedback "고객은 배송 지연을 이유로 반품을 요청했습니다"
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
#### 프로젝트 관리 시뮬레이션
|
|
662
|
+
|
|
663
|
+
```bash
|
|
664
|
+
python3 simulate_standalone.py "신제품 출시를 위한 프로젝트 계획을 수립해주세요" \
|
|
665
|
+
--agent-orch "project_manager" \
|
|
666
|
+
--delay 1.5
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
### 🔍 로그 및 디버깅
|
|
670
|
+
|
|
671
|
+
#### 이벤트 필터링
|
|
672
|
+
|
|
673
|
+
```bash
|
|
674
|
+
# 진행 상황 이벤트만 출력
|
|
675
|
+
python3 simulate_standalone.py "테스트" | grep '\[EVENT\]' | jq '.event | select(.type == "progress")'
|
|
676
|
+
|
|
677
|
+
# 최종 결과만 출력
|
|
678
|
+
python3 simulate_standalone.py "테스트" | grep '\[EVENT\]' | jq '.event | select(.type == "output")'
|
|
679
|
+
|
|
680
|
+
# 특정 프로세스 타입만 필터링
|
|
681
|
+
python3 simulate_standalone.py "데이터 분석" | grep "데이터 분석"
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
#### CI/CD 통합
|
|
685
|
+
|
|
686
|
+
```yaml
|
|
687
|
+
# .github/workflows/test.yml
|
|
688
|
+
name: Agent Simulation Tests
|
|
689
|
+
on: [push, pull_request]
|
|
690
|
+
|
|
691
|
+
jobs:
|
|
692
|
+
test:
|
|
693
|
+
runs-on: ubuntu-latest
|
|
694
|
+
steps:
|
|
695
|
+
- uses: actions/checkout@v2
|
|
696
|
+
- name: Set up Python
|
|
697
|
+
uses: actions/setup-python@v2
|
|
698
|
+
with:
|
|
699
|
+
python-version: '3.9'
|
|
700
|
+
|
|
701
|
+
- name: Run Agent Simulation Tests
|
|
702
|
+
run: |
|
|
703
|
+
python3 simulate_standalone.py "테스트 시나리오 1" --delay 0.1
|
|
704
|
+
python3 simulate_standalone.py "테스트 시나리오 2" --delay 0.1
|
|
705
|
+
python3 simulate_standalone.py "테스트 시나리오 3" --delay 0.1
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
## 🔄 워크플로우
|
|
709
|
+
|
|
710
|
+
### 시퀀스 다이어그램
|
|
711
|
+
|
|
712
|
+
```mermaid
|
|
713
|
+
sequenceDiagram
|
|
714
|
+
participant Client as Client Application
|
|
715
|
+
participant DB as Supabase Database
|
|
716
|
+
participant TodoTable as TodoList Table
|
|
717
|
+
participant EventTable as Events Table
|
|
718
|
+
participant Server as ProcessGPT Agent Server
|
|
719
|
+
participant Executor as Agent Executor
|
|
720
|
+
participant AI as CrewAI/Langgraph/OpenAI
|
|
721
|
+
|
|
722
|
+
Note over Client, AI: ProcessGPT Agent Framework Workflow
|
|
723
|
+
|
|
724
|
+
%% Task Submission
|
|
725
|
+
Client->>DB: Submit new task
|
|
726
|
+
Client->>TodoTable: INSERT INTO todolist<br/>(agent_orch, description, status='IN_PROGRESS')
|
|
727
|
+
TodoTable-->>Client: Return todolist_id
|
|
728
|
+
|
|
729
|
+
%% Server Polling Loop
|
|
730
|
+
loop Every 5 seconds (configurable)
|
|
731
|
+
Server->>TodoTable: SELECT * FROM todolist<br/>WHERE status='IN_PROGRESS'<br/>AND agent_orch='{configured_type}'
|
|
732
|
+
TodoTable-->>Server: Return pending tasks
|
|
733
|
+
|
|
734
|
+
alt Tasks found
|
|
735
|
+
Server->>TodoTable: UPDATE todolist<br/>SET draft_status='STARTED',<br/>consumer='{server_id}'
|
|
736
|
+
|
|
737
|
+
%% Event Logging - Task Started
|
|
738
|
+
Server->>EventTable: INSERT INTO events<br/>(todolist_id, event_type='task_started')
|
|
739
|
+
|
|
740
|
+
%% Create Request Context
|
|
741
|
+
Server->>Server: Create ProcessGPTRequestContext<br/>from todolist data
|
|
742
|
+
|
|
743
|
+
%% Create Event Queue
|
|
744
|
+
Server->>Server: Create ProcessGPTEventQueue<br/>with Supabase connection
|
|
745
|
+
|
|
746
|
+
%% Execute Agent
|
|
747
|
+
Server->>Executor: execute(context, event_queue)
|
|
748
|
+
|
|
749
|
+
%% Agent Processing with AI Frameworks
|
|
750
|
+
Executor->>AI: Use AI frameworks<br/>(CrewAI, Langgraph, OpenAI)<br/>with A2A interfaces
|
|
751
|
+
|
|
752
|
+
loop During Agent Execution
|
|
753
|
+
AI->>Executor: Progress events/status updates
|
|
754
|
+
Executor->>Server: Forward events to ProcessGPTEventQueue
|
|
755
|
+
Server->>EventTable: INSERT INTO events<br/>(todolist_id, event_type, event_data)
|
|
756
|
+
end
|
|
757
|
+
|
|
758
|
+
alt Agent Success
|
|
759
|
+
AI-->>Executor: Task completed successfully
|
|
760
|
+
Executor-->>Server: Task completion
|
|
761
|
+
Server->>EventTable: INSERT INTO events<br/>(event_type='done')
|
|
762
|
+
Server->>TodoTable: UPDATE todolist<br/>SET status='SUBMITTED',<br/>draft_status='COMPLETED'
|
|
763
|
+
else Agent Failure
|
|
764
|
+
AI-->>Executor: Task failed with error
|
|
765
|
+
Executor-->>Server: Task failure
|
|
766
|
+
Server->>EventTable: INSERT INTO events<br/>(event_type='error')
|
|
767
|
+
Server->>TodoTable: UPDATE todolist<br/>SET status='CANCELLED'
|
|
768
|
+
end
|
|
769
|
+
else No tasks
|
|
770
|
+
Note over Server: Wait for next polling cycle
|
|
771
|
+
end
|
|
772
|
+
end
|
|
773
|
+
|
|
774
|
+
%% Client Status Monitoring
|
|
775
|
+
loop Client Monitoring
|
|
776
|
+
Client->>TodoTable: SELECT * FROM todolist<br/>WHERE id='{todolist_id}'
|
|
777
|
+
TodoTable-->>Client: Return task status
|
|
778
|
+
|
|
779
|
+
Client->>EventTable: SELECT * FROM events<br/>WHERE todolist_id='{todolist_id}'<br/>ORDER BY created_at
|
|
780
|
+
EventTable-->>Client: Return event history
|
|
781
|
+
|
|
782
|
+
alt Task Completed
|
|
783
|
+
Note over Client: Process final result
|
|
784
|
+
else Task Still Running
|
|
785
|
+
Note over Client: Continue monitoring
|
|
786
|
+
end
|
|
787
|
+
end
|
|
788
|
+
```
|
|
789
|
+
|
|
790
|
+
### 워크플로우 단계
|
|
791
|
+
|
|
792
|
+
1. **태스크 제출**: 클라이언트가 `todolist` 테이블에 새로운 작업을 INSERT
|
|
793
|
+
2. **폴링**: ProcessGPT Agent Server가 주기적으로 `IN_PROGRESS` 상태의 작업들을 조회
|
|
794
|
+
3. **상태 업데이트**: 발견된 작업의 상태를 `STARTED`로 변경
|
|
795
|
+
4. **컨텍스트 생성**: todolist 데이터를 기반으로 `ProcessGPTRequestContext` 생성
|
|
796
|
+
5. **이벤트 큐 생성**: Supabase 연동 `ProcessGPTEventQueue` 생성
|
|
797
|
+
6. **에이전트 실행**: Google A2A SDK 인터페이스를 통해 AI 프레임워크(CrewAI, Langgraph, OpenAI) 호출
|
|
798
|
+
7. **이벤트 로깅**: 실행 과정의 모든 이벤트가 `events` 테이블에 저장
|
|
799
|
+
8. **완료 처리**: 최종 결과가 `todolist`의 `output` 또는 `draft`에 저장
|
|
800
|
+
|
|
801
|
+
## 🛠️ 커스터마이제이션
|
|
802
|
+
|
|
803
|
+
### CrewAI 통합 예제
|
|
804
|
+
|
|
805
|
+
```python
|
|
806
|
+
from crewai import Agent, Task, Crew
|
|
807
|
+
import asyncio
|
|
808
|
+
|
|
809
|
+
class CrewAIAgentExecutor(AgentExecutor):
|
|
810
|
+
"""CrewAI를 활용한 AgentExecutor"""
|
|
811
|
+
|
|
812
|
+
def __init__(self):
|
|
813
|
+
self.is_cancelled = False
|
|
814
|
+
|
|
815
|
+
# CrewAI 에이전트 설정
|
|
816
|
+
self.researcher = Agent(
|
|
817
|
+
role='Senior Researcher',
|
|
818
|
+
goal='Conduct thorough research and provide accurate information',
|
|
819
|
+
backstory='An experienced researcher with attention to detail',
|
|
820
|
+
verbose=True
|
|
821
|
+
)
|
|
822
|
+
|
|
823
|
+
self.analyst = Agent(
|
|
824
|
+
role='Data Analyst',
|
|
825
|
+
goal='Analyze data and extract meaningful insights',
|
|
826
|
+
backstory='A skilled analyst with expertise in data interpretation',
|
|
827
|
+
verbose=True
|
|
828
|
+
)
|
|
829
|
+
|
|
830
|
+
async def execute(self, context: RequestContext, event_queue: EventQueue) -> None:
|
|
831
|
+
user_input = context.get_user_input()
|
|
832
|
+
|
|
833
|
+
# 시작 이벤트
|
|
834
|
+
start_event = Event(
|
|
835
|
+
type="task_started",
|
|
836
|
+
data={"message": f"CrewAI 에이전트 시작: {user_input}"}
|
|
837
|
+
)
|
|
838
|
+
event_queue.enqueue_event(start_event)
|
|
839
|
+
|
|
840
|
+
try:
|
|
841
|
+
# CrewAI 태스크 생성
|
|
842
|
+
research_task = Task(
|
|
843
|
+
description=f"Research the following topic: {user_input}",
|
|
844
|
+
agent=self.researcher,
|
|
845
|
+
expected_output="Comprehensive research findings"
|
|
846
|
+
)
|
|
847
|
+
|
|
848
|
+
analysis_task = Task(
|
|
849
|
+
description="Analyze the research findings and provide insights",
|
|
850
|
+
agent=self.analyst,
|
|
851
|
+
expected_output="Detailed analysis with actionable insights"
|
|
852
|
+
)
|
|
853
|
+
|
|
854
|
+
# Crew 생성 및 실행
|
|
855
|
+
crew = Crew(
|
|
856
|
+
agents=[self.researcher, self.analyst],
|
|
857
|
+
tasks=[research_task, analysis_task],
|
|
858
|
+
verbose=True
|
|
859
|
+
)
|
|
860
|
+
|
|
861
|
+
# 진행 상황 이벤트
|
|
862
|
+
progress_event = Event(
|
|
863
|
+
type="progress",
|
|
864
|
+
data={"message": "CrewAI 에이전트들이 작업을 수행하고 있습니다..."}
|
|
865
|
+
)
|
|
866
|
+
event_queue.enqueue_event(progress_event)
|
|
867
|
+
|
|
868
|
+
# 비동기 실행
|
|
869
|
+
result = await asyncio.to_thread(crew.kickoff)
|
|
870
|
+
|
|
871
|
+
# 결과 이벤트
|
|
872
|
+
output_event = Event(
|
|
873
|
+
type="output",
|
|
874
|
+
data={
|
|
875
|
+
"content": {
|
|
876
|
+
"crew_result": str(result),
|
|
877
|
+
"agents_used": ["Senior Researcher", "Data Analyst"]
|
|
878
|
+
},
|
|
879
|
+
"final": True
|
|
880
|
+
}
|
|
881
|
+
)
|
|
882
|
+
event_queue.enqueue_event(output_event)
|
|
883
|
+
|
|
884
|
+
# 완료 이벤트
|
|
885
|
+
done_event = Event(
|
|
886
|
+
type="done",
|
|
887
|
+
data={"message": "CrewAI 작업 완료", "success": True}
|
|
888
|
+
)
|
|
889
|
+
event_queue.enqueue_event(done_event)
|
|
890
|
+
|
|
891
|
+
except Exception as e:
|
|
892
|
+
error_event = Event(
|
|
893
|
+
type="error",
|
|
894
|
+
data={"message": f"CrewAI 실행 오류: {str(e)}"}
|
|
895
|
+
)
|
|
896
|
+
event_queue.enqueue_event(error_event)
|
|
897
|
+
raise
|
|
898
|
+
|
|
899
|
+
async def cancel(self, context: RequestContext, event_queue: EventQueue) -> None:
|
|
900
|
+
self.is_cancelled = True
|
|
901
|
+
# CrewAI 취소 로직 구현
|
|
902
|
+
```
|
|
903
|
+
|
|
904
|
+
## 📊 모니터링
|
|
905
|
+
|
|
906
|
+
시스템 상태를 모니터링하기 위한 유틸리티:
|
|
907
|
+
|
|
908
|
+
```python
|
|
909
|
+
from processgpt_utils import ProcessGPTMonitor
|
|
910
|
+
|
|
911
|
+
monitor = ProcessGPTMonitor(supabase)
|
|
912
|
+
|
|
913
|
+
# 시스템 통계 조회
|
|
914
|
+
stats = await monitor.get_system_stats()
|
|
915
|
+
print(f"Total tasks: {stats['total_tasks']}")
|
|
916
|
+
print(f"Pending: {stats['pending_tasks']}")
|
|
917
|
+
print(f"Completed: {stats['completed_tasks']}")
|
|
918
|
+
|
|
919
|
+
# 최근 이벤트 조회
|
|
920
|
+
recent_events = await monitor.get_recent_events(limit=10)
|
|
921
|
+
```
|
|
922
|
+
|
|
923
|
+
## 🔧 설정 옵션
|
|
924
|
+
|
|
925
|
+
### 환경변수
|
|
926
|
+
|
|
927
|
+
```bash
|
|
928
|
+
# Supabase 설정
|
|
929
|
+
SUPABASE_URL=https://your-project.supabase.co
|
|
930
|
+
SUPABASE_ANON_KEY=your-anon-key-here
|
|
931
|
+
|
|
932
|
+
# 에이전트 설정
|
|
933
|
+
DEFAULT_AGENT_TYPE=my_business_agent
|
|
934
|
+
DEFAULT_POLLING_INTERVAL=5
|
|
935
|
+
|
|
936
|
+
# 로깅
|
|
937
|
+
LOG_LEVEL=INFO
|
|
938
|
+
```
|
|
939
|
+
|
|
940
|
+
### 서버 옵션
|
|
941
|
+
|
|
942
|
+
```bash
|
|
943
|
+
# 폴링 간격 설정 (초)
|
|
944
|
+
python server.py --polling-interval 10
|
|
945
|
+
|
|
946
|
+
# 특정 에이전트 타입만 처리
|
|
947
|
+
python server.py --agent-type my-custom-agent
|
|
948
|
+
```
|
|
949
|
+
|
|
950
|
+
## 🐛 트러블슈팅
|
|
951
|
+
|
|
952
|
+
### 시뮬레이터 관련
|
|
953
|
+
|
|
954
|
+
1. **Import 오류**
|
|
955
|
+
- Python 경로가 올바르게 설정되었는지 확인
|
|
956
|
+
- 필요한 의존성이 설치되었는지 확인: `pip install -r requirements.txt`
|
|
957
|
+
|
|
958
|
+
2. **Permission 오류**
|
|
959
|
+
- 스크립트 실행 권한 부여: `chmod +x simulate_standalone.py`
|
|
960
|
+
- 헬퍼 스크립트 권한 부여: `chmod +x simulate.sh`
|
|
961
|
+
|
|
962
|
+
3. **시뮬레이션이 느리게 실행됨**
|
|
963
|
+
- `--delay` 옵션으로 단계별 지연 시간 단축: `--delay 0.1`
|
|
964
|
+
- `--steps` 옵션으로 단계 수 줄이기: `--steps 3`
|
|
965
|
+
|
|
966
|
+
### 실제 서버 관련
|
|
967
|
+
|
|
968
|
+
1. **Supabase 연결 실패**
|
|
969
|
+
- 환경변수 `SUPABASE_URL`과 `SUPABASE_ANON_KEY` 확인
|
|
970
|
+
- 네트워크 연결 상태 확인
|
|
971
|
+
- Supabase 프로젝트가 활성화되어 있는지 확인
|
|
972
|
+
|
|
973
|
+
2. **폴링이 작동하지 않음**
|
|
974
|
+
- 데이터베이스 테이블이 올바르게 생성되었는지 확인
|
|
975
|
+
- `agent_orch`이 정확히 매칭되는지 확인
|
|
976
|
+
- 폴링 간격 설정 확인
|
|
977
|
+
|
|
978
|
+
3. **이벤트가 저장되지 않음**
|
|
979
|
+
- Supabase RLS (Row Level Security) 정책 확인
|
|
980
|
+
- 테이블 권한 설정 확인
|
|
981
|
+
- API 키 권한 확인
|
|
982
|
+
|
|
983
|
+
### 로그 확인
|
|
984
|
+
|
|
985
|
+
```bash
|
|
986
|
+
# 시뮬레이터 디버그 모드
|
|
987
|
+
python3 simulate_standalone.py "테스트" --verbose
|
|
988
|
+
|
|
989
|
+
# 실제 서버 디버그 모드
|
|
990
|
+
LOG_LEVEL=DEBUG python server.py
|
|
991
|
+
|
|
992
|
+
# 로그 간격 조정
|
|
993
|
+
LOG_SPACED=0 python3 simulate_standalone.py "테스트"
|
|
994
|
+
```
|
|
995
|
+
|
|
996
|
+
### 성능 최적화
|
|
997
|
+
|
|
998
|
+
```bash
|
|
999
|
+
# 빠른 테스트를 위한 설정
|
|
1000
|
+
python3 simulate_standalone.py "테스트" --delay 0.1 --steps 2
|
|
1001
|
+
|
|
1002
|
+
# 배치 테스트
|
|
1003
|
+
for prompt in "분석" "보고서" "고객서비스"; do
|
|
1004
|
+
python3 simulate_standalone.py "$prompt 작업" --delay 0.1
|
|
1005
|
+
done
|
|
1006
|
+
```
|
|
1007
|
+
|
|
1008
|
+
## 🤝 기여
|
|
1009
|
+
|
|
1010
|
+
1. Fork the repository
|
|
1011
|
+
2. Create a feature branch
|
|
1012
|
+
3. Commit your changes
|
|
1013
|
+
4. Push to the branch
|
|
1014
|
+
5. Create a Pull Request
|
|
1015
|
+
|
|
1016
|
+
## 📄 라이선스
|
|
1017
|
+
|
|
1018
|
+
MIT License - 자세한 내용은 LICENSE 파일을 참조하세요.
|
|
1019
|
+
|
|
1020
|
+
## 🔗 관련 링크
|
|
1021
|
+
|
|
1022
|
+
- [Google A2A SDK Documentation](https://developers.google.com/a2a)
|
|
1023
|
+
- [Supabase Documentation](https://supabase.com/docs)
|
|
1024
|
+
- [CrewAI Documentation](https://docs.crewai.com/)
|
|
1025
|
+
- [LangGraph Documentation](https://langchain-ai.github.io/langgraph/)
|
|
1026
|
+
- [ProcessGPT Framework Issues](https://github.com/your-repo/issues)
|