ff-taskforce 0.1.0__tar.gz
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.
- ff_taskforce-0.1.0/.env.example +4 -0
- ff_taskforce-0.1.0/.gitignore +8 -0
- ff_taskforce-0.1.0/Architecture.md +285 -0
- ff_taskforce-0.1.0/CLAUDE.md +15 -0
- ff_taskforce-0.1.0/LICENSE +21 -0
- ff_taskforce-0.1.0/PKG-INFO +136 -0
- ff_taskforce-0.1.0/README.md +111 -0
- ff_taskforce-0.1.0/pyproject.toml +37 -0
- ff_taskforce-0.1.0/src/taskforce/__init__.py +3 -0
- ff_taskforce-0.1.0/src/taskforce/for-agent-layerinfo.md +16 -0
- ff_taskforce-0.1.0/src/taskforce/l1/__init__.py +3 -0
- ff_taskforce-0.1.0/src/taskforce/l1/for-agent-layerinfo-l1.md +8 -0
- ff_taskforce-0.1.0/src/taskforce/l1/schema/__init__.py +3 -0
- ff_taskforce-0.1.0/src/taskforce/l1/schema/for-agent-moduleinfo.md +47 -0
- ff_taskforce-0.1.0/src/taskforce/l1/schema/schema.py +35 -0
- ff_taskforce-0.1.0/src/taskforce/l2/__init__.py +6 -0
- ff_taskforce-0.1.0/src/taskforce/l2/config/__init__.py +3 -0
- ff_taskforce-0.1.0/src/taskforce/l2/config/config.py +65 -0
- ff_taskforce-0.1.0/src/taskforce/l2/config/for-agent-moduleinfo.md +24 -0
- ff_taskforce-0.1.0/src/taskforce/l2/cost_logger/__init__.py +3 -0
- ff_taskforce-0.1.0/src/taskforce/l2/cost_logger/cost_logger.py +48 -0
- ff_taskforce-0.1.0/src/taskforce/l2/cost_logger/for-agent-moduleinfo.md +21 -0
- ff_taskforce-0.1.0/src/taskforce/l2/for-agent-layerinfo-l2.md +17 -0
- ff_taskforce-0.1.0/src/taskforce/l2/panelist/__init__.py +3 -0
- ff_taskforce-0.1.0/src/taskforce/l2/panelist/for-agent-moduleinfo.md +23 -0
- ff_taskforce-0.1.0/src/taskforce/l2/panelist/panelist.py +52 -0
- ff_taskforce-0.1.0/src/taskforce/l2/session_logger/__init__.py +3 -0
- ff_taskforce-0.1.0/src/taskforce/l2/session_logger/for-agent-moduleinfo.md +22 -0
- ff_taskforce-0.1.0/src/taskforce/l2/session_logger/session_logger.py +48 -0
- ff_taskforce-0.1.0/src/taskforce/l3/__init__.py +3 -0
- ff_taskforce-0.1.0/src/taskforce/l3/for-agent-layerinfo-l3.md +7 -0
- ff_taskforce-0.1.0/src/taskforce/l3/roundtable/__init__.py +3 -0
- ff_taskforce-0.1.0/src/taskforce/l3/roundtable/for-agent-moduleinfo.md +30 -0
- ff_taskforce-0.1.0/src/taskforce/l3/roundtable/roundtable.py +102 -0
- ff_taskforce-0.1.0/src/taskforce/l4/__init__.py +3 -0
- ff_taskforce-0.1.0/src/taskforce/l4/for-agent-layerinfo-l4.md +6 -0
- ff_taskforce-0.1.0/src/taskforce/l4/taskforce_facade/__init__.py +3 -0
- ff_taskforce-0.1.0/src/taskforce/l4/taskforce_facade/for-agent-moduleinfo.md +25 -0
- ff_taskforce-0.1.0/src/taskforce/l4/taskforce_facade/taskforce_facade.py +40 -0
- ff_taskforce-0.1.0/src/taskforce/mcp_wrapper/__init__.py +3 -0
- ff_taskforce-0.1.0/src/taskforce/mcp_wrapper/__main__.py +3 -0
- ff_taskforce-0.1.0/src/taskforce/mcp_wrapper/mcp_wrapper.py +48 -0
- ff_taskforce-0.1.0/start-claude.bat +13 -0
- ff_taskforce-0.1.0/start-claude.ps1 +117 -0
- ff_taskforce-0.1.0/tests/__init__.py +0 -0
- ff_taskforce-0.1.0/tests/l1/__init__.py +0 -0
- ff_taskforce-0.1.0/tests/l1/schema/__init__.py +0 -0
- ff_taskforce-0.1.0/tests/l1/schema/test_schema.py +43 -0
- ff_taskforce-0.1.0/tests/l2/__init__.py +0 -0
- ff_taskforce-0.1.0/tests/l2/config/__init__.py +0 -0
- ff_taskforce-0.1.0/tests/l2/config/test_config.py +47 -0
- ff_taskforce-0.1.0/tests/l2/cost_logger/__init__.py +0 -0
- ff_taskforce-0.1.0/tests/l2/cost_logger/test_cost_logger.py +32 -0
- ff_taskforce-0.1.0/tests/l2/panelist/__init__.py +0 -0
- ff_taskforce-0.1.0/tests/l2/panelist/test_panelist.py +59 -0
- ff_taskforce-0.1.0/tests/l2/session_logger/__init__.py +0 -0
- ff_taskforce-0.1.0/tests/l2/session_logger/test_session_logger.py +36 -0
- ff_taskforce-0.1.0/tests/l3/__init__.py +0 -0
- ff_taskforce-0.1.0/tests/l3/roundtable/__init__.py +0 -0
- ff_taskforce-0.1.0/tests/l3/roundtable/test_roundtable.py +111 -0
- ff_taskforce-0.1.0/tests/l4/__init__.py +0 -0
- ff_taskforce-0.1.0/tests/l4/taskforce_facade/__init__.py +0 -0
- ff_taskforce-0.1.0/tests/l4/taskforce_facade/test_taskforce_facade.py +54 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
# Taskforce - Architecture
|
|
2
|
+
|
|
3
|
+
다수의 LLM 패널에 의제를 질의하고 구조화된 아이디어 풀을
|
|
4
|
+
반환하는 Python 패키지.
|
|
5
|
+
|
|
6
|
+
서로 다른 방식으로 발달한 모델들의 관점 다양성을 활용하여
|
|
7
|
+
robust한 아이디어 풀을 구축하는 것이 목적.
|
|
8
|
+
프로그래머틱하게 import하여 작업흐름에 통합하는 용도.
|
|
9
|
+
|
|
10
|
+
## 시스템 개요
|
|
11
|
+
|
|
12
|
+
```mermaid
|
|
13
|
+
graph LR
|
|
14
|
+
CALLER[호출자]
|
|
15
|
+
RT[Roundtable]
|
|
16
|
+
PANEL[Panelist Pool]
|
|
17
|
+
SUM[Summarizer]
|
|
18
|
+
|
|
19
|
+
GPT[GPT 5.4]
|
|
20
|
+
GROK[Grok 4-1]
|
|
21
|
+
CLAUDE[Claude opus-4]
|
|
22
|
+
GEMINI[Gemini 2.5 Pro]
|
|
23
|
+
|
|
24
|
+
CALLER -->|roundtable.discuss(agenda)| RT
|
|
25
|
+
RT -->|병렬 질의| PANEL
|
|
26
|
+
PANEL --> GPT
|
|
27
|
+
PANEL --> GROK
|
|
28
|
+
PANEL --> CLAUDE
|
|
29
|
+
PANEL --> GEMINI
|
|
30
|
+
PANEL -->|raw opinions| RT
|
|
31
|
+
RT -->|분류 취합 요청| SUM
|
|
32
|
+
SUM -->|IdeaPool| RT
|
|
33
|
+
RT -->|IdeaPool| CALLER
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Ln 구조
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
src/taskforce/
|
|
40
|
+
for-agent-layerinfo.md
|
|
41
|
+
__init__.py # Taskforce 노출
|
|
42
|
+
|
|
43
|
+
l1/
|
|
44
|
+
for-agent-layerinfo-l1.md
|
|
45
|
+
schema/
|
|
46
|
+
schema.py # ModelEntry, Opinion, IdeaPool (pydantic)
|
|
47
|
+
for-agent-moduleinfo.md
|
|
48
|
+
__init__.py
|
|
49
|
+
|
|
50
|
+
l2/
|
|
51
|
+
for-agent-layerinfo-l2.md
|
|
52
|
+
config/
|
|
53
|
+
config.py # EnvConfig: .env 로드, 모델 레지스트리
|
|
54
|
+
for-agent-moduleinfo.md
|
|
55
|
+
__init__.py
|
|
56
|
+
panelist/
|
|
57
|
+
panelist.py # LiteLLM 래퍼, 개별 모델 호출
|
|
58
|
+
for-agent-moduleinfo.md
|
|
59
|
+
__init__.py
|
|
60
|
+
session_logger/
|
|
61
|
+
session_logger.py # 세션 전문 로그 (~/.taskforce/logs/)
|
|
62
|
+
for-agent-moduleinfo.md
|
|
63
|
+
__init__.py
|
|
64
|
+
cost_logger/
|
|
65
|
+
cost_logger.py # 비용 요약 로그 (~/.taskforce/cost_logs/)
|
|
66
|
+
for-agent-moduleinfo.md
|
|
67
|
+
__init__.py
|
|
68
|
+
|
|
69
|
+
l3/
|
|
70
|
+
for-agent-layerinfo-l3.md
|
|
71
|
+
roundtable/
|
|
72
|
+
roundtable.py # 병렬 질의 + summarizer 분류 취합
|
|
73
|
+
for-agent-moduleinfo.md
|
|
74
|
+
__init__.py
|
|
75
|
+
|
|
76
|
+
l4/
|
|
77
|
+
for-agent-layerinfo-l4.md
|
|
78
|
+
taskforce_facade/
|
|
79
|
+
taskforce_facade.py # 최상위 퍼사드
|
|
80
|
+
for-agent-moduleinfo.md
|
|
81
|
+
__init__.py
|
|
82
|
+
|
|
83
|
+
mcp_wrapper/
|
|
84
|
+
mcp_wrapper.py # optional MCP 서버 래퍼
|
|
85
|
+
__init__.py
|
|
86
|
+
__main__.py
|
|
87
|
+
|
|
88
|
+
tests/
|
|
89
|
+
l1/schema/test_schema.py
|
|
90
|
+
l2/config/test_config.py
|
|
91
|
+
l2/panelist/test_panelist.py
|
|
92
|
+
l2/session_logger/test_session_logger.py
|
|
93
|
+
l2/cost_logger/test_cost_logger.py
|
|
94
|
+
l3/roundtable/test_roundtable.py
|
|
95
|
+
l4/taskforce_facade/test_taskforce_facade.py
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 의존성 흐름
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
l1 (schema) -- pydantic (외부)
|
|
102
|
+
l2 (config) -- dotenv (외부) + l1
|
|
103
|
+
l2 (panelist) -- litellm (외부) + l1
|
|
104
|
+
l2 (session_logger) -- l1
|
|
105
|
+
l2 (cost_logger) -- l1
|
|
106
|
+
l3 (roundtable) -- l2 (panelist) + l1
|
|
107
|
+
l4 (taskforce) -- l2 (config, session_logger, cost_logger) + l3 (roundtable)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## 클래스 다이어그램
|
|
111
|
+
|
|
112
|
+
```mermaid
|
|
113
|
+
classDiagram
|
|
114
|
+
direction TB
|
|
115
|
+
|
|
116
|
+
class EnvConfig {
|
|
117
|
+
+panel_models: list~ModelEntry~
|
|
118
|
+
+summarizer_model: ModelEntry
|
|
119
|
+
+caller_provider: str
|
|
120
|
+
+load_from_env(dotenv_path, caller_provider) EnvConfig
|
|
121
|
+
+get_active_panels() list~ModelEntry~
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
class ModelEntry {
|
|
125
|
+
+provider: str
|
|
126
|
+
+model_id: str
|
|
127
|
+
+api_key: str
|
|
128
|
+
+display_name: str
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
class Opinion {
|
|
132
|
+
+model_name: str
|
|
133
|
+
+content: str
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
class DivergentPoint {
|
|
137
|
+
+topic: str
|
|
138
|
+
+positions: dict~str, str~
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
class UniquePoint {
|
|
142
|
+
+point: str
|
|
143
|
+
+source_model: str
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
class IdeaPool {
|
|
147
|
+
+agenda: str
|
|
148
|
+
+common: list~str~
|
|
149
|
+
+divergent: list~DivergentPoint~
|
|
150
|
+
+unique: list~UniquePoint~
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
class Panelist {
|
|
154
|
+
+model_entry: ModelEntry
|
|
155
|
+
+ask_async(prompt, system_msg) Opinion
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
class Roundtable {
|
|
159
|
+
+panelists: list~Panelist~
|
|
160
|
+
+summarizer: Panelist
|
|
161
|
+
+gather(agenda, context) list~Opinion~
|
|
162
|
+
+summarize(agenda, opinions) IdeaPool
|
|
163
|
+
+discuss(agenda, context) IdeaPool
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
class Taskforce {
|
|
167
|
+
+config: EnvConfig
|
|
168
|
+
+roundtable: Roundtable
|
|
169
|
+
+init(caller_provider, dotenv_path) void
|
|
170
|
+
+discuss(agenda, context) IdeaPool
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
EnvConfig "1" --> "*" ModelEntry
|
|
174
|
+
IdeaPool "1" --> "*" DivergentPoint
|
|
175
|
+
IdeaPool "1" --> "*" UniquePoint
|
|
176
|
+
Panelist "1" --> "1" ModelEntry
|
|
177
|
+
Roundtable "1" --> "*" Panelist : panel
|
|
178
|
+
Roundtable "1" --> "1" Panelist : summarizer
|
|
179
|
+
Roundtable ..> IdeaPool : produces
|
|
180
|
+
Taskforce "1" --> "1" EnvConfig
|
|
181
|
+
Taskforce "1" --> "1" Roundtable
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## 프로세스 시퀀스
|
|
185
|
+
|
|
186
|
+
```mermaid
|
|
187
|
+
sequenceDiagram
|
|
188
|
+
participant C as 호출자
|
|
189
|
+
participant TF as Taskforce
|
|
190
|
+
participant RT as Roundtable
|
|
191
|
+
participant P1 as GPT 5.4
|
|
192
|
+
participant P2 as Grok 4-1
|
|
193
|
+
participant P3 as Claude opus-4
|
|
194
|
+
participant P4 as Gemini 2.5 Pro
|
|
195
|
+
participant SM as Summarizer
|
|
196
|
+
|
|
197
|
+
C->>TF: discuss(agenda, context)
|
|
198
|
+
TF->>RT: gather + summarize
|
|
199
|
+
|
|
200
|
+
Note over RT: 1단계: 패널 질의
|
|
201
|
+
par 병렬 호출
|
|
202
|
+
RT->>P1: 의제 + 컨텍스트
|
|
203
|
+
RT->>P2: 의제 + 컨텍스트
|
|
204
|
+
RT->>P3: 의제 + 컨텍스트
|
|
205
|
+
RT->>P4: 의제 + 컨텍스트
|
|
206
|
+
end
|
|
207
|
+
P1-->>RT: Opinion
|
|
208
|
+
P2-->>RT: Opinion
|
|
209
|
+
P3-->>RT: Opinion
|
|
210
|
+
P4-->>RT: Opinion
|
|
211
|
+
|
|
212
|
+
Note over RT: 2단계: 분류 취합
|
|
213
|
+
RT->>SM: opinions 전체 + 분류 지시
|
|
214
|
+
SM-->>RT: IdeaPool (common/divergent/unique)
|
|
215
|
+
|
|
216
|
+
RT-->>TF: IdeaPool
|
|
217
|
+
TF-->>C: IdeaPool
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## IdeaPool 출력 구조
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
IdeaPool
|
|
224
|
+
+-- agenda: 원본 의제
|
|
225
|
+
+-- common[]: 다수 모델이 동의하는 포인트
|
|
226
|
+
+-- divergent[]: 모델 간 입장이 다른 지점
|
|
227
|
+
| +-- topic: 쟁점
|
|
228
|
+
| +-- positions: {model_name: 해당 입장}
|
|
229
|
+
+-- unique[]: 한 모델만 제시한 고유 관점
|
|
230
|
+
+-- point
|
|
231
|
+
+-- source_model
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## 핵심 설계 결정
|
|
235
|
+
|
|
236
|
+
### 1. 2단계 파이프라인
|
|
237
|
+
- 1단계: 고성능 패널 모델들에 병렬 질의 (관점 수집)
|
|
238
|
+
- 2단계: 경량 모델이 raw opinions를 분류 취합 (토큰 압축)
|
|
239
|
+
- 메인 에이전트에는 구조화된 IdeaPool만 전달
|
|
240
|
+
|
|
241
|
+
### 2. Summarizer 모델
|
|
242
|
+
- 분류 취합은 grok-4-1-fast-non-reasoning 사용
|
|
243
|
+
- XAI_API_KEY를 패널(grok-4-1)과 공유
|
|
244
|
+
- EnvConfig에서 summarizer_model로 별도 관리
|
|
245
|
+
|
|
246
|
+
### 3. Python 패키지 (코어) + MCP wrapper (optional)
|
|
247
|
+
- 코어: import하여 프로그래머틱하게 호출
|
|
248
|
+
- MCP wrapper: Taskforce를 FastMCP 도구로 노출하는 thin wrapper
|
|
249
|
+
- `python -m taskforce.mcp_wrapper` 로 MCP 서버 실행 가능
|
|
250
|
+
- 입출력은 pydantic 모델 (JSON 직렬화 가능)
|
|
251
|
+
|
|
252
|
+
### 4. 비동기 병렬 호출
|
|
253
|
+
- 패널 질의는 `asyncio.gather()`로 병렬 실행
|
|
254
|
+
- 개별 모델 타임아웃/실패 시 해당 모델만 제외
|
|
255
|
+
|
|
256
|
+
### 5. 모델 레지스트리
|
|
257
|
+
|
|
258
|
+
**패널 (고성능)**
|
|
259
|
+
|
|
260
|
+
| 환경변수 | 프로바이더 | 모델 |
|
|
261
|
+
|----------|-----------|------|
|
|
262
|
+
| OPENAI_API_KEY | openai | gpt-5.4 |
|
|
263
|
+
| XAI_API_KEY | xai | grok-4-1 |
|
|
264
|
+
| ANTHROPIC_API_KEY | anthropic | claude-opus-4 |
|
|
265
|
+
| GEMINI_API_KEY | gemini | gemini-2.5-pro |
|
|
266
|
+
|
|
267
|
+
**Summarizer**
|
|
268
|
+
|
|
269
|
+
| 프로바이더 | 모델 | 비고 |
|
|
270
|
+
|-----------|------|------|
|
|
271
|
+
| xai | grok-4-1-fast-non-reasoning | XAI_API_KEY 공유 |
|
|
272
|
+
|
|
273
|
+
### 6. caller_provider 기반 패널 제외
|
|
274
|
+
- 초기화 시 `caller_provider`를 받아 해당 프로바이더의 모델을 패널에서 제외
|
|
275
|
+
- 메인 에이전트와 동일 모델에 질의하는 것은 관점 다양성에 기여하지 않음
|
|
276
|
+
- 예: caller_provider="anthropic" -> claude-opus-4 패널에서 제외
|
|
277
|
+
- 키가 설정되어 있고 caller_provider와 다른 모델만 패널에 등록
|
|
278
|
+
|
|
279
|
+
## 의존성
|
|
280
|
+
|
|
281
|
+
- `litellm` : 멀티 프로바이더 LLM 호출 통합
|
|
282
|
+
- `python-dotenv` : .env 파일 로드
|
|
283
|
+
- `pydantic` : 스키마 검증 + JSON 직렬화
|
|
284
|
+
- `asyncio` : 병렬 호출 (표준 라이브러리)
|
|
285
|
+
- `mcp` : MCP 서버 프레임워크 (optional, MCP wrapper용)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# 프로젝트 프로토콜
|
|
2
|
+
|
|
3
|
+
## 구조 및 코딩 규칙
|
|
4
|
+
|
|
5
|
+
- Ln 구조: `@ff_coding_agent_protocol_md/for-agent-codingprotocol-ln-structure.md` 참조
|
|
6
|
+
- Python 코딩: `@ff_coding_agent_protocol_md/for-agent-codingprotocol-python.md` 참조
|
|
7
|
+
- 연구 프로토콜: `@ff_coding_agent_protocol_md/for-agent-research.md` 참조
|
|
8
|
+
|
|
9
|
+
## 프로젝트 설명
|
|
10
|
+
|
|
11
|
+
[프로젝트 목적과 개요를 여기에 작성]
|
|
12
|
+
|
|
13
|
+
## 추가 규칙
|
|
14
|
+
|
|
15
|
+
[프로젝트 특수 규칙이 있다면 여기에 작성]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 taskforce contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ff-taskforce
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Multi-LLM roundtable for diverse perspective gathering
|
|
5
|
+
Project-URL: Repository, https://github.com/gatesplan/taskforce
|
|
6
|
+
Project-URL: Issues, https://github.com/gatesplan/taskforce/issues
|
|
7
|
+
License: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Keywords: agent,llm,mcp,multi-model,roundtable
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Requires-Dist: litellm
|
|
19
|
+
Requires-Dist: loguru
|
|
20
|
+
Requires-Dist: pydantic>=2.0
|
|
21
|
+
Requires-Dist: python-dotenv
|
|
22
|
+
Provides-Extra: mcp
|
|
23
|
+
Requires-Dist: mcp; extra == 'mcp'
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# taskforce
|
|
27
|
+
|
|
28
|
+
AI agent-oriented multi-LLM roundtable library.
|
|
29
|
+
|
|
30
|
+
Multiple top-tier LLMs (GPT, Grok, Claude, Gemini) are queried in parallel with the same agenda, and the collected opinions are classified into **common / divergent / unique** perspectives, returned as a structured `IdeaPool`.
|
|
31
|
+
|
|
32
|
+
**This package is designed for AI agents, not for direct human use.**
|
|
33
|
+
The primary interface is the MCP wrapper (`roundtable_discuss` tool), which allows agents to invoke a roundtable discussion as a tool call. A Python API is also available for programmatic integration.
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
### 1. Install
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install taskforce
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
For MCP server support:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pip install taskforce[mcp]
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 2. Set environment variables
|
|
50
|
+
|
|
51
|
+
At least two provider API keys are required (one will be excluded as the caller).
|
|
52
|
+
`XAI_API_KEY` is always required (used by the summarizer).
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
OPENAI_API_KEY=sk-...
|
|
56
|
+
XAI_API_KEY=xai-...
|
|
57
|
+
ANTHROPIC_API_KEY=sk-ant-...
|
|
58
|
+
GEMINI_API_KEY=AI...
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 3. Use as MCP tool (recommended for agents)
|
|
62
|
+
|
|
63
|
+
Add to your MCP server config:
|
|
64
|
+
|
|
65
|
+
`TASKFORCE_CALLER_PROVIDER` is the provider of the agent that will call this tool.
|
|
66
|
+
The matching provider's model is excluded from the panel -- querying the same model that is already reasoning adds no diversity.
|
|
67
|
+
For example, if Claude Code is the caller, set it to `"anthropic"` so Claude is excluded from the panel.
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"mcpServers": {
|
|
72
|
+
"taskforce": {
|
|
73
|
+
"command": "python",
|
|
74
|
+
"args": ["-m", "taskforce.mcp_wrapper"],
|
|
75
|
+
"env": {
|
|
76
|
+
"TASKFORCE_CALLER_PROVIDER": "anthropic"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The agent can then call the `roundtable_discuss` tool with `agenda` and `context` parameters.
|
|
84
|
+
|
|
85
|
+
### 4. Use as Python library
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
from taskforce import Taskforce
|
|
89
|
+
|
|
90
|
+
tf = Taskforce(caller_provider="anthropic")
|
|
91
|
+
pool = tf.discuss(
|
|
92
|
+
agenda="Evaluate the trade-offs of approach A vs B",
|
|
93
|
+
context="<detailed context here>"
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# pool.common -- list[str]: points most models agree on
|
|
97
|
+
# pool.divergent -- list[DivergentPoint]: topics with differing positions
|
|
98
|
+
# pool.unique -- list[UniquePoint]: points raised by only one model
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Important Notes
|
|
102
|
+
|
|
103
|
+
- **Paid API calls.** Every `discuss()` invocation calls multiple LLM APIs in parallel. Agents should confirm with the user before calling.
|
|
104
|
+
- **caller_provider exclusion.** The model from the same provider as the calling agent is excluded from the panel to maximize perspective diversity.
|
|
105
|
+
- **XAI_API_KEY is mandatory.** The summarizer (grok-4-1-fast-non-reasoning) always uses the XAI key.
|
|
106
|
+
- **Rich context matters.** Input tokens are cheap. Provide as much context as possible -- specifications, constraints, background, decisions already made -- so the panel can give concrete, actionable opinions instead of generic advice.
|
|
107
|
+
|
|
108
|
+
## API
|
|
109
|
+
|
|
110
|
+
### `Taskforce(caller_provider, dotenv_path=None)`
|
|
111
|
+
|
|
112
|
+
- `caller_provider` (`str`): The LLM provider of the calling agent (e.g. `"anthropic"`, `"openai"`). That provider's model is excluded from the panel.
|
|
113
|
+
- `dotenv_path` (`str | None`): Path to `.env` file. Defaults to auto-discovery.
|
|
114
|
+
|
|
115
|
+
### `Taskforce.discuss(agenda, context="") -> IdeaPool`
|
|
116
|
+
|
|
117
|
+
Synchronous wrapper. Queries the panel, summarizes, and returns an `IdeaPool`.
|
|
118
|
+
|
|
119
|
+
### `Taskforce.discuss_async(agenda, context="") -> IdeaPool`
|
|
120
|
+
|
|
121
|
+
Async version for use in async contexts.
|
|
122
|
+
|
|
123
|
+
### `IdeaPool`
|
|
124
|
+
|
|
125
|
+
| Field | Type | Description |
|
|
126
|
+
|-------|------|-------------|
|
|
127
|
+
| `agenda` | `str` | The original agenda |
|
|
128
|
+
| `common` | `list[str]` | Points most models agree on |
|
|
129
|
+
| `divergent` | `list[DivergentPoint]` | Topics with differing positions (`topic`, `positions: dict[model, position]`) |
|
|
130
|
+
| `unique` | `list[UniquePoint]` | Points from a single model (`point`, `source_model`) |
|
|
131
|
+
| `total_cost` | `float` | Total API cost (USD) |
|
|
132
|
+
| `total_tokens` | `int` | Total tokens consumed |
|
|
133
|
+
|
|
134
|
+
## License
|
|
135
|
+
|
|
136
|
+
MIT
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# taskforce
|
|
2
|
+
|
|
3
|
+
AI agent-oriented multi-LLM roundtable library.
|
|
4
|
+
|
|
5
|
+
Multiple top-tier LLMs (GPT, Grok, Claude, Gemini) are queried in parallel with the same agenda, and the collected opinions are classified into **common / divergent / unique** perspectives, returned as a structured `IdeaPool`.
|
|
6
|
+
|
|
7
|
+
**This package is designed for AI agents, not for direct human use.**
|
|
8
|
+
The primary interface is the MCP wrapper (`roundtable_discuss` tool), which allows agents to invoke a roundtable discussion as a tool call. A Python API is also available for programmatic integration.
|
|
9
|
+
|
|
10
|
+
## Quick Start
|
|
11
|
+
|
|
12
|
+
### 1. Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pip install taskforce
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
For MCP server support:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install taskforce[mcp]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### 2. Set environment variables
|
|
25
|
+
|
|
26
|
+
At least two provider API keys are required (one will be excluded as the caller).
|
|
27
|
+
`XAI_API_KEY` is always required (used by the summarizer).
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
OPENAI_API_KEY=sk-...
|
|
31
|
+
XAI_API_KEY=xai-...
|
|
32
|
+
ANTHROPIC_API_KEY=sk-ant-...
|
|
33
|
+
GEMINI_API_KEY=AI...
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 3. Use as MCP tool (recommended for agents)
|
|
37
|
+
|
|
38
|
+
Add to your MCP server config:
|
|
39
|
+
|
|
40
|
+
`TASKFORCE_CALLER_PROVIDER` is the provider of the agent that will call this tool.
|
|
41
|
+
The matching provider's model is excluded from the panel -- querying the same model that is already reasoning adds no diversity.
|
|
42
|
+
For example, if Claude Code is the caller, set it to `"anthropic"` so Claude is excluded from the panel.
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"mcpServers": {
|
|
47
|
+
"taskforce": {
|
|
48
|
+
"command": "python",
|
|
49
|
+
"args": ["-m", "taskforce.mcp_wrapper"],
|
|
50
|
+
"env": {
|
|
51
|
+
"TASKFORCE_CALLER_PROVIDER": "anthropic"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The agent can then call the `roundtable_discuss` tool with `agenda` and `context` parameters.
|
|
59
|
+
|
|
60
|
+
### 4. Use as Python library
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
from taskforce import Taskforce
|
|
64
|
+
|
|
65
|
+
tf = Taskforce(caller_provider="anthropic")
|
|
66
|
+
pool = tf.discuss(
|
|
67
|
+
agenda="Evaluate the trade-offs of approach A vs B",
|
|
68
|
+
context="<detailed context here>"
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# pool.common -- list[str]: points most models agree on
|
|
72
|
+
# pool.divergent -- list[DivergentPoint]: topics with differing positions
|
|
73
|
+
# pool.unique -- list[UniquePoint]: points raised by only one model
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Important Notes
|
|
77
|
+
|
|
78
|
+
- **Paid API calls.** Every `discuss()` invocation calls multiple LLM APIs in parallel. Agents should confirm with the user before calling.
|
|
79
|
+
- **caller_provider exclusion.** The model from the same provider as the calling agent is excluded from the panel to maximize perspective diversity.
|
|
80
|
+
- **XAI_API_KEY is mandatory.** The summarizer (grok-4-1-fast-non-reasoning) always uses the XAI key.
|
|
81
|
+
- **Rich context matters.** Input tokens are cheap. Provide as much context as possible -- specifications, constraints, background, decisions already made -- so the panel can give concrete, actionable opinions instead of generic advice.
|
|
82
|
+
|
|
83
|
+
## API
|
|
84
|
+
|
|
85
|
+
### `Taskforce(caller_provider, dotenv_path=None)`
|
|
86
|
+
|
|
87
|
+
- `caller_provider` (`str`): The LLM provider of the calling agent (e.g. `"anthropic"`, `"openai"`). That provider's model is excluded from the panel.
|
|
88
|
+
- `dotenv_path` (`str | None`): Path to `.env` file. Defaults to auto-discovery.
|
|
89
|
+
|
|
90
|
+
### `Taskforce.discuss(agenda, context="") -> IdeaPool`
|
|
91
|
+
|
|
92
|
+
Synchronous wrapper. Queries the panel, summarizes, and returns an `IdeaPool`.
|
|
93
|
+
|
|
94
|
+
### `Taskforce.discuss_async(agenda, context="") -> IdeaPool`
|
|
95
|
+
|
|
96
|
+
Async version for use in async contexts.
|
|
97
|
+
|
|
98
|
+
### `IdeaPool`
|
|
99
|
+
|
|
100
|
+
| Field | Type | Description |
|
|
101
|
+
|-------|------|-------------|
|
|
102
|
+
| `agenda` | `str` | The original agenda |
|
|
103
|
+
| `common` | `list[str]` | Points most models agree on |
|
|
104
|
+
| `divergent` | `list[DivergentPoint]` | Topics with differing positions (`topic`, `positions: dict[model, position]`) |
|
|
105
|
+
| `unique` | `list[UniquePoint]` | Points from a single model (`point`, `source_model`) |
|
|
106
|
+
| `total_cost` | `float` | Total API cost (USD) |
|
|
107
|
+
| `total_tokens` | `int` | Total tokens consumed |
|
|
108
|
+
|
|
109
|
+
## License
|
|
110
|
+
|
|
111
|
+
MIT
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "ff-taskforce"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Multi-LLM roundtable for diverse perspective gathering"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
keywords = ["llm", "multi-model", "roundtable", "mcp", "agent"]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Development Status :: 3 - Alpha",
|
|
15
|
+
"License :: OSI Approved :: MIT License",
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Programming Language :: Python :: 3.10",
|
|
18
|
+
"Programming Language :: Python :: 3.11",
|
|
19
|
+
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"Programming Language :: Python :: 3.13",
|
|
21
|
+
]
|
|
22
|
+
dependencies = [
|
|
23
|
+
"litellm",
|
|
24
|
+
"python-dotenv",
|
|
25
|
+
"pydantic>=2.0",
|
|
26
|
+
"loguru",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[project.optional-dependencies]
|
|
30
|
+
mcp = ["mcp"]
|
|
31
|
+
|
|
32
|
+
[project.urls]
|
|
33
|
+
Repository = "https://github.com/gatesplan/taskforce"
|
|
34
|
+
Issues = "https://github.com/gatesplan/taskforce/issues"
|
|
35
|
+
|
|
36
|
+
[tool.hatch.build.targets.wheel]
|
|
37
|
+
packages = ["src/taskforce"]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# taskforce
|
|
2
|
+
|
|
3
|
+
## l1
|
|
4
|
+
- schema: 데이터 모델 (ModelEntry, Opinion, IdeaPool)
|
|
5
|
+
|
|
6
|
+
## l2
|
|
7
|
+
- config: .env 로드, 모델 레지스트리, caller 제외 로직
|
|
8
|
+
- panelist: LiteLLM 래퍼, 개별 모델 async 호출
|
|
9
|
+
- session_logger: 세션 전문 로그 (~/.taskforce/logs/)
|
|
10
|
+
- cost_logger: 비용 요약 로그 (~/.taskforce/cost_logs/)
|
|
11
|
+
|
|
12
|
+
## l3
|
|
13
|
+
- roundtable: 병렬 질의 + summarizer 분류 취합
|
|
14
|
+
|
|
15
|
+
## l4
|
|
16
|
+
- taskforce_facade: 최상위 퍼사드, 초기화/discuss/로그 기록
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# l1
|
|
2
|
+
|
|
3
|
+
## schema
|
|
4
|
+
ModelEntry(provider: str, model_id: str, api_key: str, display_name: str)
|
|
5
|
+
Opinion(model_name: str, content: str)
|
|
6
|
+
DivergentPoint(topic: str, positions: dict[str, str])
|
|
7
|
+
UniquePoint(point: str, source_model: str)
|
|
8
|
+
IdeaPool(agenda: str, common: list[str], divergent: list[DivergentPoint], unique: list[UniquePoint])
|