cocoindex 0.1.38__tar.gz → 0.1.39__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.
- {cocoindex-0.1.38 → cocoindex-0.1.39}/Cargo.lock +1 -1
- {cocoindex-0.1.38 → cocoindex-0.1.39}/Cargo.toml +1 -1
- {cocoindex-0.1.38 → cocoindex-0.1.39}/PKG-INFO +1 -1
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/docs/core/flow_def.mdx +34 -1
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/docs/core/flow_methods.mdx +1 -1
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/docs/core/initialization.mdx +3 -2
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/docs/ops/storages.md +1 -1
- cocoindex-0.1.39/examples/text_embedding_qdrant/.env +2 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/python/cocoindex/__init__.py +3 -2
- {cocoindex-0.1.38 → cocoindex-0.1.39}/python/cocoindex/convert.py +1 -1
- {cocoindex-0.1.38 → cocoindex-0.1.39}/python/cocoindex/flow.py +110 -21
- {cocoindex-0.1.38 → cocoindex-0.1.39}/python/cocoindex/op.py +12 -12
- {cocoindex-0.1.38 → cocoindex-0.1.39}/python/cocoindex/query.py +1 -1
- {cocoindex-0.1.38 → cocoindex-0.1.39}/python/cocoindex/setting.py +1 -1
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/builder/analyzed_flow.rs +1 -2
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/builder/analyzer.rs +5 -2
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/builder/flow_builder.rs +23 -18
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/py/mod.rs +23 -0
- cocoindex-0.1.38/examples/docs_to_knowledge_graph/.env +0 -3
- {cocoindex-0.1.38 → cocoindex-0.1.39}/.cargo/config.toml +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/.env.lib_debug +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/.github/ISSUE_TEMPLATE//360/237/220/233-bug-report.md" +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/.github/ISSUE_TEMPLATE//360/237/222/241-feature-request.md" +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/.github/scripts/update_version.sh +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/.github/workflows/CI.yml +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/.github/workflows/_test.yml +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/.github/workflows/docs.yml +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/.github/workflows/release.yml +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/.gitignore +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/.vscode/settings.json +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/CODE_OF_CONDUCT.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/CONTRIBUTING.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/LICENSE +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/README.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/dev/neo4j.yaml +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/dev/postgres.yaml +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/.gitignore +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/README.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/docs/about/community.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/docs/about/contributing.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/docs/ai/llm.mdx +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/docs/core/basics.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/docs/core/cli.mdx +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/docs/core/custom_function.mdx +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/docs/core/data_example.svg +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/docs/core/data_types.mdx +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/docs/core/flow_example.svg +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/docs/getting_started/installation.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/docs/getting_started/markdown_files.zip +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/docs/getting_started/overview.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/docs/getting_started/quickstart.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/docs/ops/functions.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/docs/ops/sources.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/docusaurus.config.ts +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/package.json +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/sidebars.ts +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/src/components/HomepageFeatures/index.tsx +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/src/components/HomepageFeatures/styles.module.css +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/src/css/custom.css +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/src/theme/Root.js +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/static/.nojekyll +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/static/img/docusaurus.png +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/static/img/favicon.ico +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/static/img/icon.svg +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/static/robots.txt +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/tsconfig.json +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/docs/yarn.lock +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/amazon_s3_embedding/.env.example +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/amazon_s3_embedding/.gitignore +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/amazon_s3_embedding/README.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/amazon_s3_embedding/main.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/amazon_s3_embedding/pyproject.toml +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/code_embedding/.env +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/code_embedding/README.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/code_embedding/main.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/code_embedding/pyproject.toml +0 -0
- {cocoindex-0.1.38/examples/manuals_llm_extraction → cocoindex-0.1.39/examples/docs_to_knowledge_graph}/.env +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/docs_to_knowledge_graph/README.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/docs_to_knowledge_graph/main.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/docs_to_knowledge_graph/pyproject.toml +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/fastapi_server_docker/.dockerignore +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/fastapi_server_docker/.env +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/fastapi_server_docker/README.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/fastapi_server_docker/compose.yaml +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/fastapi_server_docker/dockerfile +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/fastapi_server_docker/main.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/fastapi_server_docker/requirements.txt +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/fastapi_server_docker/sample_code/main.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/fastapi_server_docker/src/cocoindex_funs.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/gdrive_text_embedding/.env.example +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/gdrive_text_embedding/.gitignore +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/gdrive_text_embedding/README.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/gdrive_text_embedding/main.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/gdrive_text_embedding/pyproject.toml +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/image_search_example/.env +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/image_search_example/README.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/image_search_example/frontend/.gitignore +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/image_search_example/frontend/index.html +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/image_search_example/frontend/package-lock.json +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/image_search_example/frontend/package.json +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/image_search_example/frontend/src/App.jsx +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/image_search_example/frontend/src/main.jsx +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/image_search_example/frontend/src/style.css +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/image_search_example/frontend/vite.config.js +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/image_search_example/img/cat1.jpeg +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/image_search_example/img/dog1.jpeg +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/image_search_example/img/elephant1.jpg +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/image_search_example/img/giraffe.jpg +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/image_search_example/main.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/image_search_example/requirements.txt +0 -0
- {cocoindex-0.1.38/examples/pdf_embedding → cocoindex-0.1.39/examples/manuals_llm_extraction}/.env +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/manuals_llm_extraction/README.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/manuals_llm_extraction/main.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/manuals_llm_extraction/manuals/array.pdf +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/manuals_llm_extraction/manuals/base64.pdf +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/manuals_llm_extraction/manuals/copy.pdf +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/manuals_llm_extraction/manuals/glob.pdf +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/manuals_llm_extraction/pyproject.toml +0 -0
- {cocoindex-0.1.38/examples/text_embedding → cocoindex-0.1.39/examples/pdf_embedding}/.env +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/pdf_embedding/README.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/pdf_embedding/main.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/pdf_embedding/pdf_files/1706.03762v7.pdf +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/pdf_embedding/pdf_files/1810.04805v2.pdf +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/pdf_embedding/pdf_files/rfc8259.pdf +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/pdf_embedding/pyproject.toml +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/product_taxonomy_knowledge_graph/.env +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/product_taxonomy_knowledge_graph/README.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/product_taxonomy_knowledge_graph/img/cocoinsight.png +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/product_taxonomy_knowledge_graph/img/neo4j.png +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/product_taxonomy_knowledge_graph/main.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/product_taxonomy_knowledge_graph/products/p1.json +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/product_taxonomy_knowledge_graph/products/p2.json +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/product_taxonomy_knowledge_graph/products/p3.json +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/product_taxonomy_knowledge_graph/products/p4.json +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/product_taxonomy_knowledge_graph/products/p5.json +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/product_taxonomy_knowledge_graph/products/p6.json +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/product_taxonomy_knowledge_graph/products/p7.json +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/product_taxonomy_knowledge_graph/products/p8.json +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/product_taxonomy_knowledge_graph/products/p9.json +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/product_taxonomy_knowledge_graph/pyproject.toml +0 -0
- {cocoindex-0.1.38/examples/text_embedding_qdrant → cocoindex-0.1.39/examples/text_embedding}/.env +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/text_embedding/README.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/text_embedding/Text_Embedding.ipynb +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/text_embedding/main.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/text_embedding/markdown_files/1706.03762v7.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/text_embedding/markdown_files/1810.04805v2.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/text_embedding/markdown_files/rfc8259.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/text_embedding/pyproject.toml +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/text_embedding_qdrant/README.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/text_embedding_qdrant/main.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/text_embedding_qdrant/markdown_files/rfc8259.md +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/examples/text_embedding_qdrant/pyproject.toml +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/pyproject.toml +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/python/cocoindex/auth_registry.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/python/cocoindex/cli.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/python/cocoindex/functions.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/python/cocoindex/index.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/python/cocoindex/lib.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/python/cocoindex/llm.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/python/cocoindex/py.typed +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/python/cocoindex/runtime.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/python/cocoindex/setup.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/python/cocoindex/sources.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/python/cocoindex/storages.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/python/cocoindex/tests/__init__.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/python/cocoindex/tests/test_convert.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/python/cocoindex/typing.py +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/base/field_attrs.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/base/json_schema.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/base/mod.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/base/schema.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/base/spec.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/base/value.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/builder/mod.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/builder/plan.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/execution/db_tracking.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/execution/db_tracking_setup.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/execution/dumper.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/execution/evaluator.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/execution/indexing_status.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/execution/live_updater.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/execution/memoization.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/execution/mod.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/execution/query.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/execution/row_indexer.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/execution/source_indexer.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/execution/stats.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/lib.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/lib_context.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/llm/anthropic.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/llm/gemini.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/llm/mod.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/llm/ollama.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/llm/openai.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/ops/factory_bases.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/ops/functions/extract_by_llm.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/ops/functions/mod.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/ops/functions/parse_json.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/ops/functions/split_recursively.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/ops/interface.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/ops/mod.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/ops/py_factory.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/ops/registration.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/ops/registry.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/ops/sdk.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/ops/sources/amazon_s3.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/ops/sources/google_drive.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/ops/sources/local_file.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/ops/sources/mod.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/ops/storages/mod.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/ops/storages/neo4j.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/ops/storages/postgres.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/ops/storages/qdrant.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/ops/storages/spec.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/prelude.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/py/convert.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/server.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/service/error.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/service/flows.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/service/mod.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/service/search.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/settings.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/setup/auth_registry.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/setup/components.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/setup/db_metadata.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/setup/driver.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/setup/mod.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/setup/states.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/utils/db.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/utils/fingerprint.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/utils/immutable.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/utils/mod.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/utils/retryable.rs +0 -0
- {cocoindex-0.1.38 → cocoindex-0.1.39}/src/utils/yaml_ser.rs +0 -0
@@ -146,8 +146,9 @@ def demo_flow(flow_builder: cocoindex.FlowBuilder, data_scope: cocoindex.DataSco
|
|
146
146
|
|
147
147
|
:::info
|
148
148
|
|
149
|
-
In live update mode, for each refresh, CocoIndex will
|
149
|
+
In live update mode, for each refresh, CocoIndex will list rows in the data source to figure out the changes based on metadata such as last modified time,
|
150
150
|
and only perform transformations on changed source keys.
|
151
|
+
If nothing changed during the last refresh cycle, only list operations will be performed, which is usually cheap for most data sources.
|
151
152
|
|
152
153
|
:::
|
153
154
|
|
@@ -311,6 +312,38 @@ Following metrics are supported:
|
|
311
312
|
|
312
313
|
## Miscellaneous
|
313
314
|
|
315
|
+
### Getting App Namespace
|
316
|
+
|
317
|
+
You can use the [`app_namespace` setting](initialization#app-namespace) or `COCOINDEX_APP_NAMESPACE` environment variable to specify the app namespace,
|
318
|
+
to organize flows across different environments (e.g., dev, staging, production), team members, etc.
|
319
|
+
|
320
|
+
In the code, You can call `flow.get_app_namespace()` to get the app namespace, and use it to name certain backends. It takes the following arguments:
|
321
|
+
|
322
|
+
* `trailing_delimiter` (optional): a string to append to the app namespace when it's not empty.
|
323
|
+
|
324
|
+
e.g. when the current app namespace is `Staging`, `flow.get_app_namespace(trailing_delimiter='.')` will return `Staging.`.
|
325
|
+
|
326
|
+
For example,
|
327
|
+
|
328
|
+
<Tabs>
|
329
|
+
<TabItem value="python" label="Python" default>
|
330
|
+
|
331
|
+
```python
|
332
|
+
doc_embeddings.export(
|
333
|
+
"doc_embeddings",
|
334
|
+
cocoindex.storages.Qdrant(
|
335
|
+
collection_name=cocoindex.get_app_namespace(trailing_delimiter='__') + "doc_embeddings",
|
336
|
+
...
|
337
|
+
),
|
338
|
+
...
|
339
|
+
)
|
340
|
+
```
|
341
|
+
|
342
|
+
</TabItem>
|
343
|
+
</Tabs>
|
344
|
+
|
345
|
+
It will use `Staging__doc_embeddings` as the collection name if the current app namespace is `Staging`, and use `doc_embeddings` if the app namespace is empty.
|
346
|
+
|
314
347
|
### Target Declarations
|
315
348
|
|
316
349
|
Most time a target storage is created by calling `export()` method on a collector, and this `export()` call comes with configurations needed for the target storage, e.g. options for storage indexes.
|
@@ -105,7 +105,7 @@ A data source may enable one or multiple *change capture mechanisms*:
|
|
105
105
|
* Configured with a [refresh interval](flow_def#refresh-interval), which is generally applicable to all data sources.
|
106
106
|
|
107
107
|
* Specific data sources also provide their specific change capture mechanisms.
|
108
|
-
For example, [`GoogleDrive` source](../ops/sources#googledrive) allows polling recent modified files.
|
108
|
+
For example, [`AmazonS3` source](../ops/sources/#amazons3) watches S3 bucket's change events, and [`GoogleDrive` source](../ops/sources#googledrive) allows polling recent modified files.
|
109
109
|
See documentations for specific data sources.
|
110
110
|
|
111
111
|
Change capture mechanisms enable CocoIndex to continuously capture changes from the source data and update the target data accordingly, under live update mode.
|
@@ -88,9 +88,10 @@ if __name__ == "__main__":
|
|
88
88
|
|
89
89
|
### App Namespace
|
90
90
|
|
91
|
-
The `app_namespace` field helps organize flows across different environments (e.g.,
|
91
|
+
The `app_namespace` field helps organize flows across different environments (e.g., dev, staging, production), team members, etc. When set, it prefixes flow names with the namespace.
|
92
92
|
|
93
|
-
For example, if the namespace is
|
93
|
+
For example, if the namespace is `Staging`, for a flow with name specified as `Flow1` in code, the full name of the flow will be `Staging.Flow1`.
|
94
|
+
You can also get the current app namespace by calling `cocoindex.get_app_namespace()` (see [Getting App Namespace](flow_def#getting-app-namespace) for more details).
|
94
95
|
|
95
96
|
If not set, all flows are in a default unnamed namespace.
|
96
97
|
|
@@ -40,7 +40,7 @@ The spec takes the following fields:
|
|
40
40
|
See [DatabaseConnectionSpec](../core/initialization#databaseconnectionspec) for its specific fields.
|
41
41
|
If not provided, will use the same database as the [internal storage](/docs/core/basics#internal-storage).
|
42
42
|
|
43
|
-
* `table_name` (type: `str`, optional): The name of the table to store to. If unspecified, will
|
43
|
+
* `table_name` (type: `str`, optional): The name of the table to store to. If unspecified, will use the table name `[${AppNamespace}__]${FlowName}__${TargetName}`, e.g. `DemoFlow__doc_embeddings` or `Staging__DemoFlow__doc_embeddings`.
|
44
44
|
|
45
45
|
### Qdrant
|
46
46
|
|
@@ -2,13 +2,14 @@
|
|
2
2
|
Cocoindex is a framework for building and running indexing pipelines.
|
3
3
|
"""
|
4
4
|
from . import functions, query, sources, storages, cli
|
5
|
-
from .flow import FlowBuilder, DataScope, DataSlice, Flow, flow_def
|
5
|
+
from .flow import FlowBuilder, DataScope, DataSlice, Flow, flow_def, transform_flow
|
6
6
|
from .flow import EvaluateAndDumpOptions, GeneratedField
|
7
7
|
from .flow import update_all_flows_async, FlowLiveUpdater, FlowLiveUpdaterOptions
|
8
8
|
from .llm import LlmSpec, LlmApiType
|
9
9
|
from .index import VectorSimilarityMetric, VectorIndexDef, IndexOptions
|
10
10
|
from .auth_registry import AuthEntryReference, add_auth_entry, ref_auth_entry
|
11
11
|
from .lib import *
|
12
|
-
from .setting import
|
12
|
+
from .setting import DatabaseConnectionSpec, Settings, ServerSettings
|
13
|
+
from .setting import get_app_namespace
|
13
14
|
from ._engine import OpArgSchema
|
14
15
|
from .typing import Float32, Float64, LocalDateTime, OffsetDateTime, Range, Vector, Json
|
@@ -44,7 +44,7 @@ def make_engine_value_decoder(
|
|
44
44
|
|
45
45
|
src_type_kind = src_type['kind']
|
46
46
|
|
47
|
-
if dst_annotation is inspect.Parameter.empty:
|
47
|
+
if dst_annotation is None or dst_annotation is inspect.Parameter.empty or dst_annotation is Any:
|
48
48
|
if src_type_kind == 'Struct' or src_type_kind in TABLE_TYPES:
|
49
49
|
raise ValueError(f"Missing type annotation for `{''.join(field_path)}`."
|
50
50
|
f"It's required for {src_type_kind} type.")
|
@@ -8,8 +8,9 @@ import asyncio
|
|
8
8
|
import re
|
9
9
|
import inspect
|
10
10
|
import datetime
|
11
|
+
import functools
|
11
12
|
|
12
|
-
from typing import Any, Callable, Sequence, TypeVar
|
13
|
+
from typing import Any, Callable, Sequence, TypeVar, Generic, get_args, get_origin, Type, NamedTuple
|
13
14
|
from threading import Lock
|
14
15
|
from enum import Enum
|
15
16
|
from dataclasses import dataclass
|
@@ -20,7 +21,7 @@ from . import _engine
|
|
20
21
|
from . import index
|
21
22
|
from . import op
|
22
23
|
from . import setting
|
23
|
-
from .convert import dump_engine_object
|
24
|
+
from .convert import dump_engine_object, encode_engine_value, make_engine_value_decoder
|
24
25
|
from .typing import encode_enriched_type
|
25
26
|
from .runtime import execution_context
|
26
27
|
|
@@ -123,7 +124,7 @@ class _DataSliceState:
|
|
123
124
|
# TODO: We'll support this by an identity transformer or "aliasing" in the future.
|
124
125
|
raise ValueError("DataSlice is already attached to a field")
|
125
126
|
|
126
|
-
class DataSlice:
|
127
|
+
class DataSlice(Generic[T]):
|
127
128
|
"""A data slice represents a slice of data in a flow. It's readonly."""
|
128
129
|
|
129
130
|
_state: _DataSliceState
|
@@ -183,11 +184,11 @@ class DataSlice:
|
|
183
184
|
name, prefix=_to_snake_case(_spec_kind(fn_spec))+'_'),
|
184
185
|
))
|
185
186
|
|
186
|
-
def call(self, func: Callable[[DataSlice], T]) -> T:
|
187
|
+
def call(self, func: Callable[[DataSlice], T], *args, **kwargs) -> T:
|
187
188
|
"""
|
188
189
|
Call a function with the data slice.
|
189
190
|
"""
|
190
|
-
return func(self)
|
191
|
+
return func(self, *args, **kwargs)
|
191
192
|
|
192
193
|
def _data_slice_state(data_slice: DataSlice) -> _DataSliceState:
|
193
194
|
return data_slice._state # pylint: disable=protected-access
|
@@ -642,27 +643,67 @@ async def update_all_flows_async(options: FlowLiveUpdaterOptions) -> dict[str, _
|
|
642
643
|
all_stats = await asyncio.gather(*(_update_flow(name, fl) for (name, fl) in fls.items()))
|
643
644
|
return dict(all_stats)
|
644
645
|
|
645
|
-
|
646
|
-
|
646
|
+
def _get_data_slice_annotation_type(data_slice_type: Type[DataSlice[T]]) -> Type[T] | None:
|
647
|
+
type_args = get_args(data_slice_type)
|
648
|
+
if data_slice_type is DataSlice:
|
649
|
+
return None
|
650
|
+
if get_origin(data_slice_type) != DataSlice or len(type_args) != 1:
|
651
|
+
raise ValueError(f"Expect a DataSlice[T] type, but got {data_slice_type}")
|
652
|
+
return type_args[0]
|
653
|
+
|
654
|
+
_transform_flow_name_builder = _NameBuilder()
|
655
|
+
|
656
|
+
class TransformFlowInfo(NamedTuple):
|
657
|
+
engine_flow: _engine.TransientFlow
|
658
|
+
result_decoder: Callable[[Any], T]
|
659
|
+
|
660
|
+
class TransformFlow(Generic[T]):
|
647
661
|
"""
|
648
662
|
A transient transformation flow that transforms in-memory data.
|
649
663
|
"""
|
650
|
-
|
664
|
+
_flow_fn: Callable[..., DataSlice[T]]
|
665
|
+
_flow_name: str
|
666
|
+
_flow_arg_types: list[Any]
|
667
|
+
_param_names: list[str]
|
668
|
+
|
669
|
+
_lazy_lock: asyncio.Lock
|
670
|
+
_lazy_flow_info: TransformFlowInfo | None = None
|
651
671
|
|
652
672
|
def __init__(
|
653
|
-
self, flow_fn: Callable[..., DataSlice],
|
673
|
+
self, flow_fn: Callable[..., DataSlice[T]],
|
654
674
|
flow_arg_types: Sequence[Any], /, name: str | None = None):
|
675
|
+
self._flow_fn = flow_fn
|
676
|
+
self._flow_name = _transform_flow_name_builder.build_name(name, prefix="_transform_flow_")
|
677
|
+
self._flow_arg_types = list(flow_arg_types)
|
678
|
+
self._lazy_lock = asyncio.Lock()
|
679
|
+
|
680
|
+
def __call__(self, *args, **kwargs) -> DataSlice[T]:
|
681
|
+
return self._flow_fn(*args, **kwargs)
|
655
682
|
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
683
|
+
@property
|
684
|
+
def _flow_info(self) -> TransformFlowInfo:
|
685
|
+
if self._lazy_flow_info is not None:
|
686
|
+
return self._lazy_flow_info
|
687
|
+
return execution_context.run(self._flow_info_async())
|
688
|
+
|
689
|
+
async def _flow_info_async(self) -> TransformFlowInfo:
|
690
|
+
if self._lazy_flow_info is not None:
|
691
|
+
return self._lazy_flow_info
|
692
|
+
async with self._lazy_lock:
|
693
|
+
if self._lazy_flow_info is None:
|
694
|
+
self._lazy_flow_info = await self._build_flow_info_async()
|
695
|
+
return self._lazy_flow_info
|
696
|
+
|
697
|
+
async def _build_flow_info_async(self) -> TransformFlowInfo:
|
698
|
+
flow_builder_state = _FlowBuilderState(name=self._flow_name)
|
699
|
+
sig = inspect.signature(self._flow_fn)
|
700
|
+
if len(sig.parameters) != len(self._flow_arg_types):
|
660
701
|
raise ValueError(
|
661
702
|
f"Number of parameters in the flow function ({len(sig.parameters)}) "
|
662
|
-
"does not match the number of argument types ({len(
|
703
|
+
f"does not match the number of argument types ({len(self._flow_arg_types)})")
|
663
704
|
|
664
705
|
kwargs: dict[str, DataSlice] = {}
|
665
|
-
for (param_name, param), param_type in zip(sig.parameters.items(),
|
706
|
+
for (param_name, param), param_type in zip(sig.parameters.items(), self._flow_arg_types):
|
666
707
|
if param.kind not in (inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
667
708
|
inspect.Parameter.KEYWORD_ONLY):
|
668
709
|
raise ValueError(f"Parameter {param_name} is not a parameter can be passed by name")
|
@@ -670,20 +711,68 @@ class TransientFlow:
|
|
670
711
|
param_name, encode_enriched_type(param_type))
|
671
712
|
kwargs[param_name] = DataSlice(_DataSliceState(flow_builder_state, engine_ds))
|
672
713
|
|
673
|
-
output =
|
714
|
+
output = self._flow_fn(**kwargs)
|
674
715
|
flow_builder_state.engine_flow_builder.set_direct_output(
|
675
716
|
_data_slice_state(output).engine_data_slice)
|
676
|
-
|
677
|
-
|
717
|
+
engine_flow = await flow_builder_state.engine_flow_builder.build_transient_flow_async(execution_context.event_loop)
|
718
|
+
self._param_names = list(sig.parameters.keys())
|
719
|
+
|
720
|
+
engine_return_type = _data_slice_state(output).engine_data_slice.data_type().schema()
|
721
|
+
python_return_type = _get_data_slice_annotation_type(sig.return_annotation)
|
722
|
+
result_decoder = make_engine_value_decoder([], engine_return_type['type'], python_return_type)
|
723
|
+
|
724
|
+
return TransformFlowInfo(engine_flow, result_decoder)
|
678
725
|
|
679
726
|
def __str__(self):
|
680
|
-
return str(self.
|
727
|
+
return str(self._flow_info.engine_flow)
|
681
728
|
|
682
729
|
def __repr__(self):
|
683
|
-
return repr(self.
|
730
|
+
return repr(self._flow_info.engine_flow)
|
684
731
|
|
685
732
|
def internal_flow(self) -> _engine.TransientFlow:
|
686
733
|
"""
|
687
734
|
Get the internal flow.
|
688
735
|
"""
|
689
|
-
return self.
|
736
|
+
return self._flow_info.engine_flow
|
737
|
+
|
738
|
+
def eval(self, *args, **kwargs) -> T:
|
739
|
+
"""
|
740
|
+
Evaluate the transform flow.
|
741
|
+
"""
|
742
|
+
return execution_context.run(self.eval_async(*args, **kwargs))
|
743
|
+
|
744
|
+
async def eval_async(self, *args, **kwargs) -> T:
|
745
|
+
"""
|
746
|
+
Evaluate the transform flow.
|
747
|
+
"""
|
748
|
+
flow_info = await self._flow_info_async()
|
749
|
+
params = []
|
750
|
+
for i, arg in enumerate(self._param_names):
|
751
|
+
if i < len(args):
|
752
|
+
params.append(encode_engine_value(args[i]))
|
753
|
+
elif arg in kwargs:
|
754
|
+
params.append(encode_engine_value(kwargs[arg]))
|
755
|
+
else:
|
756
|
+
raise ValueError(f"Parameter {arg} is not provided")
|
757
|
+
engine_result = await flow_info.engine_flow.evaluate_async(params)
|
758
|
+
return flow_info.result_decoder(engine_result)
|
759
|
+
|
760
|
+
|
761
|
+
def transform_flow() -> Callable[[Callable[..., DataSlice[T]]], TransformFlow[T]]:
|
762
|
+
"""
|
763
|
+
A decorator to wrap the transform function.
|
764
|
+
"""
|
765
|
+
def _transform_flow_wrapper(fn: Callable[..., DataSlice[T]]):
|
766
|
+
sig = inspect.signature(fn)
|
767
|
+
arg_types = []
|
768
|
+
for (param_name, param) in sig.parameters.items():
|
769
|
+
if param.kind not in (inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
770
|
+
inspect.Parameter.KEYWORD_ONLY):
|
771
|
+
raise ValueError(f"Parameter {param_name} is not a parameter can be passed by name")
|
772
|
+
arg_types.append(_get_data_slice_annotation_type(param.annotation))
|
773
|
+
|
774
|
+
_transform_flow = TransformFlow(fn, arg_types)
|
775
|
+
functools.update_wrapper(_transform_flow, fn)
|
776
|
+
return _transform_flow
|
777
|
+
|
778
|
+
return _transform_flow_wrapper
|
@@ -100,8 +100,8 @@ def _register_op_factory(
|
|
100
100
|
return op_args.behavior_version
|
101
101
|
|
102
102
|
class _WrappedClass(executor_cls, _Fallback):
|
103
|
-
|
104
|
-
|
103
|
+
_args_decoders: list[Callable[[Any], Any]]
|
104
|
+
_kwargs_decoders: dict[str, Callable[[str, Any], Any]]
|
105
105
|
_acall: Callable
|
106
106
|
|
107
107
|
def __init__(self, spec):
|
@@ -109,17 +109,17 @@ def _register_op_factory(
|
|
109
109
|
self.spec = spec
|
110
110
|
self._acall = _to_async_call(super().__call__)
|
111
111
|
|
112
|
-
def analyze(self, *args, **kwargs):
|
112
|
+
def analyze(self, *args: _engine.OpArgSchema, **kwargs: _engine.OpArgSchema):
|
113
113
|
"""
|
114
114
|
Analyze the spec and arguments. In this phase, argument types should be validated.
|
115
115
|
It should return the expected result type for the current op.
|
116
116
|
"""
|
117
|
-
self.
|
118
|
-
self.
|
117
|
+
self._args_decoders = []
|
118
|
+
self._kwargs_decoders = {}
|
119
119
|
|
120
120
|
# Match arguments with parameters.
|
121
121
|
next_param_idx = 0
|
122
|
-
for arg in
|
122
|
+
for arg in args:
|
123
123
|
if next_param_idx >= len(expected_args):
|
124
124
|
raise ValueError(
|
125
125
|
f"Too many arguments passed in: {len(args)} > {len(expected_args)}")
|
@@ -128,7 +128,7 @@ def _register_op_factory(
|
|
128
128
|
inspect.Parameter.KEYWORD_ONLY, inspect.Parameter.VAR_KEYWORD):
|
129
129
|
raise ValueError(
|
130
130
|
f"Too many positional arguments passed in: {len(args)} > {next_param_idx}")
|
131
|
-
self.
|
131
|
+
self._args_decoders.append(
|
132
132
|
make_engine_value_decoder(
|
133
133
|
[arg_name], arg.value_type['type'], arg_param.annotation))
|
134
134
|
if arg_param.kind != inspect.Parameter.VAR_POSITIONAL:
|
@@ -146,7 +146,7 @@ def _register_op_factory(
|
|
146
146
|
if expected_arg is None:
|
147
147
|
raise ValueError(f"Unexpected keyword argument passed in: {kwarg_name}")
|
148
148
|
arg_param = expected_arg[1]
|
149
|
-
self.
|
149
|
+
self._kwargs_decoders[kwarg_name] = make_engine_value_decoder(
|
150
150
|
[kwarg_name], kwarg.value_type['type'], arg_param.annotation)
|
151
151
|
|
152
152
|
missing_args = [name for (name, arg) in expected_kwargs
|
@@ -174,8 +174,8 @@ def _register_op_factory(
|
|
174
174
|
await _to_async_call(setup_method)()
|
175
175
|
|
176
176
|
async def __call__(self, *args, **kwargs):
|
177
|
-
|
178
|
-
|
177
|
+
decoded_args = (decoder(arg) for decoder, arg in zip(self._args_decoders, args))
|
178
|
+
decoded_kwargs = {arg_name: self._kwargs_decoders[arg_name](arg)
|
179
179
|
for arg_name, arg in kwargs.items()}
|
180
180
|
|
181
181
|
if op_args.gpu:
|
@@ -185,9 +185,9 @@ def _register_op_factory(
|
|
185
185
|
# For now, we use a lock to ensure only one task is executed at a time.
|
186
186
|
# TODO: Implement multi-processing dispatching.
|
187
187
|
async with _gpu_dispatch_lock:
|
188
|
-
output = await self._acall(*
|
188
|
+
output = await self._acall(*decoded_args, **decoded_kwargs)
|
189
189
|
else:
|
190
|
-
output = await self._acall(*
|
190
|
+
output = await self._acall(*decoded_args, **decoded_kwargs)
|
191
191
|
return encode_engine_value(output)
|
192
192
|
|
193
193
|
_WrappedClass.__name__ = executor_cls.__name__
|
@@ -50,7 +50,7 @@ class SimpleSemanticsQueryHandler:
|
|
50
50
|
if engine_handler is None:
|
51
51
|
engine_handler = _engine.SimpleSemanticsQueryHandler(
|
52
52
|
flow.internal_flow(), target_name,
|
53
|
-
fl.
|
53
|
+
fl.TransformFlow(query_transform_flow, [str]).internal_flow(),
|
54
54
|
default_similarity_metric.value)
|
55
55
|
engine_handler.register_query_handler(name)
|
56
56
|
return engine_handler
|
@@ -49,7 +49,7 @@ def _load_field(target: dict[str, Any], name: str, env_name: str, required: bool
|
|
49
49
|
class Settings:
|
50
50
|
"""Settings for the cocoindex library."""
|
51
51
|
database: DatabaseConnectionSpec
|
52
|
-
app_namespace: str
|
52
|
+
app_namespace: str = ""
|
53
53
|
|
54
54
|
@classmethod
|
55
55
|
def from_env(cls) -> Self:
|
@@ -75,12 +75,11 @@ pub struct AnalyzedTransientFlow {
|
|
75
75
|
impl AnalyzedTransientFlow {
|
76
76
|
pub async fn from_transient_flow(
|
77
77
|
transient_flow: spec::TransientFlowSpec,
|
78
|
-
registry: &ExecutorFactoryRegistry,
|
79
78
|
py_exec_ctx: Option<crate::py::PythonExecutionContext>,
|
80
79
|
) -> Result<Self> {
|
81
80
|
let ctx = analyzer::build_flow_instance_context(&transient_flow.name, py_exec_ctx);
|
82
81
|
let (output_type, data_schema, execution_plan_fut) =
|
83
|
-
analyzer::analyze_transient_flow(&transient_flow, &ctx
|
82
|
+
analyzer::analyze_transient_flow(&transient_flow, &ctx)?;
|
84
83
|
Ok(Self {
|
85
84
|
transient_flow_instance: transient_flow,
|
86
85
|
data_schema,
|
@@ -1302,14 +1302,17 @@ pub fn analyze_flow(
|
|
1302
1302
|
pub fn analyze_transient_flow<'a>(
|
1303
1303
|
flow_inst: &TransientFlowSpec,
|
1304
1304
|
flow_ctx: &'_ Arc<FlowInstanceContext>,
|
1305
|
-
registry: &'a ExecutorFactoryRegistry,
|
1306
1305
|
) -> Result<(
|
1307
1306
|
EnrichedValueType,
|
1308
1307
|
FlowSchema,
|
1309
1308
|
impl Future<Output = Result<TransientExecutionPlan>> + Send + 'a,
|
1310
1309
|
)> {
|
1311
1310
|
let mut root_data_scope = DataScopeBuilder::new();
|
1312
|
-
let
|
1311
|
+
let registry = crate::ops::executor_factory_registry();
|
1312
|
+
let analyzer_ctx = AnalyzerContext {
|
1313
|
+
registry: ®istry,
|
1314
|
+
flow_ctx,
|
1315
|
+
};
|
1313
1316
|
let mut input_fields = vec![];
|
1314
1317
|
for field in flow_inst.input_fields.iter() {
|
1315
1318
|
let analyzed_field = root_data_scope.add_field(field.name.clone(), &field.value_type)?;
|
@@ -1,10 +1,11 @@
|
|
1
|
-
use crate::prelude
|
1
|
+
use crate::{prelude::*, py::Pythonized};
|
2
2
|
|
3
3
|
use pyo3::{exceptions::PyException, prelude::*};
|
4
|
+
use pyo3_async_runtimes::tokio::future_into_py;
|
4
5
|
use std::{collections::btree_map, ops::Deref};
|
5
6
|
|
6
7
|
use super::analyzer::{
|
7
|
-
|
8
|
+
AnalyzerContext, CollectorBuilder, DataScopeBuilder, OpScope, build_flow_instance_context,
|
8
9
|
};
|
9
10
|
use crate::{
|
10
11
|
base::{
|
@@ -83,6 +84,10 @@ impl DataType {
|
|
83
84
|
pub fn __repr__(&self) -> String {
|
84
85
|
self.__str__()
|
85
86
|
}
|
87
|
+
|
88
|
+
pub fn schema(&self) -> Pythonized<schema::EnrichedValueType> {
|
89
|
+
Pythonized(self.schema.clone())
|
90
|
+
}
|
86
91
|
}
|
87
92
|
|
88
93
|
#[pyclass]
|
@@ -142,7 +147,7 @@ impl DataSlice {
|
|
142
147
|
spec::ValueMapping::Constant { .. } => {
|
143
148
|
return Err(PyException::new_err(
|
144
149
|
"field access not supported for literal",
|
145
|
-
))
|
150
|
+
));
|
146
151
|
}
|
147
152
|
};
|
148
153
|
Ok(Some(DataSlice {
|
@@ -585,11 +590,11 @@ impl FlowBuilder {
|
|
585
590
|
Ok(py::Flow(flow_ctx))
|
586
591
|
}
|
587
592
|
|
588
|
-
pub fn
|
593
|
+
pub fn build_transient_flow_async<'py>(
|
589
594
|
&self,
|
590
|
-
py: Python<'
|
595
|
+
py: Python<'py>,
|
591
596
|
py_event_loop: Py<PyAny>,
|
592
|
-
) -> PyResult<py
|
597
|
+
) -> PyResult<Bound<'py, PyAny>> {
|
593
598
|
if self.direct_input_fields.is_empty() {
|
594
599
|
return Err(PyException::new_err("expect at least one direct input"));
|
595
600
|
}
|
@@ -605,16 +610,14 @@ impl FlowBuilder {
|
|
605
610
|
output_value: direct_output_value.clone(),
|
606
611
|
};
|
607
612
|
let py_ctx = crate::py::PythonExecutionContext::new(py, py_event_loop);
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
.into_py_result()?;
|
617
|
-
Ok(py::TransientFlow(Arc::new(analyzed_flow)))
|
613
|
+
|
614
|
+
future_into_py(py, async move {
|
615
|
+
let analyzed_flow =
|
616
|
+
super::AnalyzedTransientFlow::from_transient_flow(spec, Some(py_ctx))
|
617
|
+
.await
|
618
|
+
.into_py_result()?;
|
619
|
+
Ok(py::TransientFlow(Arc::new(analyzed_flow)))
|
620
|
+
})
|
618
621
|
}
|
619
622
|
|
620
623
|
pub fn __str__(&self) -> String {
|
@@ -695,7 +698,8 @@ impl FlowBuilder {
|
|
695
698
|
} else if !common_scope.is_op_scope_descendant(scope) {
|
696
699
|
api_bail!(
|
697
700
|
"expect all arguments share the common scope, got {} and {} exclusive to each other",
|
698
|
-
common_scope,
|
701
|
+
common_scope,
|
702
|
+
scope
|
699
703
|
);
|
700
704
|
}
|
701
705
|
}
|
@@ -703,7 +707,8 @@ impl FlowBuilder {
|
|
703
707
|
if !target_scope.is_op_scope_descendant(common_scope) {
|
704
708
|
api_bail!(
|
705
709
|
"the field can only be attached to a scope or sub-scope of the input value. Target scope: {}, input scope: {}",
|
706
|
-
target_scope,
|
710
|
+
target_scope,
|
711
|
+
common_scope
|
707
712
|
);
|
708
713
|
}
|
709
714
|
common_scope = target_scope;
|
@@ -1,3 +1,4 @@
|
|
1
|
+
use crate::execution::evaluator::evaluate_transient_flow;
|
1
2
|
use crate::prelude::*;
|
2
3
|
|
3
4
|
use crate::base::schema::{FieldSchema, ValueType};
|
@@ -11,6 +12,7 @@ use crate::ops::{interface::ExecutorFactory, py_factory::PyFunctionFactory, regi
|
|
11
12
|
use crate::server::{self, ServerSettings};
|
12
13
|
use crate::settings::Settings;
|
13
14
|
use crate::setup;
|
15
|
+
use pyo3::IntoPyObjectExt;
|
14
16
|
use pyo3::{exceptions::PyException, prelude::*};
|
15
17
|
use pyo3_async_runtimes::tokio::future_into_py;
|
16
18
|
use std::collections::btree_map;
|
@@ -349,6 +351,27 @@ impl TransientFlow {
|
|
349
351
|
pub fn __repr__(&self) -> String {
|
350
352
|
self.__str__()
|
351
353
|
}
|
354
|
+
|
355
|
+
pub fn evaluate_async<'py>(
|
356
|
+
&self,
|
357
|
+
py: Python<'py>,
|
358
|
+
args: Vec<Bound<'py, PyAny>>,
|
359
|
+
) -> PyResult<Bound<'py, PyAny>> {
|
360
|
+
let flow = self.0.clone();
|
361
|
+
let input_values: Vec<value::Value> = std::iter::zip(
|
362
|
+
self.0.transient_flow_instance.input_fields.iter(),
|
363
|
+
args.into_iter(),
|
364
|
+
)
|
365
|
+
.map(|(input_schema, arg)| value_from_py_object(&input_schema.value_type.typ, &arg))
|
366
|
+
.collect::<PyResult<_>>()?;
|
367
|
+
|
368
|
+
future_into_py(py, async move {
|
369
|
+
let result = evaluate_transient_flow(&flow, &input_values)
|
370
|
+
.await
|
371
|
+
.into_py_result()?;
|
372
|
+
Python::with_gil(|py| value_to_py_object(py, &result)?.into_py_any(py))
|
373
|
+
})
|
374
|
+
}
|
352
375
|
}
|
353
376
|
|
354
377
|
#[pyclass]
|
File without changes
|
File without changes
|
{cocoindex-0.1.38 → cocoindex-0.1.39}/.github/ISSUE_TEMPLATE//360/237/220/233-bug-report.md"
RENAMED
File without changes
|
{cocoindex-0.1.38 → cocoindex-0.1.39}/.github/ISSUE_TEMPLATE//360/237/222/241-feature-request.md"
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|