prompture 1.0.55.dev2__tar.gz → 1.0.56.dev1__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.
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.env.copy +4 -1
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/PKG-INFO +25 -2
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/README.md +24 -1
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/_version.py +2 -2
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/__init__.py +37 -1
- prompture-1.0.56.dev1/prompture/drivers/async_grok_video_gen_driver.py +194 -0
- prompture-1.0.56.dev1/prompture/drivers/async_video_gen_base.py +78 -0
- prompture-1.0.56.dev1/prompture/drivers/grok_video_gen_driver.py +241 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/provider_descriptors.py +17 -2
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/registry.py +79 -0
- prompture-1.0.56.dev1/prompture/drivers/video_gen_base.py +94 -0
- prompture-1.0.56.dev1/prompture/drivers/video_gen_registry.py +33 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/__init__.py +4 -1
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/cost_mixin.py +42 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/discovery.py +38 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/provider_env.py +1 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/settings.py +2 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/media/__init__.py +17 -1
- prompture-1.0.56.dev1/prompture/media/video.py +191 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/persistence/serialization.py +4 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture.egg-info/PKG-INFO +25 -2
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture.egg-info/SOURCES.txt +6 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.claude/skills/add-driver/SKILL.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.claude/skills/add-driver/references/driver-template.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.claude/skills/add-example/SKILL.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.claude/skills/add-field/SKILL.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.claude/skills/add-persona/SKILL.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.claude/skills/add-test/SKILL.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.claude/skills/add-tool/SKILL.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.claude/skills/create-pr/SKILL.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.claude/skills/run-tests/SKILL.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.claude/skills/scaffold-extraction/SKILL.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.claude/skills/update-pricing/SKILL.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/FUNDING.yml +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/ISSUE_TEMPLATE/pricing_cost_mismatch.yml +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/ISSUE_TEMPLATE/provider_driver_bug.yml +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/ISSUE_TEMPLATE/schema_extraction_failure.yml +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/scripts/update_docs_version.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/scripts/update_wrapper_version.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/workflows/dev.yml +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/workflows/documentation.yml +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/workflows/pricing-freshness.yml +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/workflows/publish.yml +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.github/workflows/security.yml +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/.safety-project.ini +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/AGENTS.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/BREAKING_CHANGES.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/CLAUDE.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/CONTRIBUTING.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/LICENSE +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/MANIFEST.in +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/ROADMAP.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/SECURITY.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/dev.ps1 +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/dev.sh +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/mypy_errors.txt +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/packages/README.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/packages/llm_to_json/README.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/packages/llm_to_json/llm_to_json/__init__.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/packages/llm_to_json/pyproject.toml +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/packages/llm_to_json/test.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/packages/llm_to_toon/README.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/packages/llm_to_toon/llm_to_toon/__init__.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/packages/llm_to_toon/pyproject.toml +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/packages/llm_to_toon/test.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/__init__.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/agents/__init__.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/agents/agent.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/agents/async_agent.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/agents/async_conversation.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/agents/conversation.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/agents/persona.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/agents/simulated_tools.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/agents/skills.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/agents/tools_schema.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/agents/types.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/aio/__init__.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/bridges/__init__.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/bridges/tukuy_backend.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/cli/__init__.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/cli/cli.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/cli/formatters.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/cli/runner.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/cli/server.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/airllm_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_airllm_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_azure_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_base.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_cachibot_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_claude_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_elevenlabs_stt_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_elevenlabs_tts_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_embedding_base.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_google_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_google_img_gen_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_google_vertexai_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_grok_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_grok_img_gen_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_groq_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_hugging_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_img_gen_base.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_lmstudio_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_local_http_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_modelscope_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_moonshot_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_ollama_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_ollama_embedding_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_openai_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_openai_embedding_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_openai_img_gen_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_openai_stt_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_openai_tts_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_openrouter_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_registry.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_stability_img_gen_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_stt_base.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_tts_base.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/async_zai_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/audio_registry.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/azure_config.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/azure_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/base.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/cachibot_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/claude_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/driver_registry.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/elevenlabs_stt_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/elevenlabs_tts_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/embedding_base.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/embedding_registry.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/google_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/google_img_gen_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/google_vertexai_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/grok_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/grok_img_gen_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/groq_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/hugging_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/img_gen_base.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/img_gen_registry.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/lmstudio_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/local_http_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/modelscope_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/moonshot_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/ollama_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/ollama_embedding_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/openai_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/openai_embedding_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/openai_img_gen_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/openai_stt_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/openai_tts_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/openrouter_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/stability_img_gen_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/stt_base.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/tts_base.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/vision_helpers.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/drivers/zai_driver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/exceptions.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/extraction/__init__.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/extraction/async_core.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/extraction/core.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/extraction/fields.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/extraction/reasoning.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/extraction/strategy.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/extraction/tools.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/extraction/tukuy_bridge.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/extraction/validator.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/groups/__init__.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/groups/async_groups.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/groups/consensus.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/groups/debate.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/groups/groups.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/groups/types.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/budget.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/cache.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/callbacks.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/capabilities.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/ledger.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/logging.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/model_rates.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/pricing.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/rates/anthropic.json +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/rates/azure.json +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/rates/google.json +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/rates/google_vertexai.json +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/rates/groq.json +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/rates/moonshot.json +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/rates/openai.json +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/rates/openrouter.json +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/rates/xai.json +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/session.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/tracker.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/infra/tukuy_backend.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/__init__.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/chunking.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/detect.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/document.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/parsers/__init__.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/parsers/base.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/parsers/csv_parser.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/parsers/docx.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/parsers/html.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/parsers/markdown.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/parsers/pdf.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/ingestion/parsers/xlsx.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/integrations/__init__.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/integrations/tukuy_bridge.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/media/audio.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/media/image.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/pages/01-why-prompture.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/pages/02-installation.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/pages/03-quickstart.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/pages/04-toon-input.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/pages/05-test-harness.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/pages/06-stability.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/pages/07-migration.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/persistence/__init__.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/persistence/history.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/persistence/store.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/pipeline/__init__.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/pipeline/pipeline.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/pipeline/resolver.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/pipeline/routing.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/py.typed +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/scaffold/__init__.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/scaffold/generator.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/scaffold/templates/Dockerfile.j2 +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/scaffold/templates/README.md.j2 +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/scaffold/templates/config.py.j2 +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/scaffold/templates/env.example.j2 +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/scaffold/templates/main.py.j2 +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/scaffold/templates/models.py.j2 +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/scaffold/templates/requirements.txt.j2 +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/testing/__init__.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture/testing/driver_contract.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture.egg-info/dependency_links.txt +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture.egg-info/entry_points.txt +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture.egg-info/requires.txt +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture.egg-info/top_level.txt +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/prompture_cost_tracking.md +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/pyproject.toml +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/requirements.txt +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/scripts/check_pricing_freshness.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/setup.cfg +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/specs/basic_extraction.json +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/specs/schema_validation.json +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/specs/strategy_comparison.json +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/test.py +0 -0
- {prompture-1.0.55.dev2 → prompture-1.0.56.dev1}/test_version_diagnosis.py +0 -0
|
@@ -53,7 +53,10 @@ OPENROUTER_MODEL=openai/gpt-4o-mini
|
|
|
53
53
|
|
|
54
54
|
# ─── Grok (xAI) ─────────────────────────────────────────────────────────────
|
|
55
55
|
GROK_API_KEY=your-grok-api-key
|
|
56
|
+
# XAI_API_KEY is also supported for xAI docs compatibility.
|
|
57
|
+
XAI_API_KEY=
|
|
56
58
|
GROK_MODEL=grok-4-fast-reasoning
|
|
59
|
+
GROK_VIDEO_MODEL=grok-imagine-video
|
|
57
60
|
|
|
58
61
|
# ─── Moonshot AI (Kimi) ─────────────────────────────────────────────────────
|
|
59
62
|
MOONSHOT_API_KEY=your-moonshot-api-key
|
|
@@ -86,4 +89,4 @@ AIRLLM_MODEL=meta-llama/Llama-2-7b-hf
|
|
|
86
89
|
AIRLLM_COMPRESSION=
|
|
87
90
|
|
|
88
91
|
# ─── Stability AI (image generation) ────────────────────────────────────────
|
|
89
|
-
STABILITY_API_KEY=
|
|
92
|
+
STABILITY_API_KEY=
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: prompture
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.56.dev1
|
|
4
4
|
Summary: Ask LLMs to return structured JSON and run cross-model tests. API-first.
|
|
5
5
|
Author-email: Juan Denis <juan@vene.co>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -96,7 +96,7 @@ print(person.name) # Maria
|
|
|
96
96
|
|
|
97
97
|
- **Structured output** — JSON schema enforcement and direct Pydantic model population
|
|
98
98
|
- **17+ providers** — OpenAI, Claude, Google, Groq, Grok, Azure, Ollama, LM Studio, OpenRouter, HuggingFace, Moonshot, ModelScope, Z.ai, Vertex AI, AirLLM, CachiBot, and generic HTTP
|
|
99
|
-
- **Multi-modal** — Drivers for embeddings, image generation (DALL-E, Imagen, Grok, Stability), text-to-speech, and speech-to-text (Whisper, ElevenLabs)
|
|
99
|
+
- **Multi-modal** — Drivers for embeddings, image generation (DALL-E, Imagen, Grok, Stability), video generation (Grok Imagine Video), text-to-speech, and speech-to-text (Whisper, ElevenLabs)
|
|
100
100
|
- **Multi-model fallback** — Try a list of models in sequence with per-attempt cost, token, and capability accounting
|
|
101
101
|
- **Strategy cascade** — Auto-selects between provider-native JSON mode, tool-call extraction, and prompted repair so extraction works on any model
|
|
102
102
|
- **TOON input conversion** — 45-60% token savings when sending structured data via [Token-Oriented Object Notation](https://github.com/jhd3197/python-toon)
|
|
@@ -141,6 +141,8 @@ ANTHROPIC_API_KEY=sk-ant-...
|
|
|
141
141
|
GOOGLE_API_KEY=...
|
|
142
142
|
GROQ_API_KEY=...
|
|
143
143
|
GROK_API_KEY=...
|
|
144
|
+
# optional xAI-compatible alias for Grok APIs
|
|
145
|
+
XAI_API_KEY=...
|
|
144
146
|
OPENROUTER_API_KEY=...
|
|
145
147
|
AZURE_OPENAI_ENDPOINT=...
|
|
146
148
|
AZURE_OPENAI_API_KEY=...
|
|
@@ -198,6 +200,7 @@ Beyond text LLMs, Prompture exposes drivers for adjacent modalities under the sa
|
|
|
198
200
|
|
|
199
201
|
- **Embeddings** — OpenAI (`text-embedding-3-*`) and Ollama (`nomic-embed-text`)
|
|
200
202
|
- **Image generation** — OpenAI DALL-E, Google Imagen, Grok, Stability AI
|
|
203
|
+
- **Video generation** — Grok Imagine Video (`grok-imagine-video`) with text-to-video, image-to-video, reference images, and polling
|
|
201
204
|
- **Text-to-speech** — OpenAI (`tts-1`) and ElevenLabs
|
|
202
205
|
- **Speech-to-text** — OpenAI Whisper and ElevenLabs
|
|
203
206
|
|
|
@@ -212,6 +215,26 @@ result = driver.generate_image(
|
|
|
212
215
|
print(result["meta"]["cost"], result["meta"]["image_count"])
|
|
213
216
|
```
|
|
214
217
|
|
|
218
|
+
Video generation uses the same provider/model routing. Set `GROK_API_KEY` or `XAI_API_KEY`, then request a Grok video model:
|
|
219
|
+
|
|
220
|
+
```python
|
|
221
|
+
from prompture import get_video_gen_driver_for_model
|
|
222
|
+
|
|
223
|
+
driver = get_video_gen_driver_for_model("grok/grok-imagine-video")
|
|
224
|
+
result = driver.generate_video(
|
|
225
|
+
"wide shot of a crystal-powered rocket launching from red desert dunes",
|
|
226
|
+
{"duration": 8, "aspect_ratio": "16:9", "resolution": "720p"},
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
video = result["videos"][0]
|
|
230
|
+
print(video.url)
|
|
231
|
+
print(result["meta"]["request_id"], result["meta"]["cost"])
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
For local smoke tests without waiting on the render, pass `{"poll": False}` to get the provider request ID. The async factory is available as `get_async_video_gen_driver_for_model()`.
|
|
235
|
+
|
|
236
|
+
Runnable example: `python examples/grok_video_generation_example.py`.
|
|
237
|
+
|
|
215
238
|
## Usage
|
|
216
239
|
|
|
217
240
|
### One-Shot Pydantic Extraction
|
|
@@ -32,7 +32,7 @@ print(person.name) # Maria
|
|
|
32
32
|
|
|
33
33
|
- **Structured output** — JSON schema enforcement and direct Pydantic model population
|
|
34
34
|
- **17+ providers** — OpenAI, Claude, Google, Groq, Grok, Azure, Ollama, LM Studio, OpenRouter, HuggingFace, Moonshot, ModelScope, Z.ai, Vertex AI, AirLLM, CachiBot, and generic HTTP
|
|
35
|
-
- **Multi-modal** — Drivers for embeddings, image generation (DALL-E, Imagen, Grok, Stability), text-to-speech, and speech-to-text (Whisper, ElevenLabs)
|
|
35
|
+
- **Multi-modal** — Drivers for embeddings, image generation (DALL-E, Imagen, Grok, Stability), video generation (Grok Imagine Video), text-to-speech, and speech-to-text (Whisper, ElevenLabs)
|
|
36
36
|
- **Multi-model fallback** — Try a list of models in sequence with per-attempt cost, token, and capability accounting
|
|
37
37
|
- **Strategy cascade** — Auto-selects between provider-native JSON mode, tool-call extraction, and prompted repair so extraction works on any model
|
|
38
38
|
- **TOON input conversion** — 45-60% token savings when sending structured data via [Token-Oriented Object Notation](https://github.com/jhd3197/python-toon)
|
|
@@ -77,6 +77,8 @@ ANTHROPIC_API_KEY=sk-ant-...
|
|
|
77
77
|
GOOGLE_API_KEY=...
|
|
78
78
|
GROQ_API_KEY=...
|
|
79
79
|
GROK_API_KEY=...
|
|
80
|
+
# optional xAI-compatible alias for Grok APIs
|
|
81
|
+
XAI_API_KEY=...
|
|
80
82
|
OPENROUTER_API_KEY=...
|
|
81
83
|
AZURE_OPENAI_ENDPOINT=...
|
|
82
84
|
AZURE_OPENAI_API_KEY=...
|
|
@@ -134,6 +136,7 @@ Beyond text LLMs, Prompture exposes drivers for adjacent modalities under the sa
|
|
|
134
136
|
|
|
135
137
|
- **Embeddings** — OpenAI (`text-embedding-3-*`) and Ollama (`nomic-embed-text`)
|
|
136
138
|
- **Image generation** — OpenAI DALL-E, Google Imagen, Grok, Stability AI
|
|
139
|
+
- **Video generation** — Grok Imagine Video (`grok-imagine-video`) with text-to-video, image-to-video, reference images, and polling
|
|
137
140
|
- **Text-to-speech** — OpenAI (`tts-1`) and ElevenLabs
|
|
138
141
|
- **Speech-to-text** — OpenAI Whisper and ElevenLabs
|
|
139
142
|
|
|
@@ -148,6 +151,26 @@ result = driver.generate_image(
|
|
|
148
151
|
print(result["meta"]["cost"], result["meta"]["image_count"])
|
|
149
152
|
```
|
|
150
153
|
|
|
154
|
+
Video generation uses the same provider/model routing. Set `GROK_API_KEY` or `XAI_API_KEY`, then request a Grok video model:
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
from prompture import get_video_gen_driver_for_model
|
|
158
|
+
|
|
159
|
+
driver = get_video_gen_driver_for_model("grok/grok-imagine-video")
|
|
160
|
+
result = driver.generate_video(
|
|
161
|
+
"wide shot of a crystal-powered rocket launching from red desert dunes",
|
|
162
|
+
{"duration": 8, "aspect_ratio": "16:9", "resolution": "720p"},
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
video = result["videos"][0]
|
|
166
|
+
print(video.url)
|
|
167
|
+
print(result["meta"]["request_id"], result["meta"]["cost"])
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
For local smoke tests without waiting on the render, pass `{"poll": False}` to get the provider request ID. The async factory is available as `get_async_video_gen_driver_for_model()`.
|
|
171
|
+
|
|
172
|
+
Runnable example: `python examples/grok_video_generation_example.py`.
|
|
173
|
+
|
|
151
174
|
## Usage
|
|
152
175
|
|
|
153
176
|
### One-Shot Pydantic Extraction
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '1.0.
|
|
22
|
-
__version_tuple__ = version_tuple = (1, 0,
|
|
21
|
+
__version__ = version = '1.0.56.dev1'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 0, 56, 'dev1')
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -41,6 +41,7 @@ from .async_google_driver import AsyncGoogleDriver
|
|
|
41
41
|
from .async_google_img_gen_driver import AsyncGoogleImageGenDriver
|
|
42
42
|
from .async_grok_driver import AsyncGrokDriver
|
|
43
43
|
from .async_grok_img_gen_driver import AsyncGrokImageGenDriver
|
|
44
|
+
from .async_grok_video_gen_driver import AsyncGrokVideoGenDriver
|
|
44
45
|
from .async_groq_driver import AsyncGroqDriver
|
|
45
46
|
from .async_hugging_driver import AsyncHuggingFaceDriver
|
|
46
47
|
from .async_img_gen_base import AsyncImageGenDriver
|
|
@@ -59,6 +60,7 @@ from .async_openrouter_driver import AsyncOpenRouterDriver
|
|
|
59
60
|
from .async_stability_img_gen_driver import AsyncStabilityImageGenDriver
|
|
60
61
|
from .async_stt_base import AsyncSTTDriver
|
|
61
62
|
from .async_tts_base import AsyncTTSDriver
|
|
63
|
+
from .async_video_gen_base import AsyncVideoGenDriver
|
|
62
64
|
from .async_zai_driver import AsyncZaiDriver
|
|
63
65
|
from .azure_config import (
|
|
64
66
|
clear_azure_configs,
|
|
@@ -76,6 +78,7 @@ from .google_driver import GoogleDriver
|
|
|
76
78
|
from .google_img_gen_driver import GoogleImageGenDriver
|
|
77
79
|
from .grok_driver import GrokDriver
|
|
78
80
|
from .grok_img_gen_driver import GrokImageGenDriver
|
|
81
|
+
from .grok_video_gen_driver import GrokVideoGenDriver
|
|
79
82
|
from .groq_driver import GroqDriver
|
|
80
83
|
from .hugging_driver import HuggingFaceDriver
|
|
81
84
|
from .img_gen_base import ImageGenDriver
|
|
@@ -104,59 +107,70 @@ from .registry import (
|
|
|
104
107
|
get_async_img_gen_driver_factory,
|
|
105
108
|
get_async_stt_driver_factory,
|
|
106
109
|
get_async_tts_driver_factory,
|
|
110
|
+
get_async_video_gen_driver_factory,
|
|
107
111
|
get_driver_factory,
|
|
108
112
|
get_embedding_driver_factory,
|
|
109
113
|
get_img_gen_driver_factory,
|
|
110
114
|
get_stt_driver_factory,
|
|
111
115
|
get_tts_driver_factory,
|
|
116
|
+
get_video_gen_driver_factory,
|
|
112
117
|
is_async_driver_registered,
|
|
113
118
|
is_async_embedding_driver_registered,
|
|
114
119
|
is_async_img_gen_driver_registered,
|
|
115
120
|
is_async_stt_driver_registered,
|
|
116
121
|
is_async_tts_driver_registered,
|
|
122
|
+
is_async_video_gen_driver_registered,
|
|
117
123
|
is_driver_registered,
|
|
118
124
|
is_embedding_driver_registered,
|
|
119
125
|
is_img_gen_driver_registered,
|
|
120
126
|
is_stt_driver_registered,
|
|
121
127
|
is_tts_driver_registered,
|
|
128
|
+
is_video_gen_driver_registered,
|
|
122
129
|
list_registered_async_drivers,
|
|
123
130
|
list_registered_async_embedding_drivers,
|
|
124
131
|
list_registered_async_img_gen_drivers,
|
|
125
132
|
list_registered_async_stt_drivers,
|
|
126
133
|
list_registered_async_tts_drivers,
|
|
134
|
+
list_registered_async_video_gen_drivers,
|
|
127
135
|
list_registered_drivers,
|
|
128
136
|
list_registered_embedding_drivers,
|
|
129
137
|
list_registered_img_gen_drivers,
|
|
130
138
|
list_registered_stt_drivers,
|
|
131
139
|
list_registered_tts_drivers,
|
|
140
|
+
list_registered_video_gen_drivers,
|
|
132
141
|
load_entry_point_drivers,
|
|
133
142
|
register_async_driver,
|
|
134
143
|
register_async_embedding_driver,
|
|
135
144
|
register_async_img_gen_driver,
|
|
136
145
|
register_async_stt_driver,
|
|
137
146
|
register_async_tts_driver,
|
|
147
|
+
register_async_video_gen_driver,
|
|
138
148
|
register_driver,
|
|
139
149
|
register_embedding_driver,
|
|
140
150
|
register_img_gen_driver,
|
|
141
151
|
register_stt_driver,
|
|
142
152
|
register_tts_driver,
|
|
153
|
+
register_video_gen_driver,
|
|
143
154
|
unregister_async_driver,
|
|
144
155
|
unregister_async_embedding_driver,
|
|
145
156
|
unregister_async_img_gen_driver,
|
|
146
157
|
unregister_async_stt_driver,
|
|
147
158
|
unregister_async_tts_driver,
|
|
159
|
+
unregister_async_video_gen_driver,
|
|
148
160
|
unregister_driver,
|
|
149
161
|
unregister_embedding_driver,
|
|
150
162
|
unregister_img_gen_driver,
|
|
151
163
|
unregister_stt_driver,
|
|
152
164
|
unregister_tts_driver,
|
|
165
|
+
unregister_video_gen_driver,
|
|
153
166
|
)
|
|
154
167
|
from .stability_img_gen_driver import StabilityImageGenDriver
|
|
155
168
|
from .stt_base import STTDriver
|
|
156
169
|
from .tts_base import TTSDriver
|
|
170
|
+
from .video_gen_base import VideoGenDriver
|
|
157
171
|
from .zai_driver import ZaiDriver
|
|
158
172
|
|
|
159
|
-
# Register all built-in drivers (LLM sync/async, STT, TTS, img_gen, embedding)
|
|
173
|
+
# Register all built-in drivers (LLM sync/async, STT, TTS, img_gen, video_gen, embedding)
|
|
160
174
|
# from the unified ProviderDescriptor list — replaces ~200 lines of individual
|
|
161
175
|
# register_*() calls that were previously scattered across this file,
|
|
162
176
|
# async_registry.py, audio_registry.py, embedding_registry.py, and img_gen_registry.py.
|
|
@@ -185,6 +199,10 @@ from .img_gen_registry import (
|
|
|
185
199
|
get_async_img_gen_driver_for_model,
|
|
186
200
|
get_img_gen_driver_for_model,
|
|
187
201
|
)
|
|
202
|
+
from .video_gen_registry import (
|
|
203
|
+
get_async_video_gen_driver_for_model,
|
|
204
|
+
get_video_gen_driver_for_model,
|
|
205
|
+
)
|
|
188
206
|
|
|
189
207
|
# Backwards compatibility: expose registry dict (read-only view recommended)
|
|
190
208
|
DRIVER_REGISTRY = _get_sync_registry()
|
|
@@ -449,6 +467,7 @@ __all__ = [
|
|
|
449
467
|
"AsyncGoogleImageGenDriver",
|
|
450
468
|
"AsyncGrokDriver",
|
|
451
469
|
"AsyncGrokImageGenDriver",
|
|
470
|
+
"AsyncGrokVideoGenDriver",
|
|
452
471
|
"AsyncGroqDriver",
|
|
453
472
|
"AsyncHuggingFaceDriver",
|
|
454
473
|
"AsyncImageGenDriver",
|
|
@@ -467,6 +486,7 @@ __all__ = [
|
|
|
467
486
|
"AsyncSTTDriver",
|
|
468
487
|
"AsyncStabilityImageGenDriver",
|
|
469
488
|
"AsyncTTSDriver",
|
|
489
|
+
"AsyncVideoGenDriver",
|
|
470
490
|
"AsyncZaiDriver",
|
|
471
491
|
# Sync LLM drivers
|
|
472
492
|
"AzureDriver",
|
|
@@ -482,6 +502,7 @@ __all__ = [
|
|
|
482
502
|
"GoogleImageGenDriver",
|
|
483
503
|
"GrokDriver",
|
|
484
504
|
"GrokImageGenDriver",
|
|
505
|
+
"GrokVideoGenDriver",
|
|
485
506
|
"GroqDriver",
|
|
486
507
|
"HuggingFaceDriver",
|
|
487
508
|
# Image gen base class
|
|
@@ -502,6 +523,7 @@ __all__ = [
|
|
|
502
523
|
"STTDriver",
|
|
503
524
|
"StabilityImageGenDriver",
|
|
504
525
|
"TTSDriver",
|
|
526
|
+
"VideoGenDriver",
|
|
505
527
|
"ZaiDriver",
|
|
506
528
|
# Azure config API
|
|
507
529
|
"clear_azure_configs",
|
|
@@ -521,6 +543,10 @@ __all__ = [
|
|
|
521
543
|
"get_async_stt_driver_for_model",
|
|
522
544
|
"get_async_tts_driver_factory",
|
|
523
545
|
"get_async_tts_driver_for_model",
|
|
546
|
+
# Video gen registry query functions
|
|
547
|
+
"get_async_video_gen_driver_factory",
|
|
548
|
+
# Video gen factory functions
|
|
549
|
+
"get_async_video_gen_driver_for_model",
|
|
524
550
|
# LLM factory functions
|
|
525
551
|
"get_driver",
|
|
526
552
|
"get_driver_for_model",
|
|
@@ -532,27 +558,33 @@ __all__ = [
|
|
|
532
558
|
"get_stt_driver_for_model",
|
|
533
559
|
"get_tts_driver_factory",
|
|
534
560
|
"get_tts_driver_for_model",
|
|
561
|
+
"get_video_gen_driver_factory",
|
|
562
|
+
"get_video_gen_driver_for_model",
|
|
535
563
|
# Other registry query functions
|
|
536
564
|
"is_async_driver_registered",
|
|
537
565
|
"is_async_embedding_driver_registered",
|
|
538
566
|
"is_async_img_gen_driver_registered",
|
|
539
567
|
"is_async_stt_driver_registered",
|
|
540
568
|
"is_async_tts_driver_registered",
|
|
569
|
+
"is_async_video_gen_driver_registered",
|
|
541
570
|
"is_driver_registered",
|
|
542
571
|
"is_embedding_driver_registered",
|
|
543
572
|
"is_img_gen_driver_registered",
|
|
544
573
|
"is_stt_driver_registered",
|
|
545
574
|
"is_tts_driver_registered",
|
|
575
|
+
"is_video_gen_driver_registered",
|
|
546
576
|
"list_registered_async_drivers",
|
|
547
577
|
"list_registered_async_embedding_drivers",
|
|
548
578
|
"list_registered_async_img_gen_drivers",
|
|
549
579
|
"list_registered_async_stt_drivers",
|
|
550
580
|
"list_registered_async_tts_drivers",
|
|
581
|
+
"list_registered_async_video_gen_drivers",
|
|
551
582
|
"list_registered_drivers",
|
|
552
583
|
"list_registered_embedding_drivers",
|
|
553
584
|
"list_registered_img_gen_drivers",
|
|
554
585
|
"list_registered_stt_drivers",
|
|
555
586
|
"list_registered_tts_drivers",
|
|
587
|
+
"list_registered_video_gen_drivers",
|
|
556
588
|
"load_entry_point_drivers",
|
|
557
589
|
"parse_model_string",
|
|
558
590
|
"provider_for_model",
|
|
@@ -562,6 +594,7 @@ __all__ = [
|
|
|
562
594
|
"register_async_img_gen_driver",
|
|
563
595
|
"register_async_stt_driver",
|
|
564
596
|
"register_async_tts_driver",
|
|
597
|
+
"register_async_video_gen_driver",
|
|
565
598
|
"register_azure_config",
|
|
566
599
|
# Registry functions (public API)
|
|
567
600
|
"register_driver",
|
|
@@ -569,16 +602,19 @@ __all__ = [
|
|
|
569
602
|
"register_img_gen_driver",
|
|
570
603
|
"register_stt_driver",
|
|
571
604
|
"register_tts_driver",
|
|
605
|
+
"register_video_gen_driver",
|
|
572
606
|
"set_azure_config_resolver",
|
|
573
607
|
"unregister_async_driver",
|
|
574
608
|
"unregister_async_embedding_driver",
|
|
575
609
|
"unregister_async_img_gen_driver",
|
|
576
610
|
"unregister_async_stt_driver",
|
|
577
611
|
"unregister_async_tts_driver",
|
|
612
|
+
"unregister_async_video_gen_driver",
|
|
578
613
|
"unregister_azure_config",
|
|
579
614
|
"unregister_driver",
|
|
580
615
|
"unregister_embedding_driver",
|
|
581
616
|
"unregister_img_gen_driver",
|
|
582
617
|
"unregister_stt_driver",
|
|
583
618
|
"unregister_tts_driver",
|
|
619
|
+
"unregister_video_gen_driver",
|
|
584
620
|
]
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"""Async xAI Grok Imagine video generation driver."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import os
|
|
7
|
+
import time
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
import httpx
|
|
11
|
+
|
|
12
|
+
from ..infra.cost_mixin import VideoCostMixin
|
|
13
|
+
from .async_video_gen_base import AsyncVideoGenDriver
|
|
14
|
+
from .grok_video_gen_driver import (
|
|
15
|
+
_DEFAULT_ENDPOINT,
|
|
16
|
+
_duration_from_options,
|
|
17
|
+
_error_text,
|
|
18
|
+
_extract_video_content,
|
|
19
|
+
_get_xai_api_key,
|
|
20
|
+
_image_payload,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class AsyncGrokVideoGenDriver(VideoCostMixin, AsyncVideoGenDriver):
|
|
25
|
+
"""Async video generation via xAI Grok Imagine Video REST API."""
|
|
26
|
+
|
|
27
|
+
supports_image_input = True
|
|
28
|
+
supports_reference_images = True
|
|
29
|
+
supports_video_input = False
|
|
30
|
+
supports_audio = True
|
|
31
|
+
supports_polling = True
|
|
32
|
+
supported_aspect_ratios = ["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3"]
|
|
33
|
+
supported_resolutions = ["480p", "720p"]
|
|
34
|
+
max_seconds = 15
|
|
35
|
+
|
|
36
|
+
KNOWN_MODELS = ["grok-imagine-video"]
|
|
37
|
+
VIDEO_PRICING: dict[str, dict[str, Any]] = {
|
|
38
|
+
"grok-imagine-video": {
|
|
39
|
+
"per_second": 0.05,
|
|
40
|
+
"per_second_by_resolution": {
|
|
41
|
+
"480p": 0.05,
|
|
42
|
+
"720p": 0.07,
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
def __init__(
|
|
48
|
+
self,
|
|
49
|
+
api_key: str | None = None,
|
|
50
|
+
model: str = "grok-imagine-video",
|
|
51
|
+
endpoint: str | None = None,
|
|
52
|
+
):
|
|
53
|
+
self.api_key = _get_xai_api_key(api_key)
|
|
54
|
+
self.model = model
|
|
55
|
+
self.endpoint = (endpoint or os.getenv("GROK_ENDPOINT") or _DEFAULT_ENDPOINT).rstrip("/")
|
|
56
|
+
|
|
57
|
+
@classmethod
|
|
58
|
+
def list_models(cls, *, api_key: str | None = None, **kw: object) -> list[str] | None:
|
|
59
|
+
"""Return known xAI video models when an API key is configured."""
|
|
60
|
+
key = _get_xai_api_key(api_key)
|
|
61
|
+
if not key:
|
|
62
|
+
return None
|
|
63
|
+
return list(cls.KNOWN_MODELS)
|
|
64
|
+
|
|
65
|
+
async def generate_video(self, prompt: str, options: dict[str, Any]) -> dict[str, Any]:
|
|
66
|
+
"""Generate a video using xAI Grok Imagine Video (async)."""
|
|
67
|
+
if not self.api_key:
|
|
68
|
+
raise RuntimeError("GROK_API_KEY or XAI_API_KEY environment variable is required")
|
|
69
|
+
if not prompt:
|
|
70
|
+
raise ValueError("prompt cannot be empty")
|
|
71
|
+
|
|
72
|
+
model = options.get("model", self.model)
|
|
73
|
+
duration = _duration_from_options(options)
|
|
74
|
+
aspect_ratio = options.get("aspect_ratio", "16:9")
|
|
75
|
+
resolution = options.get("resolution", "480p")
|
|
76
|
+
|
|
77
|
+
if aspect_ratio not in self.supported_aspect_ratios:
|
|
78
|
+
raise ValueError(f"Unsupported aspect_ratio '{aspect_ratio}'")
|
|
79
|
+
if resolution not in self.supported_resolutions:
|
|
80
|
+
raise ValueError(f"Unsupported resolution '{resolution}'")
|
|
81
|
+
|
|
82
|
+
image = options.get("image")
|
|
83
|
+
reference_images = options.get("reference_images")
|
|
84
|
+
if image is not None and reference_images:
|
|
85
|
+
raise ValueError("image and reference_images cannot be used together")
|
|
86
|
+
if reference_images:
|
|
87
|
+
if len(reference_images) > 7:
|
|
88
|
+
raise ValueError("reference_images supports at most 7 images")
|
|
89
|
+
if duration > 10:
|
|
90
|
+
raise ValueError("duration must be 10 seconds or less when using reference_images")
|
|
91
|
+
|
|
92
|
+
payload: dict[str, Any] = {
|
|
93
|
+
"model": model,
|
|
94
|
+
"prompt": prompt,
|
|
95
|
+
"duration": duration,
|
|
96
|
+
"aspect_ratio": aspect_ratio,
|
|
97
|
+
"resolution": resolution,
|
|
98
|
+
}
|
|
99
|
+
if image is not None:
|
|
100
|
+
payload["image"] = _image_payload(image)
|
|
101
|
+
if reference_images:
|
|
102
|
+
payload["reference_images"] = [_image_payload(img) for img in reference_images]
|
|
103
|
+
|
|
104
|
+
headers = {"Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json"}
|
|
105
|
+
async with httpx.AsyncClient() as client:
|
|
106
|
+
response = await client.post(
|
|
107
|
+
f"{self.endpoint}/videos/generations",
|
|
108
|
+
headers=headers,
|
|
109
|
+
json=payload,
|
|
110
|
+
timeout=120.0,
|
|
111
|
+
)
|
|
112
|
+
if response.status_code >= 400:
|
|
113
|
+
raise RuntimeError(
|
|
114
|
+
f"Grok video generation failed: HTTP {response.status_code}: {_error_text(response)}"
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
start_data = response.json()
|
|
118
|
+
request_id = start_data.get("request_id")
|
|
119
|
+
if not request_id:
|
|
120
|
+
raise RuntimeError("Grok video generation response did not include request_id")
|
|
121
|
+
|
|
122
|
+
if not options.get("poll", True):
|
|
123
|
+
return {
|
|
124
|
+
"videos": [],
|
|
125
|
+
"meta": {
|
|
126
|
+
"video_count": 0,
|
|
127
|
+
"request_id": request_id,
|
|
128
|
+
"status": start_data.get("status", "pending"),
|
|
129
|
+
"duration_seconds": duration,
|
|
130
|
+
"aspect_ratio": aspect_ratio,
|
|
131
|
+
"resolution": resolution,
|
|
132
|
+
"cost": 0.0,
|
|
133
|
+
"model_name": f"grok/{model}",
|
|
134
|
+
"raw_response": start_data,
|
|
135
|
+
},
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
final_data = await self._poll_until_done(
|
|
139
|
+
client,
|
|
140
|
+
request_id,
|
|
141
|
+
headers=headers,
|
|
142
|
+
poll_interval=float(options.get("poll_interval", 5)),
|
|
143
|
+
timeout_seconds=float(options.get("timeout", 600)),
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
video = _extract_video_content(final_data)
|
|
147
|
+
duration_seconds = video.duration_seconds or float(duration)
|
|
148
|
+
cost = self._calculate_video_cost(
|
|
149
|
+
"grok",
|
|
150
|
+
model,
|
|
151
|
+
duration_seconds=duration_seconds,
|
|
152
|
+
n=1,
|
|
153
|
+
resolution=resolution,
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
"videos": [video],
|
|
158
|
+
"meta": {
|
|
159
|
+
"video_count": 1,
|
|
160
|
+
"request_id": request_id,
|
|
161
|
+
"status": final_data.get("status"),
|
|
162
|
+
"duration_seconds": duration_seconds,
|
|
163
|
+
"aspect_ratio": aspect_ratio,
|
|
164
|
+
"resolution": resolution,
|
|
165
|
+
"cost": cost,
|
|
166
|
+
"model_name": f"grok/{model}",
|
|
167
|
+
"raw_response": {"start": start_data, "final": final_data},
|
|
168
|
+
},
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async def _poll_until_done(
|
|
172
|
+
self,
|
|
173
|
+
client: httpx.AsyncClient,
|
|
174
|
+
request_id: str,
|
|
175
|
+
*,
|
|
176
|
+
headers: dict[str, str],
|
|
177
|
+
poll_interval: float,
|
|
178
|
+
timeout_seconds: float,
|
|
179
|
+
) -> dict[str, Any]:
|
|
180
|
+
deadline = time.monotonic() + timeout_seconds
|
|
181
|
+
while True:
|
|
182
|
+
response = await client.get(f"{self.endpoint}/videos/{request_id}", headers=headers, timeout=30.0)
|
|
183
|
+
if response.status_code >= 400:
|
|
184
|
+
raise RuntimeError(f"Grok video status failed: HTTP {response.status_code}: {_error_text(response)}")
|
|
185
|
+
|
|
186
|
+
data = response.json()
|
|
187
|
+
status = data.get("status")
|
|
188
|
+
if status == "done":
|
|
189
|
+
return data
|
|
190
|
+
if status in {"failed", "expired"}:
|
|
191
|
+
raise RuntimeError(f"Grok video generation {status}: {data}")
|
|
192
|
+
if time.monotonic() >= deadline:
|
|
193
|
+
raise TimeoutError(f"Grok video generation timed out for request_id={request_id}")
|
|
194
|
+
await asyncio.sleep(poll_interval)
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""Async base class for video generation drivers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import time
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from ..infra.callbacks import DriverCallbacks
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger("prompture.async_video_gen_driver")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class AsyncVideoGenDriver:
|
|
15
|
+
"""Async adapter base for video generation. Implement ``async generate_video(prompt, options)``."""
|
|
16
|
+
|
|
17
|
+
supports_image_input: bool = False
|
|
18
|
+
supports_reference_images: bool = False
|
|
19
|
+
supports_video_input: bool = False
|
|
20
|
+
supports_audio: bool = False
|
|
21
|
+
supports_polling: bool = True
|
|
22
|
+
supported_aspect_ratios: list[str] = []
|
|
23
|
+
supported_resolutions: list[str] = []
|
|
24
|
+
max_seconds: int | None = None
|
|
25
|
+
|
|
26
|
+
callbacks: DriverCallbacks | None = None
|
|
27
|
+
|
|
28
|
+
async def generate_video(self, prompt: str, options: dict[str, Any]) -> dict[str, Any]:
|
|
29
|
+
"""Generate video(s) from a text prompt (async)."""
|
|
30
|
+
raise NotImplementedError
|
|
31
|
+
|
|
32
|
+
async def generate_video_with_hooks(self, prompt: str, options: dict[str, Any]) -> dict[str, Any]:
|
|
33
|
+
"""Wrap :meth:`generate_video` with on_request / on_response / on_error callbacks."""
|
|
34
|
+
driver_name = getattr(self, "model", self.__class__.__name__)
|
|
35
|
+
self._fire_callback(
|
|
36
|
+
"on_request",
|
|
37
|
+
{"prompt_length": len(prompt), "options": options, "driver": driver_name},
|
|
38
|
+
)
|
|
39
|
+
t0 = time.perf_counter()
|
|
40
|
+
try:
|
|
41
|
+
resp = await self.generate_video(prompt, options)
|
|
42
|
+
except Exception as exc:
|
|
43
|
+
self._fire_callback(
|
|
44
|
+
"on_error",
|
|
45
|
+
{"error": exc, "prompt_length": len(prompt), "options": options, "driver": driver_name},
|
|
46
|
+
)
|
|
47
|
+
raise
|
|
48
|
+
elapsed_ms = (time.perf_counter() - t0) * 1000
|
|
49
|
+
meta = resp.get("meta", {})
|
|
50
|
+
logger.debug(
|
|
51
|
+
"[video_gen] async generate driver=%s videos=%d cost=%.6f elapsed=%.0fms",
|
|
52
|
+
driver_name,
|
|
53
|
+
meta.get("video_count", 0),
|
|
54
|
+
meta.get("cost", 0.0),
|
|
55
|
+
elapsed_ms,
|
|
56
|
+
)
|
|
57
|
+
self._fire_callback(
|
|
58
|
+
"on_response",
|
|
59
|
+
{
|
|
60
|
+
"video_count": meta.get("video_count", 0),
|
|
61
|
+
"meta": meta,
|
|
62
|
+
"driver": driver_name,
|
|
63
|
+
"elapsed_ms": elapsed_ms,
|
|
64
|
+
},
|
|
65
|
+
)
|
|
66
|
+
return resp
|
|
67
|
+
|
|
68
|
+
def _fire_callback(self, event: str, payload: dict[str, Any]) -> None:
|
|
69
|
+
"""Invoke a single callback, swallowing and logging any exception."""
|
|
70
|
+
if self.callbacks is None:
|
|
71
|
+
return
|
|
72
|
+
cb = getattr(self.callbacks, event, None)
|
|
73
|
+
if cb is None:
|
|
74
|
+
return
|
|
75
|
+
try:
|
|
76
|
+
cb(payload)
|
|
77
|
+
except Exception:
|
|
78
|
+
logger.exception("Callback %s raised an exception", event)
|