PraisonAI 3.0.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.
- praisonai/__init__.py +54 -0
- praisonai/__main__.py +15 -0
- praisonai/acp/__init__.py +54 -0
- praisonai/acp/config.py +159 -0
- praisonai/acp/server.py +587 -0
- praisonai/acp/session.py +219 -0
- praisonai/adapters/__init__.py +50 -0
- praisonai/adapters/readers.py +395 -0
- praisonai/adapters/rerankers.py +315 -0
- praisonai/adapters/retrievers.py +394 -0
- praisonai/adapters/vector_stores.py +409 -0
- praisonai/agent_scheduler.py +337 -0
- praisonai/agents_generator.py +903 -0
- praisonai/api/call.py +292 -0
- praisonai/auto.py +1197 -0
- praisonai/capabilities/__init__.py +275 -0
- praisonai/capabilities/a2a.py +140 -0
- praisonai/capabilities/assistants.py +283 -0
- praisonai/capabilities/audio.py +320 -0
- praisonai/capabilities/batches.py +469 -0
- praisonai/capabilities/completions.py +336 -0
- praisonai/capabilities/container_files.py +155 -0
- praisonai/capabilities/containers.py +93 -0
- praisonai/capabilities/embeddings.py +158 -0
- praisonai/capabilities/files.py +467 -0
- praisonai/capabilities/fine_tuning.py +293 -0
- praisonai/capabilities/guardrails.py +182 -0
- praisonai/capabilities/images.py +330 -0
- praisonai/capabilities/mcp.py +190 -0
- praisonai/capabilities/messages.py +270 -0
- praisonai/capabilities/moderations.py +154 -0
- praisonai/capabilities/ocr.py +217 -0
- praisonai/capabilities/passthrough.py +204 -0
- praisonai/capabilities/rag.py +207 -0
- praisonai/capabilities/realtime.py +160 -0
- praisonai/capabilities/rerank.py +165 -0
- praisonai/capabilities/responses.py +266 -0
- praisonai/capabilities/search.py +109 -0
- praisonai/capabilities/skills.py +133 -0
- praisonai/capabilities/vector_store_files.py +334 -0
- praisonai/capabilities/vector_stores.py +304 -0
- praisonai/capabilities/videos.py +141 -0
- praisonai/chainlit_ui.py +304 -0
- praisonai/chat/__init__.py +106 -0
- praisonai/chat/app.py +125 -0
- praisonai/cli/__init__.py +26 -0
- praisonai/cli/app.py +213 -0
- praisonai/cli/commands/__init__.py +75 -0
- praisonai/cli/commands/acp.py +70 -0
- praisonai/cli/commands/completion.py +333 -0
- praisonai/cli/commands/config.py +166 -0
- praisonai/cli/commands/debug.py +142 -0
- praisonai/cli/commands/diag.py +55 -0
- praisonai/cli/commands/doctor.py +166 -0
- praisonai/cli/commands/environment.py +179 -0
- praisonai/cli/commands/lsp.py +112 -0
- praisonai/cli/commands/mcp.py +210 -0
- praisonai/cli/commands/profile.py +457 -0
- praisonai/cli/commands/run.py +228 -0
- praisonai/cli/commands/schedule.py +150 -0
- praisonai/cli/commands/serve.py +97 -0
- praisonai/cli/commands/session.py +212 -0
- praisonai/cli/commands/traces.py +145 -0
- praisonai/cli/commands/version.py +101 -0
- praisonai/cli/configuration/__init__.py +18 -0
- praisonai/cli/configuration/loader.py +353 -0
- praisonai/cli/configuration/paths.py +114 -0
- praisonai/cli/configuration/schema.py +164 -0
- praisonai/cli/features/__init__.py +268 -0
- praisonai/cli/features/acp.py +236 -0
- praisonai/cli/features/action_orchestrator.py +546 -0
- praisonai/cli/features/agent_scheduler.py +773 -0
- praisonai/cli/features/agent_tools.py +474 -0
- praisonai/cli/features/agents.py +375 -0
- praisonai/cli/features/at_mentions.py +471 -0
- praisonai/cli/features/auto_memory.py +182 -0
- praisonai/cli/features/autonomy_mode.py +490 -0
- praisonai/cli/features/background.py +356 -0
- praisonai/cli/features/base.py +168 -0
- praisonai/cli/features/capabilities.py +1326 -0
- praisonai/cli/features/checkpoints.py +338 -0
- praisonai/cli/features/code_intelligence.py +652 -0
- praisonai/cli/features/compaction.py +294 -0
- praisonai/cli/features/compare.py +534 -0
- praisonai/cli/features/cost_tracker.py +514 -0
- praisonai/cli/features/debug.py +810 -0
- praisonai/cli/features/deploy.py +517 -0
- praisonai/cli/features/diag.py +289 -0
- praisonai/cli/features/doctor/__init__.py +63 -0
- praisonai/cli/features/doctor/checks/__init__.py +24 -0
- praisonai/cli/features/doctor/checks/acp_checks.py +240 -0
- praisonai/cli/features/doctor/checks/config_checks.py +366 -0
- praisonai/cli/features/doctor/checks/db_checks.py +366 -0
- praisonai/cli/features/doctor/checks/env_checks.py +543 -0
- praisonai/cli/features/doctor/checks/lsp_checks.py +199 -0
- praisonai/cli/features/doctor/checks/mcp_checks.py +349 -0
- praisonai/cli/features/doctor/checks/memory_checks.py +268 -0
- praisonai/cli/features/doctor/checks/network_checks.py +251 -0
- praisonai/cli/features/doctor/checks/obs_checks.py +328 -0
- praisonai/cli/features/doctor/checks/performance_checks.py +235 -0
- praisonai/cli/features/doctor/checks/permissions_checks.py +259 -0
- praisonai/cli/features/doctor/checks/selftest_checks.py +322 -0
- praisonai/cli/features/doctor/checks/serve_checks.py +426 -0
- praisonai/cli/features/doctor/checks/skills_checks.py +231 -0
- praisonai/cli/features/doctor/checks/tools_checks.py +371 -0
- praisonai/cli/features/doctor/engine.py +266 -0
- praisonai/cli/features/doctor/formatters.py +310 -0
- praisonai/cli/features/doctor/handler.py +397 -0
- praisonai/cli/features/doctor/models.py +264 -0
- praisonai/cli/features/doctor/registry.py +239 -0
- praisonai/cli/features/endpoints.py +1019 -0
- praisonai/cli/features/eval.py +560 -0
- praisonai/cli/features/external_agents.py +231 -0
- praisonai/cli/features/fast_context.py +410 -0
- praisonai/cli/features/flow_display.py +566 -0
- praisonai/cli/features/git_integration.py +651 -0
- praisonai/cli/features/guardrail.py +171 -0
- praisonai/cli/features/handoff.py +185 -0
- praisonai/cli/features/hooks.py +583 -0
- praisonai/cli/features/image.py +384 -0
- praisonai/cli/features/interactive_runtime.py +585 -0
- praisonai/cli/features/interactive_tools.py +380 -0
- praisonai/cli/features/interactive_tui.py +603 -0
- praisonai/cli/features/jobs.py +632 -0
- praisonai/cli/features/knowledge.py +531 -0
- praisonai/cli/features/lite.py +244 -0
- praisonai/cli/features/lsp_cli.py +225 -0
- praisonai/cli/features/mcp.py +169 -0
- praisonai/cli/features/message_queue.py +587 -0
- praisonai/cli/features/metrics.py +211 -0
- praisonai/cli/features/n8n.py +673 -0
- praisonai/cli/features/observability.py +293 -0
- praisonai/cli/features/ollama.py +361 -0
- praisonai/cli/features/output_style.py +273 -0
- praisonai/cli/features/package.py +631 -0
- praisonai/cli/features/performance.py +308 -0
- praisonai/cli/features/persistence.py +636 -0
- praisonai/cli/features/profile.py +226 -0
- praisonai/cli/features/profiler/__init__.py +81 -0
- praisonai/cli/features/profiler/core.py +558 -0
- praisonai/cli/features/profiler/optimizations.py +652 -0
- praisonai/cli/features/profiler/suite.py +386 -0
- praisonai/cli/features/profiling.py +350 -0
- praisonai/cli/features/queue/__init__.py +73 -0
- praisonai/cli/features/queue/manager.py +395 -0
- praisonai/cli/features/queue/models.py +286 -0
- praisonai/cli/features/queue/persistence.py +564 -0
- praisonai/cli/features/queue/scheduler.py +484 -0
- praisonai/cli/features/queue/worker.py +372 -0
- praisonai/cli/features/recipe.py +1723 -0
- praisonai/cli/features/recipes.py +449 -0
- praisonai/cli/features/registry.py +229 -0
- praisonai/cli/features/repo_map.py +860 -0
- praisonai/cli/features/router.py +466 -0
- praisonai/cli/features/sandbox_executor.py +515 -0
- praisonai/cli/features/serve.py +829 -0
- praisonai/cli/features/session.py +222 -0
- praisonai/cli/features/skills.py +856 -0
- praisonai/cli/features/slash_commands.py +650 -0
- praisonai/cli/features/telemetry.py +179 -0
- praisonai/cli/features/templates.py +1384 -0
- praisonai/cli/features/thinking.py +305 -0
- praisonai/cli/features/todo.py +334 -0
- praisonai/cli/features/tools.py +680 -0
- praisonai/cli/features/tui/__init__.py +83 -0
- praisonai/cli/features/tui/app.py +580 -0
- praisonai/cli/features/tui/cli.py +566 -0
- praisonai/cli/features/tui/debug.py +511 -0
- praisonai/cli/features/tui/events.py +99 -0
- praisonai/cli/features/tui/mock_provider.py +328 -0
- praisonai/cli/features/tui/orchestrator.py +652 -0
- praisonai/cli/features/tui/screens/__init__.py +50 -0
- praisonai/cli/features/tui/screens/main.py +245 -0
- praisonai/cli/features/tui/screens/queue.py +174 -0
- praisonai/cli/features/tui/screens/session.py +124 -0
- praisonai/cli/features/tui/screens/settings.py +148 -0
- praisonai/cli/features/tui/widgets/__init__.py +56 -0
- praisonai/cli/features/tui/widgets/chat.py +261 -0
- praisonai/cli/features/tui/widgets/composer.py +224 -0
- praisonai/cli/features/tui/widgets/queue_panel.py +200 -0
- praisonai/cli/features/tui/widgets/status.py +167 -0
- praisonai/cli/features/tui/widgets/tool_panel.py +248 -0
- praisonai/cli/features/workflow.py +720 -0
- praisonai/cli/legacy.py +236 -0
- praisonai/cli/main.py +5559 -0
- praisonai/cli/schedule_cli.py +54 -0
- praisonai/cli/state/__init__.py +31 -0
- praisonai/cli/state/identifiers.py +161 -0
- praisonai/cli/state/sessions.py +313 -0
- praisonai/code/__init__.py +93 -0
- praisonai/code/agent_tools.py +344 -0
- praisonai/code/diff/__init__.py +21 -0
- praisonai/code/diff/diff_strategy.py +432 -0
- praisonai/code/tools/__init__.py +27 -0
- praisonai/code/tools/apply_diff.py +221 -0
- praisonai/code/tools/execute_command.py +275 -0
- praisonai/code/tools/list_files.py +274 -0
- praisonai/code/tools/read_file.py +206 -0
- praisonai/code/tools/search_replace.py +248 -0
- praisonai/code/tools/write_file.py +217 -0
- praisonai/code/utils/__init__.py +46 -0
- praisonai/code/utils/file_utils.py +307 -0
- praisonai/code/utils/ignore_utils.py +308 -0
- praisonai/code/utils/text_utils.py +276 -0
- praisonai/db/__init__.py +64 -0
- praisonai/db/adapter.py +531 -0
- praisonai/deploy/__init__.py +62 -0
- praisonai/deploy/api.py +231 -0
- praisonai/deploy/docker.py +454 -0
- praisonai/deploy/doctor.py +367 -0
- praisonai/deploy/main.py +327 -0
- praisonai/deploy/models.py +179 -0
- praisonai/deploy/providers/__init__.py +33 -0
- praisonai/deploy/providers/aws.py +331 -0
- praisonai/deploy/providers/azure.py +358 -0
- praisonai/deploy/providers/base.py +101 -0
- praisonai/deploy/providers/gcp.py +314 -0
- praisonai/deploy/schema.py +208 -0
- praisonai/deploy.py +185 -0
- praisonai/endpoints/__init__.py +53 -0
- praisonai/endpoints/a2u_server.py +410 -0
- praisonai/endpoints/discovery.py +165 -0
- praisonai/endpoints/providers/__init__.py +28 -0
- praisonai/endpoints/providers/a2a.py +253 -0
- praisonai/endpoints/providers/a2u.py +208 -0
- praisonai/endpoints/providers/agents_api.py +171 -0
- praisonai/endpoints/providers/base.py +231 -0
- praisonai/endpoints/providers/mcp.py +263 -0
- praisonai/endpoints/providers/recipe.py +206 -0
- praisonai/endpoints/providers/tools_mcp.py +150 -0
- praisonai/endpoints/registry.py +131 -0
- praisonai/endpoints/server.py +161 -0
- praisonai/inbuilt_tools/__init__.py +24 -0
- praisonai/inbuilt_tools/autogen_tools.py +117 -0
- praisonai/inc/__init__.py +2 -0
- praisonai/inc/config.py +96 -0
- praisonai/inc/models.py +155 -0
- praisonai/integrations/__init__.py +56 -0
- praisonai/integrations/base.py +303 -0
- praisonai/integrations/claude_code.py +270 -0
- praisonai/integrations/codex_cli.py +255 -0
- praisonai/integrations/cursor_cli.py +195 -0
- praisonai/integrations/gemini_cli.py +222 -0
- praisonai/jobs/__init__.py +67 -0
- praisonai/jobs/executor.py +425 -0
- praisonai/jobs/models.py +230 -0
- praisonai/jobs/router.py +314 -0
- praisonai/jobs/server.py +186 -0
- praisonai/jobs/store.py +203 -0
- praisonai/llm/__init__.py +66 -0
- praisonai/llm/registry.py +382 -0
- praisonai/mcp_server/__init__.py +152 -0
- praisonai/mcp_server/adapters/__init__.py +74 -0
- praisonai/mcp_server/adapters/agents.py +128 -0
- praisonai/mcp_server/adapters/capabilities.py +168 -0
- praisonai/mcp_server/adapters/cli_tools.py +568 -0
- praisonai/mcp_server/adapters/extended_capabilities.py +462 -0
- praisonai/mcp_server/adapters/knowledge.py +93 -0
- praisonai/mcp_server/adapters/memory.py +104 -0
- praisonai/mcp_server/adapters/prompts.py +306 -0
- praisonai/mcp_server/adapters/resources.py +124 -0
- praisonai/mcp_server/adapters/tools_bridge.py +280 -0
- praisonai/mcp_server/auth/__init__.py +48 -0
- praisonai/mcp_server/auth/api_key.py +291 -0
- praisonai/mcp_server/auth/oauth.py +460 -0
- praisonai/mcp_server/auth/oidc.py +289 -0
- praisonai/mcp_server/auth/scopes.py +260 -0
- praisonai/mcp_server/cli.py +852 -0
- praisonai/mcp_server/elicitation.py +445 -0
- praisonai/mcp_server/icons.py +302 -0
- praisonai/mcp_server/recipe_adapter.py +573 -0
- praisonai/mcp_server/recipe_cli.py +824 -0
- praisonai/mcp_server/registry.py +703 -0
- praisonai/mcp_server/sampling.py +422 -0
- praisonai/mcp_server/server.py +490 -0
- praisonai/mcp_server/tasks.py +443 -0
- praisonai/mcp_server/transports/__init__.py +18 -0
- praisonai/mcp_server/transports/http_stream.py +376 -0
- praisonai/mcp_server/transports/stdio.py +132 -0
- praisonai/persistence/__init__.py +84 -0
- praisonai/persistence/config.py +238 -0
- praisonai/persistence/conversation/__init__.py +25 -0
- praisonai/persistence/conversation/async_mysql.py +427 -0
- praisonai/persistence/conversation/async_postgres.py +410 -0
- praisonai/persistence/conversation/async_sqlite.py +371 -0
- praisonai/persistence/conversation/base.py +151 -0
- praisonai/persistence/conversation/json_store.py +250 -0
- praisonai/persistence/conversation/mysql.py +387 -0
- praisonai/persistence/conversation/postgres.py +401 -0
- praisonai/persistence/conversation/singlestore.py +240 -0
- praisonai/persistence/conversation/sqlite.py +341 -0
- praisonai/persistence/conversation/supabase.py +203 -0
- praisonai/persistence/conversation/surrealdb.py +287 -0
- praisonai/persistence/factory.py +301 -0
- praisonai/persistence/hooks/__init__.py +18 -0
- praisonai/persistence/hooks/agent_hooks.py +297 -0
- praisonai/persistence/knowledge/__init__.py +26 -0
- praisonai/persistence/knowledge/base.py +144 -0
- praisonai/persistence/knowledge/cassandra.py +232 -0
- praisonai/persistence/knowledge/chroma.py +295 -0
- praisonai/persistence/knowledge/clickhouse.py +242 -0
- praisonai/persistence/knowledge/cosmosdb_vector.py +438 -0
- praisonai/persistence/knowledge/couchbase.py +286 -0
- praisonai/persistence/knowledge/lancedb.py +216 -0
- praisonai/persistence/knowledge/langchain_adapter.py +291 -0
- praisonai/persistence/knowledge/lightrag_adapter.py +212 -0
- praisonai/persistence/knowledge/llamaindex_adapter.py +256 -0
- praisonai/persistence/knowledge/milvus.py +277 -0
- praisonai/persistence/knowledge/mongodb_vector.py +306 -0
- praisonai/persistence/knowledge/pgvector.py +335 -0
- praisonai/persistence/knowledge/pinecone.py +253 -0
- praisonai/persistence/knowledge/qdrant.py +301 -0
- praisonai/persistence/knowledge/redis_vector.py +291 -0
- praisonai/persistence/knowledge/singlestore_vector.py +299 -0
- praisonai/persistence/knowledge/surrealdb_vector.py +309 -0
- praisonai/persistence/knowledge/upstash_vector.py +266 -0
- praisonai/persistence/knowledge/weaviate.py +223 -0
- praisonai/persistence/migrations/__init__.py +10 -0
- praisonai/persistence/migrations/manager.py +251 -0
- praisonai/persistence/orchestrator.py +406 -0
- praisonai/persistence/state/__init__.py +21 -0
- praisonai/persistence/state/async_mongodb.py +200 -0
- praisonai/persistence/state/base.py +107 -0
- praisonai/persistence/state/dynamodb.py +226 -0
- praisonai/persistence/state/firestore.py +175 -0
- praisonai/persistence/state/gcs.py +155 -0
- praisonai/persistence/state/memory.py +245 -0
- praisonai/persistence/state/mongodb.py +158 -0
- praisonai/persistence/state/redis.py +190 -0
- praisonai/persistence/state/upstash.py +144 -0
- praisonai/persistence/tests/__init__.py +3 -0
- praisonai/persistence/tests/test_all_backends.py +633 -0
- praisonai/profiler.py +1214 -0
- praisonai/recipe/__init__.py +134 -0
- praisonai/recipe/bridge.py +278 -0
- praisonai/recipe/core.py +893 -0
- praisonai/recipe/exceptions.py +54 -0
- praisonai/recipe/history.py +402 -0
- praisonai/recipe/models.py +266 -0
- praisonai/recipe/operations.py +440 -0
- praisonai/recipe/policy.py +422 -0
- praisonai/recipe/registry.py +849 -0
- praisonai/recipe/runtime.py +214 -0
- praisonai/recipe/security.py +711 -0
- praisonai/recipe/serve.py +859 -0
- praisonai/recipe/server.py +613 -0
- praisonai/scheduler/__init__.py +45 -0
- praisonai/scheduler/agent_scheduler.py +552 -0
- praisonai/scheduler/base.py +124 -0
- praisonai/scheduler/daemon_manager.py +225 -0
- praisonai/scheduler/state_manager.py +155 -0
- praisonai/scheduler/yaml_loader.py +193 -0
- praisonai/scheduler.py +194 -0
- praisonai/setup/__init__.py +1 -0
- praisonai/setup/build.py +21 -0
- praisonai/setup/post_install.py +23 -0
- praisonai/setup/setup_conda_env.py +25 -0
- praisonai/setup.py +16 -0
- praisonai/templates/__init__.py +116 -0
- praisonai/templates/cache.py +364 -0
- praisonai/templates/dependency_checker.py +358 -0
- praisonai/templates/discovery.py +391 -0
- praisonai/templates/loader.py +564 -0
- praisonai/templates/registry.py +511 -0
- praisonai/templates/resolver.py +206 -0
- praisonai/templates/security.py +327 -0
- praisonai/templates/tool_override.py +498 -0
- praisonai/templates/tools_doctor.py +256 -0
- praisonai/test.py +105 -0
- praisonai/train.py +562 -0
- praisonai/train_vision.py +306 -0
- praisonai/ui/agents.py +824 -0
- praisonai/ui/callbacks.py +57 -0
- praisonai/ui/chainlit_compat.py +246 -0
- praisonai/ui/chat.py +532 -0
- praisonai/ui/code.py +717 -0
- praisonai/ui/colab.py +474 -0
- praisonai/ui/colab_chainlit.py +81 -0
- praisonai/ui/components/aicoder.py +284 -0
- praisonai/ui/context.py +283 -0
- praisonai/ui/database_config.py +56 -0
- praisonai/ui/db.py +294 -0
- praisonai/ui/realtime.py +488 -0
- praisonai/ui/realtimeclient/__init__.py +756 -0
- praisonai/ui/realtimeclient/tools.py +242 -0
- praisonai/ui/sql_alchemy.py +710 -0
- praisonai/upload_vision.py +140 -0
- praisonai/version.py +1 -0
- praisonai-3.0.0.dist-info/METADATA +3493 -0
- praisonai-3.0.0.dist-info/RECORD +393 -0
- praisonai-3.0.0.dist-info/WHEEL +5 -0
- praisonai-3.0.0.dist-info/entry_points.txt +4 -0
- praisonai-3.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Image Handler for CLI.
|
|
3
|
+
|
|
4
|
+
Provides two distinct image capabilities:
|
|
5
|
+
1. Image Description (Vision) - Analyze existing images using vision-capable LLMs
|
|
6
|
+
Usage: praisonai "Describe this image" --image path/to/image.png
|
|
7
|
+
|
|
8
|
+
2. Image Generation - Generate new images from text prompts
|
|
9
|
+
Usage: praisonai "A sunset over mountains" --image-generate
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
import base64
|
|
14
|
+
import logging
|
|
15
|
+
from typing import Any, Dict, Tuple, List, Optional
|
|
16
|
+
from .base import FlagHandler
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
# Supported image extensions for vision/description
|
|
21
|
+
SUPPORTED_EXTENSIONS = {'.png', '.jpg', '.jpeg', '.gif', '.webp', '.bmp', '.svg', '.tiff'}
|
|
22
|
+
|
|
23
|
+
# Default vision-capable models (gpt-4o has better vision support than gpt-4o-mini)
|
|
24
|
+
DEFAULT_VISION_MODEL = "gpt-4o"
|
|
25
|
+
|
|
26
|
+
# Default image generation models
|
|
27
|
+
DEFAULT_IMAGE_GEN_MODEL = "dall-e-3"
|
|
28
|
+
SUPPORTED_IMAGE_GEN_MODELS = [
|
|
29
|
+
'gpt-image-1', 'gpt-image-1-mini', 'gpt-image-1.5',
|
|
30
|
+
'chatgpt-image-latest', 'dall-e-2', 'dall-e-3'
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ImageHandler(FlagHandler):
|
|
35
|
+
"""
|
|
36
|
+
Handler for --image flag (Image Description/Vision).
|
|
37
|
+
|
|
38
|
+
Describes/analyzes existing images using vision-capable LLMs like GPT-4o.
|
|
39
|
+
This is for understanding what's IN an image, not generating new images.
|
|
40
|
+
|
|
41
|
+
Example:
|
|
42
|
+
praisonai "Describe this image" --image photo.png
|
|
43
|
+
praisonai "What's in this image?" --image /path/to/image.jpg
|
|
44
|
+
praisonai "Count the objects" --image image1.png,image2.png
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def feature_name(self) -> str:
|
|
49
|
+
return "image"
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def flag_name(self) -> str:
|
|
53
|
+
return "image"
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def flag_help(self) -> str:
|
|
57
|
+
return "Path to image file for vision-based description/analysis"
|
|
58
|
+
|
|
59
|
+
def check_dependencies(self) -> Tuple[bool, str]:
|
|
60
|
+
"""Check if litellm is available for vision."""
|
|
61
|
+
try:
|
|
62
|
+
import litellm
|
|
63
|
+
return True, ""
|
|
64
|
+
except ImportError:
|
|
65
|
+
return False, "litellm not installed. Install with: pip install litellm"
|
|
66
|
+
|
|
67
|
+
def validate_image_path(self, path: str) -> Tuple[bool, str]:
|
|
68
|
+
"""
|
|
69
|
+
Validate that the image path is valid.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
path: Path to the image file
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
Tuple of (is_valid, error_message)
|
|
76
|
+
"""
|
|
77
|
+
if not path:
|
|
78
|
+
return False, "No image path provided"
|
|
79
|
+
|
|
80
|
+
# Check extension
|
|
81
|
+
ext = os.path.splitext(path)[1].lower()
|
|
82
|
+
if ext not in SUPPORTED_EXTENSIONS:
|
|
83
|
+
return False, f"Unsupported image format: {ext}. Supported: {', '.join(SUPPORTED_EXTENSIONS)}"
|
|
84
|
+
|
|
85
|
+
# Check if file exists (for local files)
|
|
86
|
+
if not path.startswith(('http://', 'https://')):
|
|
87
|
+
if not os.path.exists(path):
|
|
88
|
+
return False, f"Image file not found: {path}"
|
|
89
|
+
|
|
90
|
+
return True, ""
|
|
91
|
+
|
|
92
|
+
def _encode_image_to_base64(self, image_path: str) -> str:
|
|
93
|
+
"""Encode a local image file to base64."""
|
|
94
|
+
with open(image_path, 'rb') as f:
|
|
95
|
+
return base64.b64encode(f.read()).decode('utf-8')
|
|
96
|
+
|
|
97
|
+
def _get_image_mime_type(self, image_path: str) -> str:
|
|
98
|
+
"""Get MIME type based on file extension."""
|
|
99
|
+
ext = os.path.splitext(image_path)[1].lower()
|
|
100
|
+
mime_types = {
|
|
101
|
+
'.png': 'image/png',
|
|
102
|
+
'.jpg': 'image/jpeg',
|
|
103
|
+
'.jpeg': 'image/jpeg',
|
|
104
|
+
'.gif': 'image/gif',
|
|
105
|
+
'.webp': 'image/webp',
|
|
106
|
+
'.bmp': 'image/bmp',
|
|
107
|
+
'.svg': 'image/svg+xml',
|
|
108
|
+
'.tiff': 'image/tiff',
|
|
109
|
+
}
|
|
110
|
+
return mime_types.get(ext, 'image/png')
|
|
111
|
+
|
|
112
|
+
def _build_image_content(self, image_path: str) -> Dict[str, Any]:
|
|
113
|
+
"""Build image content for vision API."""
|
|
114
|
+
if image_path.startswith(('http://', 'https://')):
|
|
115
|
+
return {
|
|
116
|
+
"type": "image_url",
|
|
117
|
+
"image_url": {"url": image_path}
|
|
118
|
+
}
|
|
119
|
+
else:
|
|
120
|
+
mime_type = self._get_image_mime_type(image_path)
|
|
121
|
+
base64_data = self._encode_image_to_base64(image_path)
|
|
122
|
+
return {
|
|
123
|
+
"type": "image_url",
|
|
124
|
+
"image_url": {"url": f"data:{mime_type};base64,{base64_data}"}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
def apply_to_agent_config(self, config: Dict[str, Any], flag_value: Any) -> Dict[str, Any]:
|
|
128
|
+
"""Apply image configuration to agent config."""
|
|
129
|
+
if flag_value:
|
|
130
|
+
if isinstance(flag_value, str):
|
|
131
|
+
config["images"] = [flag_value]
|
|
132
|
+
elif isinstance(flag_value, list):
|
|
133
|
+
config["images"] = flag_value
|
|
134
|
+
config["use_vision"] = True
|
|
135
|
+
return config
|
|
136
|
+
|
|
137
|
+
def describe_image(self, prompt: str, image_path: str, llm = None) -> str:
|
|
138
|
+
"""
|
|
139
|
+
Describe an image using vision-capable LLM.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
prompt: The prompt/question about the image
|
|
143
|
+
image_path: Path to the image file
|
|
144
|
+
llm: Optional LLM model name (must be vision-capable), can be string or dict
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
Description of the image
|
|
148
|
+
"""
|
|
149
|
+
valid, msg = self.validate_image_path(image_path)
|
|
150
|
+
if not valid:
|
|
151
|
+
return f"Error: {msg}"
|
|
152
|
+
|
|
153
|
+
available, dep_msg = self.check_dependencies()
|
|
154
|
+
if not available:
|
|
155
|
+
return f"Error: {dep_msg}"
|
|
156
|
+
|
|
157
|
+
import litellm
|
|
158
|
+
|
|
159
|
+
# Handle llm being a dict (from agent_config) or string
|
|
160
|
+
if isinstance(llm, dict):
|
|
161
|
+
model = llm.get('model', DEFAULT_VISION_MODEL)
|
|
162
|
+
else:
|
|
163
|
+
model = llm or DEFAULT_VISION_MODEL
|
|
164
|
+
|
|
165
|
+
try:
|
|
166
|
+
# Build message with image
|
|
167
|
+
content = [
|
|
168
|
+
{"type": "text", "text": prompt},
|
|
169
|
+
self._build_image_content(image_path)
|
|
170
|
+
]
|
|
171
|
+
|
|
172
|
+
response = litellm.completion(
|
|
173
|
+
model=model,
|
|
174
|
+
messages=[{"role": "user", "content": content}]
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
return response.choices[0].message.content
|
|
178
|
+
|
|
179
|
+
except Exception as e:
|
|
180
|
+
logger.error(f"Error describing image: {e}")
|
|
181
|
+
return f"Error describing image: {e}"
|
|
182
|
+
|
|
183
|
+
def describe_multiple_images(self, prompt: str, image_paths: List[str], llm = None) -> str:
|
|
184
|
+
"""
|
|
185
|
+
Describe multiple images using vision-capable LLM.
|
|
186
|
+
|
|
187
|
+
Args:
|
|
188
|
+
prompt: The prompt/question about the images
|
|
189
|
+
image_paths: List of paths to image files
|
|
190
|
+
llm: Optional LLM model name, can be string or dict
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
Description of the images
|
|
194
|
+
"""
|
|
195
|
+
for path in image_paths:
|
|
196
|
+
valid, msg = self.validate_image_path(path)
|
|
197
|
+
if not valid:
|
|
198
|
+
return f"Error: {msg}"
|
|
199
|
+
|
|
200
|
+
available, dep_msg = self.check_dependencies()
|
|
201
|
+
if not available:
|
|
202
|
+
return f"Error: {dep_msg}"
|
|
203
|
+
|
|
204
|
+
import litellm
|
|
205
|
+
|
|
206
|
+
# Handle llm being a dict (from agent_config) or string
|
|
207
|
+
if isinstance(llm, dict):
|
|
208
|
+
model = llm.get('model', DEFAULT_VISION_MODEL)
|
|
209
|
+
else:
|
|
210
|
+
model = llm or DEFAULT_VISION_MODEL
|
|
211
|
+
|
|
212
|
+
try:
|
|
213
|
+
# Build message with all images
|
|
214
|
+
content = [{"type": "text", "text": prompt}]
|
|
215
|
+
for path in image_paths:
|
|
216
|
+
content.append(self._build_image_content(path))
|
|
217
|
+
|
|
218
|
+
response = litellm.completion(
|
|
219
|
+
model=model,
|
|
220
|
+
messages=[{"role": "user", "content": content}]
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
return response.choices[0].message.content
|
|
224
|
+
|
|
225
|
+
except Exception as e:
|
|
226
|
+
logger.error(f"Error describing images: {e}")
|
|
227
|
+
return f"Error describing images: {e}"
|
|
228
|
+
|
|
229
|
+
def execute(self, prompt: str = None, image_path: str = None, llm: str = None, **kwargs) -> str:
|
|
230
|
+
"""
|
|
231
|
+
Execute image description (vision).
|
|
232
|
+
|
|
233
|
+
Args:
|
|
234
|
+
prompt: The prompt/question about the image
|
|
235
|
+
image_path: Path to the image file (or comma-separated paths)
|
|
236
|
+
llm: Optional vision-capable LLM model name
|
|
237
|
+
|
|
238
|
+
Returns:
|
|
239
|
+
Description of the image(s)
|
|
240
|
+
"""
|
|
241
|
+
if not prompt:
|
|
242
|
+
return "Error: No prompt provided"
|
|
243
|
+
|
|
244
|
+
if not image_path:
|
|
245
|
+
return "Error: No image path provided"
|
|
246
|
+
|
|
247
|
+
# Handle multiple images (comma-separated)
|
|
248
|
+
if ',' in image_path:
|
|
249
|
+
paths = [p.strip() for p in image_path.split(',')]
|
|
250
|
+
return self.describe_multiple_images(prompt, paths, llm)
|
|
251
|
+
|
|
252
|
+
return self.describe_image(prompt, image_path, llm)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
class ImageGenerateHandler(FlagHandler):
|
|
256
|
+
"""
|
|
257
|
+
Handler for --image-generate flag (Image Generation).
|
|
258
|
+
|
|
259
|
+
Generates NEW images from text prompts using DALL-E or similar models.
|
|
260
|
+
This is for CREATING images, not analyzing existing ones.
|
|
261
|
+
|
|
262
|
+
Example:
|
|
263
|
+
praisonai "A sunset over mountains" --image-generate
|
|
264
|
+
praisonai "A cat wearing a hat" --image-generate --llm dall-e-3
|
|
265
|
+
"""
|
|
266
|
+
|
|
267
|
+
@property
|
|
268
|
+
def feature_name(self) -> str:
|
|
269
|
+
return "image_generate"
|
|
270
|
+
|
|
271
|
+
@property
|
|
272
|
+
def flag_name(self) -> str:
|
|
273
|
+
return "image_generate"
|
|
274
|
+
|
|
275
|
+
@property
|
|
276
|
+
def flag_help(self) -> str:
|
|
277
|
+
return "Generate an image from the text prompt"
|
|
278
|
+
|
|
279
|
+
def check_dependencies(self) -> Tuple[bool, str]:
|
|
280
|
+
"""Check if ImageAgent is available."""
|
|
281
|
+
try:
|
|
282
|
+
import importlib.util
|
|
283
|
+
if importlib.util.find_spec("praisonaiagents") is not None:
|
|
284
|
+
return True, ""
|
|
285
|
+
return False, "praisonaiagents not installed. Install with: pip install praisonaiagents"
|
|
286
|
+
except ImportError:
|
|
287
|
+
return False, "praisonaiagents not installed. Install with: pip install praisonaiagents"
|
|
288
|
+
|
|
289
|
+
def apply_to_agent_config(self, config: Dict[str, Any], flag_value: Any) -> Dict[str, Any]:
|
|
290
|
+
"""Apply image generation configuration."""
|
|
291
|
+
if flag_value:
|
|
292
|
+
config["use_image_generation"] = True
|
|
293
|
+
return config
|
|
294
|
+
|
|
295
|
+
def generate_image(self, prompt: str, llm: str = None, output_path: str = None) -> Dict[str, Any]:
|
|
296
|
+
"""
|
|
297
|
+
Generate an image from a text prompt.
|
|
298
|
+
|
|
299
|
+
Args:
|
|
300
|
+
prompt: Text description of the image to generate
|
|
301
|
+
llm: Image generation model (dall-e-3, dall-e-2, etc.)
|
|
302
|
+
output_path: Optional path to save the generated image
|
|
303
|
+
|
|
304
|
+
Returns:
|
|
305
|
+
Dict with image URL or path, or error message
|
|
306
|
+
"""
|
|
307
|
+
available, msg = self.check_dependencies()
|
|
308
|
+
if not available:
|
|
309
|
+
return {"error": msg}
|
|
310
|
+
|
|
311
|
+
from praisonaiagents import ImageAgent
|
|
312
|
+
|
|
313
|
+
# Use provided model or default
|
|
314
|
+
model = llm or DEFAULT_IMAGE_GEN_MODEL
|
|
315
|
+
|
|
316
|
+
# Validate model is supported for generation
|
|
317
|
+
if model not in SUPPORTED_IMAGE_GEN_MODELS:
|
|
318
|
+
return {
|
|
319
|
+
"error": f"Invalid model: '{model}'. Supported image generation models: {', '.join(SUPPORTED_IMAGE_GEN_MODELS)}"
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
try:
|
|
323
|
+
agent = ImageAgent(
|
|
324
|
+
name="ImageGenerator",
|
|
325
|
+
role="Image Generation Assistant",
|
|
326
|
+
goal="Generate high-quality images from text descriptions",
|
|
327
|
+
llm=model
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
result = agent.chat(prompt)
|
|
331
|
+
|
|
332
|
+
# Save image if output path provided
|
|
333
|
+
if output_path and isinstance(result, dict) and 'data' in result:
|
|
334
|
+
self._save_image(result, output_path)
|
|
335
|
+
result['saved_to'] = output_path
|
|
336
|
+
|
|
337
|
+
return result
|
|
338
|
+
|
|
339
|
+
except Exception as e:
|
|
340
|
+
logger.error(f"Error generating image: {e}")
|
|
341
|
+
return {"error": str(e)}
|
|
342
|
+
|
|
343
|
+
def _save_image(self, result: Dict[str, Any], output_path: str) -> bool:
|
|
344
|
+
"""Save generated image to file."""
|
|
345
|
+
try:
|
|
346
|
+
import requests
|
|
347
|
+
|
|
348
|
+
if 'data' in result and len(result['data']) > 0:
|
|
349
|
+
image_data = result['data'][0]
|
|
350
|
+
|
|
351
|
+
if 'url' in image_data:
|
|
352
|
+
# Download from URL
|
|
353
|
+
response = requests.get(image_data['url'])
|
|
354
|
+
with open(output_path, 'wb') as f:
|
|
355
|
+
f.write(response.content)
|
|
356
|
+
return True
|
|
357
|
+
elif 'b64_json' in image_data:
|
|
358
|
+
# Decode base64
|
|
359
|
+
import base64
|
|
360
|
+
img_bytes = base64.b64decode(image_data['b64_json'])
|
|
361
|
+
with open(output_path, 'wb') as f:
|
|
362
|
+
f.write(img_bytes)
|
|
363
|
+
return True
|
|
364
|
+
return False
|
|
365
|
+
except Exception as e:
|
|
366
|
+
logger.error(f"Error saving image: {e}")
|
|
367
|
+
return False
|
|
368
|
+
|
|
369
|
+
def execute(self, prompt: str = None, llm: str = None, output_path: str = None, **kwargs) -> Dict[str, Any]:
|
|
370
|
+
"""
|
|
371
|
+
Execute image generation.
|
|
372
|
+
|
|
373
|
+
Args:
|
|
374
|
+
prompt: Text description of the image to generate
|
|
375
|
+
llm: Image generation model name
|
|
376
|
+
output_path: Optional path to save the image
|
|
377
|
+
|
|
378
|
+
Returns:
|
|
379
|
+
Dict with generated image info or error
|
|
380
|
+
"""
|
|
381
|
+
if not prompt:
|
|
382
|
+
return {"error": "No prompt provided for image generation"}
|
|
383
|
+
|
|
384
|
+
return self.generate_image(prompt, llm, output_path)
|