cat-stack 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cat_stack/__about__.py +10 -0
- cat_stack/__init__.py +128 -0
- cat_stack/_batch.py +1388 -0
- cat_stack/_category_analysis.py +348 -0
- cat_stack/_chunked.py +424 -0
- cat_stack/_embeddings.py +189 -0
- cat_stack/_formatter.py +169 -0
- cat_stack/_providers.py +1048 -0
- cat_stack/_tiebreaker.py +277 -0
- cat_stack/_utils.py +512 -0
- cat_stack/_web_fetch.py +194 -0
- cat_stack/calls/CoVe.py +287 -0
- cat_stack/calls/__init__.py +25 -0
- cat_stack/calls/all_calls.py +622 -0
- cat_stack/calls/image_CoVe.py +386 -0
- cat_stack/calls/image_stepback.py +210 -0
- cat_stack/calls/pdf_CoVe.py +386 -0
- cat_stack/calls/pdf_stepback.py +210 -0
- cat_stack/calls/stepback.py +180 -0
- cat_stack/calls/top_n.py +217 -0
- cat_stack/classify.py +682 -0
- cat_stack/explore.py +111 -0
- cat_stack/extract.py +218 -0
- cat_stack/image_functions.py +2078 -0
- cat_stack/images/circle.png +0 -0
- cat_stack/images/cube.png +0 -0
- cat_stack/images/diamond.png +0 -0
- cat_stack/images/overlapping_pentagons.png +0 -0
- cat_stack/images/rectangles.png +0 -0
- cat_stack/model_reference_list.py +94 -0
- cat_stack/pdf_functions.py +2087 -0
- cat_stack/summarize.py +290 -0
- cat_stack/text_functions.py +1358 -0
- cat_stack/text_functions_ensemble.py +3644 -0
- cat_stack-0.1.0.dist-info/METADATA +150 -0
- cat_stack-0.1.0.dist-info/RECORD +38 -0
- cat_stack-0.1.0.dist-info/WHEEL +4 -0
- cat_stack-0.1.0.dist-info/licenses/LICENSE +672 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Stepback prompting functions for various LLM providers
|
|
2
|
+
|
|
3
|
+
import requests
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def get_stepback_insight_openai(
|
|
7
|
+
stepback,
|
|
8
|
+
api_key,
|
|
9
|
+
user_model,
|
|
10
|
+
model_source="openai",
|
|
11
|
+
creativity=None
|
|
12
|
+
):
|
|
13
|
+
"""
|
|
14
|
+
Get stepback insight from OpenAI-compatible APIs.
|
|
15
|
+
Supports OpenAI, Perplexity, Huggingface, and xAI.
|
|
16
|
+
|
|
17
|
+
Uses direct HTTP requests instead of OpenAI SDK for lighter dependencies.
|
|
18
|
+
"""
|
|
19
|
+
# Determine the base URL based on model source
|
|
20
|
+
if model_source == "huggingface":
|
|
21
|
+
from cat_stack._providers import _detect_huggingface_endpoint
|
|
22
|
+
base_url = _detect_huggingface_endpoint(api_key, user_model)
|
|
23
|
+
elif model_source == "huggingface-together":
|
|
24
|
+
base_url = "https://router.huggingface.co/together/v1"
|
|
25
|
+
elif model_source == "perplexity":
|
|
26
|
+
base_url = "https://api.perplexity.ai"
|
|
27
|
+
elif model_source == "xai":
|
|
28
|
+
base_url = "https://api.x.ai/v1"
|
|
29
|
+
else:
|
|
30
|
+
base_url = "https://api.openai.com/v1"
|
|
31
|
+
|
|
32
|
+
endpoint = f"{base_url}/chat/completions"
|
|
33
|
+
|
|
34
|
+
headers = {
|
|
35
|
+
"Content-Type": "application/json",
|
|
36
|
+
"Authorization": f"Bearer {api_key}"
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
payload = {
|
|
40
|
+
"model": user_model,
|
|
41
|
+
"messages": [{"role": "user", "content": stepback}],
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if creativity is not None:
|
|
45
|
+
payload["temperature"] = creativity
|
|
46
|
+
|
|
47
|
+
try:
|
|
48
|
+
response = requests.post(endpoint, headers=headers, json=payload, timeout=120)
|
|
49
|
+
response.raise_for_status()
|
|
50
|
+
result = response.json()
|
|
51
|
+
stepback_insight = result["choices"][0]["message"]["content"]
|
|
52
|
+
|
|
53
|
+
return stepback_insight, True
|
|
54
|
+
|
|
55
|
+
except Exception as e:
|
|
56
|
+
return None, False
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def get_stepback_insight_anthropic(
|
|
60
|
+
stepback,
|
|
61
|
+
api_key,
|
|
62
|
+
user_model,
|
|
63
|
+
model_source="anthropic",
|
|
64
|
+
creativity=None
|
|
65
|
+
):
|
|
66
|
+
"""
|
|
67
|
+
Get stepback insight from Anthropic Claude.
|
|
68
|
+
|
|
69
|
+
Uses direct HTTP requests instead of Anthropic SDK for lighter dependencies.
|
|
70
|
+
"""
|
|
71
|
+
import requests
|
|
72
|
+
|
|
73
|
+
endpoint = "https://api.anthropic.com/v1/messages"
|
|
74
|
+
|
|
75
|
+
headers = {
|
|
76
|
+
"Content-Type": "application/json",
|
|
77
|
+
"x-api-key": api_key,
|
|
78
|
+
"anthropic-version": "2023-06-01"
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
payload = {
|
|
82
|
+
"model": user_model,
|
|
83
|
+
"max_tokens": 4096,
|
|
84
|
+
"messages": [{"role": "user", "content": stepback}],
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if creativity is not None:
|
|
88
|
+
payload["temperature"] = creativity
|
|
89
|
+
|
|
90
|
+
try:
|
|
91
|
+
response = requests.post(endpoint, headers=headers, json=payload, timeout=120)
|
|
92
|
+
response.raise_for_status()
|
|
93
|
+
result = response.json()
|
|
94
|
+
|
|
95
|
+
# Parse response - Anthropic returns content as a list
|
|
96
|
+
content = result.get("content", [])
|
|
97
|
+
if content and content[0].get("type") == "text":
|
|
98
|
+
stepback_insight = content[0].get("text", "")
|
|
99
|
+
return stepback_insight, True
|
|
100
|
+
|
|
101
|
+
return None, False
|
|
102
|
+
|
|
103
|
+
except Exception as e:
|
|
104
|
+
return None, False
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def get_stepback_insight_google(
|
|
108
|
+
stepback,
|
|
109
|
+
api_key,
|
|
110
|
+
user_model,
|
|
111
|
+
model_source="google",
|
|
112
|
+
creativity=None
|
|
113
|
+
):
|
|
114
|
+
"""
|
|
115
|
+
Get stepback insight from Google Gemini.
|
|
116
|
+
"""
|
|
117
|
+
import requests
|
|
118
|
+
|
|
119
|
+
url = f"https://generativelanguage.googleapis.com/v1beta/models/{user_model}:generateContent?key={api_key}"
|
|
120
|
+
|
|
121
|
+
headers = {
|
|
122
|
+
"Content-Type": "application/json"
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
payload = {
|
|
126
|
+
"contents": [{
|
|
127
|
+
"parts": [{"text": stepback}],
|
|
128
|
+
|
|
129
|
+
**({"generationConfig": {"temperature": creativity}} if creativity is not None else {})
|
|
130
|
+
}]
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
try:
|
|
134
|
+
response = requests.post(url, headers=headers, json=payload)
|
|
135
|
+
response.raise_for_status() # Raise error for bad status codes
|
|
136
|
+
|
|
137
|
+
result = response.json()
|
|
138
|
+
stepback_insight = result['candidates'][0]['content']['parts'][0]['text']
|
|
139
|
+
|
|
140
|
+
return stepback_insight, True
|
|
141
|
+
|
|
142
|
+
except Exception as e:
|
|
143
|
+
return None, False
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def get_stepback_insight_mistral(
|
|
147
|
+
stepback,
|
|
148
|
+
api_key,
|
|
149
|
+
user_model,
|
|
150
|
+
model_source="mistral",
|
|
151
|
+
creativity=None
|
|
152
|
+
):
|
|
153
|
+
"""
|
|
154
|
+
Get stepback insight from Mistral AI.
|
|
155
|
+
"""
|
|
156
|
+
import requests
|
|
157
|
+
|
|
158
|
+
endpoint = "https://api.mistral.ai/v1/chat/completions"
|
|
159
|
+
headers = {
|
|
160
|
+
"Content-Type": "application/json",
|
|
161
|
+
"Authorization": f"Bearer {api_key}"
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
payload = {
|
|
165
|
+
"model": user_model,
|
|
166
|
+
"messages": [{'role': 'user', 'content': stepback}],
|
|
167
|
+
}
|
|
168
|
+
if creativity is not None:
|
|
169
|
+
payload["temperature"] = creativity
|
|
170
|
+
|
|
171
|
+
try:
|
|
172
|
+
response = requests.post(endpoint, headers=headers, json=payload, timeout=120)
|
|
173
|
+
response.raise_for_status()
|
|
174
|
+
result = response.json()
|
|
175
|
+
stepback_insight = result["choices"][0]["message"]["content"]
|
|
176
|
+
|
|
177
|
+
return stepback_insight, True
|
|
178
|
+
|
|
179
|
+
except Exception as e:
|
|
180
|
+
return None, False
|
cat_stack/calls/top_n.py
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# Top N category extraction functions for various LLM providers
|
|
2
|
+
|
|
3
|
+
import requests
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def get_openai_top_n(
|
|
7
|
+
prompt,
|
|
8
|
+
user_model,
|
|
9
|
+
specificity,
|
|
10
|
+
model_source,
|
|
11
|
+
api_key,
|
|
12
|
+
research_question,
|
|
13
|
+
creativity
|
|
14
|
+
):
|
|
15
|
+
"""
|
|
16
|
+
Get response from OpenAI API with system message.
|
|
17
|
+
Supports OpenAI, Perplexity, Huggingface, and xAI.
|
|
18
|
+
|
|
19
|
+
Uses direct HTTP requests instead of OpenAI SDK for lighter dependencies.
|
|
20
|
+
"""
|
|
21
|
+
# Determine the base URL based on model source
|
|
22
|
+
if model_source == "huggingface":
|
|
23
|
+
from cat_stack._providers import _detect_huggingface_endpoint
|
|
24
|
+
base_url = _detect_huggingface_endpoint(api_key, user_model)
|
|
25
|
+
elif model_source == "huggingface-together":
|
|
26
|
+
base_url = "https://router.huggingface.co/together/v1"
|
|
27
|
+
elif model_source == "perplexity":
|
|
28
|
+
base_url = "https://api.perplexity.ai"
|
|
29
|
+
elif model_source == "xai":
|
|
30
|
+
base_url = "https://api.x.ai/v1"
|
|
31
|
+
else:
|
|
32
|
+
base_url = "https://api.openai.com/v1"
|
|
33
|
+
|
|
34
|
+
endpoint = f"{base_url}/chat/completions"
|
|
35
|
+
|
|
36
|
+
headers = {
|
|
37
|
+
"Content-Type": "application/json",
|
|
38
|
+
"Authorization": f"Bearer {api_key}"
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# Build system message
|
|
42
|
+
if research_question:
|
|
43
|
+
system_content = (
|
|
44
|
+
f"You are a helpful assistant that extracts categories from text responses. "
|
|
45
|
+
f"The specific task is to identify {specificity} categories of responses to a text prompt. "
|
|
46
|
+
f"The research question is: {research_question}"
|
|
47
|
+
)
|
|
48
|
+
else:
|
|
49
|
+
system_content = "You are a helpful assistant."
|
|
50
|
+
|
|
51
|
+
payload = {
|
|
52
|
+
"model": user_model,
|
|
53
|
+
"messages": [
|
|
54
|
+
{"role": "system", "content": system_content},
|
|
55
|
+
{"role": "user", "content": prompt}
|
|
56
|
+
],
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if creativity is not None:
|
|
60
|
+
payload["temperature"] = creativity
|
|
61
|
+
|
|
62
|
+
response = requests.post(endpoint, headers=headers, json=payload, timeout=120)
|
|
63
|
+
response.raise_for_status()
|
|
64
|
+
result = response.json()
|
|
65
|
+
|
|
66
|
+
return result["choices"][0]["message"]["content"]
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def get_anthropic_top_n(
|
|
70
|
+
prompt,
|
|
71
|
+
user_model,
|
|
72
|
+
model_source,
|
|
73
|
+
specificity,
|
|
74
|
+
api_key,
|
|
75
|
+
research_question,
|
|
76
|
+
creativity
|
|
77
|
+
):
|
|
78
|
+
"""
|
|
79
|
+
Get response from Anthropic API with system prompt.
|
|
80
|
+
|
|
81
|
+
Uses direct HTTP requests instead of Anthropic SDK for lighter dependencies.
|
|
82
|
+
"""
|
|
83
|
+
import requests
|
|
84
|
+
|
|
85
|
+
endpoint = "https://api.anthropic.com/v1/messages"
|
|
86
|
+
|
|
87
|
+
headers = {
|
|
88
|
+
"Content-Type": "application/json",
|
|
89
|
+
"x-api-key": api_key,
|
|
90
|
+
"anthropic-version": "2023-06-01"
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
# Build system prompt
|
|
94
|
+
if research_question:
|
|
95
|
+
system_content = (f"You are a helpful assistant that extracts categories from text responses. "
|
|
96
|
+
f"The specific task is to identify {specificity} categories of responses to a text prompt. "
|
|
97
|
+
f"The research question is: {research_question}")
|
|
98
|
+
else:
|
|
99
|
+
system_content = "You are a helpful assistant."
|
|
100
|
+
|
|
101
|
+
payload = {
|
|
102
|
+
"model": user_model,
|
|
103
|
+
"max_tokens": 4096,
|
|
104
|
+
"system": system_content,
|
|
105
|
+
"messages": [{"role": "user", "content": prompt}],
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if creativity is not None:
|
|
109
|
+
payload["temperature"] = creativity
|
|
110
|
+
|
|
111
|
+
response = requests.post(endpoint, headers=headers, json=payload, timeout=120)
|
|
112
|
+
response.raise_for_status()
|
|
113
|
+
result = response.json()
|
|
114
|
+
|
|
115
|
+
# Parse response - Anthropic returns content as a list
|
|
116
|
+
content = result.get("content", [])
|
|
117
|
+
if content and content[0].get("type") == "text":
|
|
118
|
+
return content[0].get("text", "")
|
|
119
|
+
|
|
120
|
+
return ""
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def get_google_top_n(
|
|
124
|
+
prompt,
|
|
125
|
+
user_model,
|
|
126
|
+
specificity,
|
|
127
|
+
model_source,
|
|
128
|
+
api_key,
|
|
129
|
+
research_question,
|
|
130
|
+
creativity
|
|
131
|
+
):
|
|
132
|
+
"""
|
|
133
|
+
Get response from Google Gemini API.
|
|
134
|
+
"""
|
|
135
|
+
import requests
|
|
136
|
+
|
|
137
|
+
url = f"https://generativelanguage.googleapis.com/v1beta/models/{user_model}:generateContent"
|
|
138
|
+
|
|
139
|
+
headers = {
|
|
140
|
+
"x-goog-api-key": api_key,
|
|
141
|
+
"Content-Type": "application/json"
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
# Build system-like content in the prompt
|
|
145
|
+
if research_question:
|
|
146
|
+
system_context = (f"You are a helpful assistant that extracts categories from text responses. "
|
|
147
|
+
f"The specific task is to identify {specificity} categories of responses to a text prompt. "
|
|
148
|
+
f"The research question is: {research_question}\n\n")
|
|
149
|
+
else:
|
|
150
|
+
system_context = "You are a helpful assistant.\n\n"
|
|
151
|
+
|
|
152
|
+
full_prompt = system_context + prompt
|
|
153
|
+
|
|
154
|
+
payload = {
|
|
155
|
+
"contents": [{
|
|
156
|
+
"parts": [{"text": full_prompt}]
|
|
157
|
+
}],
|
|
158
|
+
"generationConfig": {
|
|
159
|
+
**({"temperature": creativity} if creativity is not None else {})
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
response = requests.post(url, headers=headers, json=payload)
|
|
164
|
+
response.raise_for_status()
|
|
165
|
+
|
|
166
|
+
result = response.json()
|
|
167
|
+
|
|
168
|
+
if "candidates" in result and result["candidates"]:
|
|
169
|
+
return result["candidates"][0]["content"]["parts"][0]["text"]
|
|
170
|
+
else:
|
|
171
|
+
return "No response generated"
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def get_mistral_top_n(
|
|
175
|
+
prompt,
|
|
176
|
+
user_model,
|
|
177
|
+
specificity,
|
|
178
|
+
model_source,
|
|
179
|
+
api_key,
|
|
180
|
+
research_question,
|
|
181
|
+
creativity
|
|
182
|
+
):
|
|
183
|
+
"""
|
|
184
|
+
Get response from Mistral AI API.
|
|
185
|
+
"""
|
|
186
|
+
import requests
|
|
187
|
+
|
|
188
|
+
endpoint = "https://api.mistral.ai/v1/chat/completions"
|
|
189
|
+
headers = {
|
|
190
|
+
"Content-Type": "application/json",
|
|
191
|
+
"Authorization": f"Bearer {api_key}"
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
# Build system prompt
|
|
195
|
+
if research_question:
|
|
196
|
+
system_content = (f"You are a helpful assistant that extracts categories from text responses. "
|
|
197
|
+
f"The specific task is to identify {specificity} categories of responses to a text prompt. "
|
|
198
|
+
f"The research question is: {research_question}")
|
|
199
|
+
else:
|
|
200
|
+
system_content = "You are a helpful assistant."
|
|
201
|
+
|
|
202
|
+
payload = {
|
|
203
|
+
"model": user_model,
|
|
204
|
+
"messages": [
|
|
205
|
+
{'role': 'system', 'content': system_content},
|
|
206
|
+
{'role': 'user', 'content': prompt}
|
|
207
|
+
],
|
|
208
|
+
}
|
|
209
|
+
if creativity is not None:
|
|
210
|
+
payload["temperature"] = creativity
|
|
211
|
+
|
|
212
|
+
response = requests.post(endpoint, headers=headers, json=payload, timeout=120)
|
|
213
|
+
response.raise_for_status()
|
|
214
|
+
result = response.json()
|
|
215
|
+
|
|
216
|
+
return result["choices"][0]["message"]["content"]
|
|
217
|
+
|