omnimancer-cli 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.
- omnimancer/__init__.py +42 -0
- omnimancer/__main__.py +9 -0
- omnimancer/cli/__init__.py +8 -0
- omnimancer/cli/agent_manager.py +826 -0
- omnimancer/cli/agent_wizard.py +944 -0
- omnimancer/cli/approval_formatter.py +734 -0
- omnimancer/cli/approval_integration.py +734 -0
- omnimancer/cli/approval_prompt.py +1286 -0
- omnimancer/cli/batch_approval_display.py +617 -0
- omnimancer/cli/batch_approval_filters.py +729 -0
- omnimancer/cli/batch_operation_monitor.py +775 -0
- omnimancer/cli/commands/performance_cmd.py +624 -0
- omnimancer/cli/commands.py +757 -0
- omnimancer/cli/completion_handler.py +281 -0
- omnimancer/cli/config_setup_wizard.py +783 -0
- omnimancer/cli/dynamic_commands.py +371 -0
- omnimancer/cli/handlers/__init__.py +18 -0
- omnimancer/cli/handlers/agent_handler.py +865 -0
- omnimancer/cli/handlers/agent_persona_handler.py +1048 -0
- omnimancer/cli/handlers/custom_agent_handler.py +352 -0
- omnimancer/cli/handlers/permissions_handler.py +1609 -0
- omnimancer/cli/interface.py +6695 -0
- omnimancer/cli/performance_dashboard.py +612 -0
- omnimancer/core/__init__.py +34 -0
- omnimancer/core/agent/__init__.py +256 -0
- omnimancer/core/agent/agent_config.py +715 -0
- omnimancer/core/agent/agent_switcher.py +668 -0
- omnimancer/core/agent/approval_context.py +460 -0
- omnimancer/core/agent/approval_dialog.py +902 -0
- omnimancer/core/agent/approval_interface.py +628 -0
- omnimancer/core/agent/approval_manager.py +760 -0
- omnimancer/core/agent/cli_integration.py +470 -0
- omnimancer/core/agent/config.py +845 -0
- omnimancer/core/agent/custom_agent_integration.py +654 -0
- omnimancer/core/agent/diff_renderer.py +706 -0
- omnimancer/core/agent/file_content_display.py +503 -0
- omnimancer/core/agent/file_modification_workflow.py +658 -0
- omnimancer/core/agent/file_system_manager.py +1790 -0
- omnimancer/core/agent/input_handler.py +614 -0
- omnimancer/core/agent/metrics_collector.py +771 -0
- omnimancer/core/agent/optimization_engine.py +729 -0
- omnimancer/core/agent/performance_monitor.py +717 -0
- omnimancer/core/agent/persona.py +870 -0
- omnimancer/core/agent/persona_validator.py +672 -0
- omnimancer/core/agent/program_executor.py +748 -0
- omnimancer/core/agent/proposed_changes_integration.py +663 -0
- omnimancer/core/agent/read_before_write_errors.py +492 -0
- omnimancer/core/agent/read_before_write_ui.py +647 -0
- omnimancer/core/agent/rich_renderer.py +763 -0
- omnimancer/core/agent/status_config.py +238 -0
- omnimancer/core/agent/status_core.py +446 -0
- omnimancer/core/agent/status_integrated_engine.py +540 -0
- omnimancer/core/agent/status_manager.py +878 -0
- omnimancer/core/agent/status_ui_components.py +535 -0
- omnimancer/core/agent/template_applicator.py +548 -0
- omnimancer/core/agent/terminal_status_listener.py +394 -0
- omnimancer/core/agent/token_tracker.py +679 -0
- omnimancer/core/agent/types.py +60 -0
- omnimancer/core/agent/web_client.py +745 -0
- omnimancer/core/agent/workflow_orchestrator.py +826 -0
- omnimancer/core/agent_engine.py +1625 -0
- omnimancer/core/agent_mode_manager.py +706 -0
- omnimancer/core/agent_progress_ui.py +545 -0
- omnimancer/core/chat_manager.py +141 -0
- omnimancer/core/config_manager.py +2199 -0
- omnimancer/core/config_migration.py +772 -0
- omnimancer/core/config_provider.py +1974 -0
- omnimancer/core/config_security_validator.py +393 -0
- omnimancer/core/config_validator.py +768 -0
- omnimancer/core/conversation_manager.py +352 -0
- omnimancer/core/engine.py +787 -0
- omnimancer/core/enhanced_input.py +523 -0
- omnimancer/core/env_loader.py +83 -0
- omnimancer/core/fallback_manager.py +568 -0
- omnimancer/core/health_monitor.py +462 -0
- omnimancer/core/history_manager.py +462 -0
- omnimancer/core/mcp_integration_layer.py +878 -0
- omnimancer/core/models.py +1889 -0
- omnimancer/core/provider_capabilities.py +403 -0
- omnimancer/core/provider_initializer.py +450 -0
- omnimancer/core/provider_registry.py +432 -0
- omnimancer/core/security/__init__.py +16 -0
- omnimancer/core/security/approval_workflow.py +406 -0
- omnimancer/core/security/audit_logger.py +511 -0
- omnimancer/core/security/permission_controller.py +511 -0
- omnimancer/core/security/sandbox_manager.py +379 -0
- omnimancer/core/security/security_manager.py +530 -0
- omnimancer/core/setup_wizard.py +345 -0
- omnimancer/core/setup_wizard_core.py +449 -0
- omnimancer/core/setup_wizard_guide_generator.py +376 -0
- omnimancer/core/setup_wizard_provider_setup.py +454 -0
- omnimancer/core/setup_wizard_ui.py +317 -0
- omnimancer/core/setup_wizard_validation.py +371 -0
- omnimancer/core/signal_handler.py +174 -0
- omnimancer/mcp/__init__.py +11 -0
- omnimancer/mcp/client.py +725 -0
- omnimancer/mcp/manager.py +649 -0
- omnimancer/providers/__init__.py +24 -0
- omnimancer/providers/azure.py +608 -0
- omnimancer/providers/base.py +262 -0
- omnimancer/providers/bedrock.py +711 -0
- omnimancer/providers/claude.py +426 -0
- omnimancer/providers/claude_code.py +406 -0
- omnimancer/providers/cohere.py +412 -0
- omnimancer/providers/factory.py +988 -0
- omnimancer/providers/gemini.py +708 -0
- omnimancer/providers/mistral.py +554 -0
- omnimancer/providers/ollama.py +510 -0
- omnimancer/providers/openai.py +362 -0
- omnimancer/providers/openrouter.py +709 -0
- omnimancer/providers/perplexity.py +476 -0
- omnimancer/providers/vertex.py +617 -0
- omnimancer/providers/xai.py +484 -0
- omnimancer/ui/__init__.py +6 -0
- omnimancer/ui/cancellation_handler.py +235 -0
- omnimancer/ui/progress_indicator.py +318 -0
- omnimancer/utils/__init__.py +22 -0
- omnimancer/utils/error_handler.py +589 -0
- omnimancer/utils/errors.py +667 -0
- omnimancer/utils/retry.py +238 -0
- omnimancer_cli-0.1.0.dist-info/METADATA +413 -0
- omnimancer_cli-0.1.0.dist-info/RECORD +126 -0
- omnimancer_cli-0.1.0.dist-info/WHEEL +5 -0
- omnimancer_cli-0.1.0.dist-info/entry_points.txt +4 -0
- omnimancer_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
- omnimancer_cli-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Perplexity AI provider implementation for Omnimancer.
|
|
3
|
+
|
|
4
|
+
This module provides the Perplexity AI provider implementation using Perplexity's API
|
|
5
|
+
with support for search-enabled conversations and recency filtering.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
from typing import Dict, List
|
|
10
|
+
|
|
11
|
+
import httpx
|
|
12
|
+
|
|
13
|
+
from ..core.models import ChatContext, ChatResponse, EnhancedModelInfo
|
|
14
|
+
from ..utils.errors import (
|
|
15
|
+
AuthenticationError,
|
|
16
|
+
ModelNotFoundError,
|
|
17
|
+
NetworkError,
|
|
18
|
+
ProviderError,
|
|
19
|
+
RateLimitError,
|
|
20
|
+
)
|
|
21
|
+
from .base import BaseProvider
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class PerplexityProvider(BaseProvider):
|
|
25
|
+
"""
|
|
26
|
+
Perplexity AI provider implementation using Perplexity's API.
|
|
27
|
+
|
|
28
|
+
Supports search-enabled conversations with real-time web information
|
|
29
|
+
and recency filtering for up-to-date responses.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
BASE_URL = "https://api.perplexity.ai"
|
|
33
|
+
|
|
34
|
+
def __init__(self, api_key: str, model: str = "", **kwargs):
|
|
35
|
+
"""
|
|
36
|
+
Initialize Perplexity provider.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
api_key: Perplexity API key
|
|
40
|
+
model: Perplexity model to use (e.g., 'llama-3.1-sonar-small-128k-online', 'llama-3.1-sonar-large-128k-online')
|
|
41
|
+
**kwargs: Additional configuration including search settings
|
|
42
|
+
"""
|
|
43
|
+
super().__init__(
|
|
44
|
+
api_key, model or "llama-3.1-sonar-small-128k-online", **kwargs
|
|
45
|
+
)
|
|
46
|
+
self.max_tokens = kwargs.get("max_tokens", 4096)
|
|
47
|
+
self.temperature = kwargs.get("temperature", 0.2)
|
|
48
|
+
self.search_enabled = kwargs.get("search_enabled", True)
|
|
49
|
+
self.search_recency_filter = kwargs.get(
|
|
50
|
+
"search_recency_filter", "month"
|
|
51
|
+
) # hour, day, week, month, year
|
|
52
|
+
self.return_citations = kwargs.get("return_citations", False)
|
|
53
|
+
self.return_images = kwargs.get("return_images", False)
|
|
54
|
+
self.return_related_questions = kwargs.get("return_related_questions", False)
|
|
55
|
+
|
|
56
|
+
async def send_message(self, message: str, context: ChatContext) -> ChatResponse:
|
|
57
|
+
"""
|
|
58
|
+
Send a message to Perplexity API with search capabilities.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
message: User message
|
|
62
|
+
context: Conversation context
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
ChatResponse with Perplexity's reply including search results
|
|
66
|
+
"""
|
|
67
|
+
try:
|
|
68
|
+
# Prepare messages for Perplexity API
|
|
69
|
+
messages = self._prepare_messages(message, context)
|
|
70
|
+
|
|
71
|
+
# Build request payload
|
|
72
|
+
payload = {
|
|
73
|
+
"model": self.model,
|
|
74
|
+
"messages": messages,
|
|
75
|
+
"max_tokens": self.max_tokens,
|
|
76
|
+
"temperature": self.temperature,
|
|
77
|
+
"return_citations": self.return_citations,
|
|
78
|
+
"return_images": self.return_images,
|
|
79
|
+
"return_related_questions": self.return_related_questions,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# Add search-specific parameters for online models
|
|
83
|
+
if self._is_online_model():
|
|
84
|
+
payload["search_recency_filter"] = self.search_recency_filter
|
|
85
|
+
|
|
86
|
+
# Make API request
|
|
87
|
+
async with httpx.AsyncClient() as client:
|
|
88
|
+
response = await client.post(
|
|
89
|
+
f"{self.BASE_URL}/chat/completions",
|
|
90
|
+
headers={
|
|
91
|
+
"Content-Type": "application/json",
|
|
92
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
93
|
+
},
|
|
94
|
+
json=payload,
|
|
95
|
+
timeout=60.0, # Longer timeout for search operations
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
# Handle response
|
|
99
|
+
return self._handle_response(response)
|
|
100
|
+
|
|
101
|
+
except httpx.TimeoutException:
|
|
102
|
+
raise NetworkError("Request to Perplexity API timed out")
|
|
103
|
+
except httpx.RequestError as e:
|
|
104
|
+
raise NetworkError(f"Network error: {e}")
|
|
105
|
+
except (
|
|
106
|
+
AuthenticationError,
|
|
107
|
+
RateLimitError,
|
|
108
|
+
ModelNotFoundError,
|
|
109
|
+
ProviderError,
|
|
110
|
+
):
|
|
111
|
+
# Re-raise provider-specific errors without wrapping
|
|
112
|
+
raise
|
|
113
|
+
except Exception as e:
|
|
114
|
+
raise ProviderError(f"Unexpected error: {e}")
|
|
115
|
+
|
|
116
|
+
async def validate_credentials(self) -> bool:
|
|
117
|
+
"""
|
|
118
|
+
Validate Perplexity API credentials by making a test request.
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
True if credentials are valid
|
|
122
|
+
"""
|
|
123
|
+
try:
|
|
124
|
+
async with httpx.AsyncClient() as client:
|
|
125
|
+
response = await client.post(
|
|
126
|
+
f"{self.BASE_URL}/chat/completions",
|
|
127
|
+
headers={
|
|
128
|
+
"Content-Type": "application/json",
|
|
129
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
130
|
+
},
|
|
131
|
+
json={
|
|
132
|
+
"model": self.model,
|
|
133
|
+
"messages": [{"role": "user", "content": "Hi"}],
|
|
134
|
+
"max_tokens": 10,
|
|
135
|
+
},
|
|
136
|
+
timeout=10.0,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
return response.status_code == 200
|
|
140
|
+
|
|
141
|
+
except Exception:
|
|
142
|
+
return False
|
|
143
|
+
|
|
144
|
+
def _prepare_messages(
|
|
145
|
+
self, message: str, context: ChatContext
|
|
146
|
+
) -> List[Dict[str, str]]:
|
|
147
|
+
"""
|
|
148
|
+
Prepare messages for Perplexity API format.
|
|
149
|
+
|
|
150
|
+
Args:
|
|
151
|
+
message: Current user message
|
|
152
|
+
context: Conversation context
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
List of messages formatted for Perplexity API
|
|
156
|
+
"""
|
|
157
|
+
messages = []
|
|
158
|
+
|
|
159
|
+
# Add context messages
|
|
160
|
+
for msg in context.messages:
|
|
161
|
+
messages.append({"role": msg.role.value, "content": msg.content})
|
|
162
|
+
|
|
163
|
+
# Add current message
|
|
164
|
+
messages.append({"role": "user", "content": message})
|
|
165
|
+
|
|
166
|
+
return messages
|
|
167
|
+
|
|
168
|
+
def _handle_response(self, response: httpx.Response) -> ChatResponse:
|
|
169
|
+
"""
|
|
170
|
+
Handle Perplexity API response.
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
response: HTTP response from Perplexity API
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
ChatResponse object
|
|
177
|
+
|
|
178
|
+
Raises:
|
|
179
|
+
Various provider errors based on response status
|
|
180
|
+
"""
|
|
181
|
+
if response.status_code == 200:
|
|
182
|
+
data = response.json()
|
|
183
|
+
choices = data.get("choices", [])
|
|
184
|
+
|
|
185
|
+
if choices and len(choices) > 0:
|
|
186
|
+
message = choices[0].get("message", {})
|
|
187
|
+
content = message.get("content", "")
|
|
188
|
+
usage = data.get("usage", {})
|
|
189
|
+
|
|
190
|
+
# Extract citations and additional metadata
|
|
191
|
+
citations = data.get("citations", [])
|
|
192
|
+
images = data.get("images", [])
|
|
193
|
+
related_questions = data.get("related_questions", [])
|
|
194
|
+
|
|
195
|
+
# Format content with citations if available
|
|
196
|
+
formatted_content = self._format_content_with_metadata(
|
|
197
|
+
content, citations, images, related_questions
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
return ChatResponse(
|
|
201
|
+
content=formatted_content,
|
|
202
|
+
model_used=self.model,
|
|
203
|
+
tokens_used=usage.get("total_tokens", 0),
|
|
204
|
+
timestamp=datetime.now(),
|
|
205
|
+
)
|
|
206
|
+
else:
|
|
207
|
+
raise ProviderError("Empty response from Perplexity API")
|
|
208
|
+
|
|
209
|
+
elif response.status_code == 401:
|
|
210
|
+
raise AuthenticationError("Invalid Perplexity API key")
|
|
211
|
+
elif response.status_code == 429:
|
|
212
|
+
raise RateLimitError("Perplexity API rate limit exceeded")
|
|
213
|
+
elif response.status_code == 404:
|
|
214
|
+
raise ModelNotFoundError(f"Perplexity model '{self.model}' not found")
|
|
215
|
+
else:
|
|
216
|
+
try:
|
|
217
|
+
error_data = response.json()
|
|
218
|
+
error_msg = error_data.get("error", {}).get("message", "Unknown error")
|
|
219
|
+
except:
|
|
220
|
+
error_msg = f"HTTP {response.status_code}"
|
|
221
|
+
|
|
222
|
+
raise ProviderError(f"Perplexity API error: {error_msg}")
|
|
223
|
+
|
|
224
|
+
def _format_content_with_metadata(
|
|
225
|
+
self,
|
|
226
|
+
content: str,
|
|
227
|
+
citations: List[Dict],
|
|
228
|
+
images: List[Dict],
|
|
229
|
+
related_questions: List[str],
|
|
230
|
+
) -> str:
|
|
231
|
+
"""
|
|
232
|
+
Format response content with citations and metadata.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
content: Main response content
|
|
236
|
+
citations: List of citation objects
|
|
237
|
+
images: List of image objects
|
|
238
|
+
related_questions: List of related questions
|
|
239
|
+
|
|
240
|
+
Returns:
|
|
241
|
+
Formatted content string
|
|
242
|
+
"""
|
|
243
|
+
formatted = content
|
|
244
|
+
|
|
245
|
+
# Add citations if available
|
|
246
|
+
if citations and self.return_citations:
|
|
247
|
+
formatted += "\n\n**Sources:**\n"
|
|
248
|
+
for i, citation in enumerate(citations, 1):
|
|
249
|
+
title = citation.get("title", "Unknown")
|
|
250
|
+
url = citation.get("url", "")
|
|
251
|
+
formatted += f"{i}. [{title}]({url})\n"
|
|
252
|
+
|
|
253
|
+
# Add related questions if available
|
|
254
|
+
if related_questions and self.return_related_questions:
|
|
255
|
+
formatted += "\n\n**Related Questions:**\n"
|
|
256
|
+
for question in related_questions:
|
|
257
|
+
formatted += f"• {question}\n"
|
|
258
|
+
|
|
259
|
+
return formatted
|
|
260
|
+
|
|
261
|
+
def _is_online_model(self) -> bool:
|
|
262
|
+
"""
|
|
263
|
+
Check if the current model is an online/search-enabled model.
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
True if model supports online search
|
|
267
|
+
"""
|
|
268
|
+
online_models = [
|
|
269
|
+
"llama-3.1-sonar-small-128k-online",
|
|
270
|
+
"llama-3.1-sonar-large-128k-online",
|
|
271
|
+
"llama-3.1-sonar-huge-128k-online",
|
|
272
|
+
]
|
|
273
|
+
return self.model in online_models
|
|
274
|
+
|
|
275
|
+
def get_model_info(self) -> EnhancedModelInfo:
|
|
276
|
+
"""
|
|
277
|
+
Get information about the current Perplexity model.
|
|
278
|
+
"""
|
|
279
|
+
model_configs = {
|
|
280
|
+
"llama-3.1-sonar-small-128k-online": {
|
|
281
|
+
"description": "Llama 3.1 Sonar Small with real-time web search",
|
|
282
|
+
"max_tokens": 127072,
|
|
283
|
+
"cost_per_million_input": 0.2,
|
|
284
|
+
"cost_per_million_output": 0.2,
|
|
285
|
+
"swe_score": 45.2,
|
|
286
|
+
"supports_tools": True,
|
|
287
|
+
"supports_multimodal": False,
|
|
288
|
+
},
|
|
289
|
+
"llama-3.1-sonar-large-128k-online": {
|
|
290
|
+
"description": "Llama 3.1 Sonar Large with real-time web search",
|
|
291
|
+
"max_tokens": 127072,
|
|
292
|
+
"cost_per_million_input": 1.0,
|
|
293
|
+
"cost_per_million_output": 1.0,
|
|
294
|
+
"swe_score": 52.4,
|
|
295
|
+
"supports_tools": True,
|
|
296
|
+
"supports_multimodal": False,
|
|
297
|
+
},
|
|
298
|
+
"llama-3.1-sonar-huge-128k-online": {
|
|
299
|
+
"description": "Llama 3.1 Sonar Huge with real-time web search",
|
|
300
|
+
"max_tokens": 127072,
|
|
301
|
+
"cost_per_million_input": 5.0,
|
|
302
|
+
"cost_per_million_output": 5.0,
|
|
303
|
+
"swe_score": 58.1,
|
|
304
|
+
"supports_tools": True,
|
|
305
|
+
"supports_multimodal": False,
|
|
306
|
+
},
|
|
307
|
+
"llama-3.1-sonar-small-128k-chat": {
|
|
308
|
+
"description": "Llama 3.1 Sonar Small for chat without search",
|
|
309
|
+
"max_tokens": 127072,
|
|
310
|
+
"cost_per_million_input": 0.2,
|
|
311
|
+
"cost_per_million_output": 0.2,
|
|
312
|
+
"swe_score": 45.2,
|
|
313
|
+
"supports_tools": False,
|
|
314
|
+
"supports_multimodal": False,
|
|
315
|
+
},
|
|
316
|
+
"llama-3.1-sonar-large-128k-chat": {
|
|
317
|
+
"description": "Llama 3.1 Sonar Large for chat without search",
|
|
318
|
+
"max_tokens": 127072,
|
|
319
|
+
"cost_per_million_input": 1.0,
|
|
320
|
+
"cost_per_million_output": 1.0,
|
|
321
|
+
"swe_score": 52.4,
|
|
322
|
+
"supports_tools": False,
|
|
323
|
+
"supports_multimodal": False,
|
|
324
|
+
},
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
config = model_configs.get(
|
|
328
|
+
self.model,
|
|
329
|
+
{
|
|
330
|
+
"description": f"Perplexity model {self.model}",
|
|
331
|
+
"max_tokens": 127072,
|
|
332
|
+
"cost_per_million_input": 1.0,
|
|
333
|
+
"cost_per_million_output": 1.0,
|
|
334
|
+
"swe_score": 50.0,
|
|
335
|
+
"supports_tools": False,
|
|
336
|
+
"supports_multimodal": False,
|
|
337
|
+
},
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
enhanced_info = EnhancedModelInfo(
|
|
341
|
+
name=self.model,
|
|
342
|
+
provider="perplexity",
|
|
343
|
+
description=config["description"],
|
|
344
|
+
max_tokens=config["max_tokens"],
|
|
345
|
+
cost_per_million_input=config["cost_per_million_input"],
|
|
346
|
+
cost_per_million_output=config["cost_per_million_output"],
|
|
347
|
+
swe_score=config["swe_score"],
|
|
348
|
+
available=True,
|
|
349
|
+
supports_tools=config["supports_tools"],
|
|
350
|
+
supports_multimodal=config["supports_multimodal"],
|
|
351
|
+
latest_version=self.model == "llama-3.1-sonar-huge-128k-online",
|
|
352
|
+
context_window=config["max_tokens"],
|
|
353
|
+
is_free=False,
|
|
354
|
+
release_date=datetime(2024, 7, 1), # Approximate release date
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
# Update SWE rating based on score
|
|
358
|
+
enhanced_info.update_swe_rating()
|
|
359
|
+
|
|
360
|
+
return enhanced_info
|
|
361
|
+
|
|
362
|
+
def get_available_models(self) -> List[EnhancedModelInfo]:
|
|
363
|
+
"""
|
|
364
|
+
Get list of available Perplexity models.
|
|
365
|
+
"""
|
|
366
|
+
models = [
|
|
367
|
+
EnhancedModelInfo(
|
|
368
|
+
name="llama-3.1-sonar-small-128k-online",
|
|
369
|
+
provider="perplexity",
|
|
370
|
+
description="Llama 3.1 Sonar Small with real-time web search",
|
|
371
|
+
max_tokens=127072,
|
|
372
|
+
cost_per_million_input=0.2,
|
|
373
|
+
cost_per_million_output=0.2,
|
|
374
|
+
swe_score=45.2,
|
|
375
|
+
available=True,
|
|
376
|
+
supports_tools=True,
|
|
377
|
+
supports_multimodal=False,
|
|
378
|
+
context_window=127072,
|
|
379
|
+
is_free=False,
|
|
380
|
+
release_date=datetime(2024, 7, 1),
|
|
381
|
+
),
|
|
382
|
+
EnhancedModelInfo(
|
|
383
|
+
name="llama-3.1-sonar-large-128k-online",
|
|
384
|
+
provider="perplexity",
|
|
385
|
+
description="Llama 3.1 Sonar Large with real-time web search",
|
|
386
|
+
max_tokens=127072,
|
|
387
|
+
cost_per_million_input=1.0,
|
|
388
|
+
cost_per_million_output=1.0,
|
|
389
|
+
swe_score=52.4,
|
|
390
|
+
available=True,
|
|
391
|
+
supports_tools=True,
|
|
392
|
+
supports_multimodal=False,
|
|
393
|
+
context_window=127072,
|
|
394
|
+
is_free=False,
|
|
395
|
+
release_date=datetime(2024, 7, 1),
|
|
396
|
+
),
|
|
397
|
+
EnhancedModelInfo(
|
|
398
|
+
name="llama-3.1-sonar-huge-128k-online",
|
|
399
|
+
provider="perplexity",
|
|
400
|
+
description="Llama 3.1 Sonar Huge with real-time web search",
|
|
401
|
+
max_tokens=127072,
|
|
402
|
+
cost_per_million_input=5.0,
|
|
403
|
+
cost_per_million_output=5.0,
|
|
404
|
+
swe_score=58.1,
|
|
405
|
+
available=True,
|
|
406
|
+
supports_tools=True,
|
|
407
|
+
supports_multimodal=False,
|
|
408
|
+
latest_version=True,
|
|
409
|
+
context_window=127072,
|
|
410
|
+
is_free=False,
|
|
411
|
+
release_date=datetime(2024, 7, 1),
|
|
412
|
+
),
|
|
413
|
+
EnhancedModelInfo(
|
|
414
|
+
name="llama-3.1-sonar-small-128k-chat",
|
|
415
|
+
provider="perplexity",
|
|
416
|
+
description="Llama 3.1 Sonar Small for chat without search",
|
|
417
|
+
max_tokens=127072,
|
|
418
|
+
cost_per_million_input=0.2,
|
|
419
|
+
cost_per_million_output=0.2,
|
|
420
|
+
swe_score=45.2,
|
|
421
|
+
available=True,
|
|
422
|
+
supports_tools=False,
|
|
423
|
+
supports_multimodal=False,
|
|
424
|
+
context_window=127072,
|
|
425
|
+
is_free=False,
|
|
426
|
+
release_date=datetime(2024, 7, 1),
|
|
427
|
+
),
|
|
428
|
+
EnhancedModelInfo(
|
|
429
|
+
name="llama-3.1-sonar-large-128k-chat",
|
|
430
|
+
provider="perplexity",
|
|
431
|
+
description="Llama 3.1 Sonar Large for chat without search",
|
|
432
|
+
max_tokens=127072,
|
|
433
|
+
cost_per_million_input=1.0,
|
|
434
|
+
cost_per_million_output=1.0,
|
|
435
|
+
swe_score=52.4,
|
|
436
|
+
available=True,
|
|
437
|
+
supports_tools=False,
|
|
438
|
+
supports_multimodal=False,
|
|
439
|
+
context_window=127072,
|
|
440
|
+
is_free=False,
|
|
441
|
+
release_date=datetime(2024, 7, 1),
|
|
442
|
+
),
|
|
443
|
+
]
|
|
444
|
+
|
|
445
|
+
# Update SWE ratings for all models
|
|
446
|
+
for model in models:
|
|
447
|
+
model.update_swe_rating()
|
|
448
|
+
|
|
449
|
+
return models
|
|
450
|
+
|
|
451
|
+
def supports_tools(self) -> bool:
|
|
452
|
+
"""
|
|
453
|
+
Check if Perplexity provider supports tool calling.
|
|
454
|
+
|
|
455
|
+
Returns:
|
|
456
|
+
True for online models that support search tools
|
|
457
|
+
"""
|
|
458
|
+
return self._is_online_model()
|
|
459
|
+
|
|
460
|
+
def supports_multimodal(self) -> bool:
|
|
461
|
+
"""
|
|
462
|
+
Check if Perplexity provider supports multimodal inputs.
|
|
463
|
+
|
|
464
|
+
Returns:
|
|
465
|
+
False - Current Perplexity models don't support multimodal inputs
|
|
466
|
+
"""
|
|
467
|
+
return False
|
|
468
|
+
|
|
469
|
+
def supports_streaming(self) -> bool:
|
|
470
|
+
"""
|
|
471
|
+
Check if Perplexity provider supports streaming responses.
|
|
472
|
+
|
|
473
|
+
Returns:
|
|
474
|
+
True - Perplexity supports streaming
|
|
475
|
+
"""
|
|
476
|
+
return True
|