diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..d9cdb75 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,60 @@ +name: release + +on: + push: + tags: + - "v*" + +permissions: + contents: read + +jobs: + test: + uses: ./.github/workflows/test.yaml + secrets: inherit + + build: + runs-on: ubuntu-latest + needs: test + + steps: + - name: Check out python-select-ai repository code + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 + + - name: Set up Python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 + with: + python-version: "3.13" + + - name: Build release distributions + run: | + python -m pip install --upgrade pip build twine + python -m build + twine check dist/* + + - name: Upload release distributions + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: release-distributions + path: dist/ + if-no-files-found: error + + publish: + runs-on: ubuntu-latest + needs: build + environment: + name: pypi + url: https://pypi.org/p/select_ai + permissions: + contents: read + id-token: write + + steps: + - name: Download release distributions + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 + with: + name: release-distributions + path: dist/ + + - name: Publish release distributions to PyPI + uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # release/v1 diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 9ab95e6..27ce26f 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -1,5 +1,7 @@ name: select_ai_py_tests -on: push +on: + push: + workflow_call: permissions: contents: read diff --git a/MANIFEST.in b/MANIFEST.in index e42ab22..0363fa4 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1,3 @@ recursive-include tests *.py recursive-include samples *.py +recursive-include recipes *.py diff --git a/doc/source/image/select_ai_cli_demo.gif b/doc/source/image/select_ai_cli_demo.gif index 4235309..2483fd2 100644 Binary files a/doc/source/image/select_ai_cli_demo.gif and b/doc/source/image/select_ai_cli_demo.gif differ diff --git a/doc/source/image/select_ai_cli_demo.png b/doc/source/image/select_ai_cli_demo.png index 260f184..3ace261 100644 Binary files a/doc/source/image/select_ai_cli_demo.png and b/doc/source/image/select_ai_cli_demo.png differ diff --git a/doc/source/index.rst b/doc/source/index.rst index 00ece82..0a2dc6a 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -48,7 +48,7 @@ Provider :numbered: :maxdepth: 3 - user_guide/provider.rst + Provider Credential ========== @@ -78,15 +78,14 @@ Profile user_guide/profile.rst -Command Line Interface -====================== +Async Profile +============= .. toctree:: :numbered: :maxdepth: 3 - user_guide/cli.rst - + user_guide/async_profile.rst Conversation ============ @@ -135,6 +134,24 @@ AI Agent user_guide/agent.rst +Async AI Agent +============== + +.. toctree:: + :numbered: + :maxdepth: 3 + + user_guide/async_agent.rst + +Command Line Interface +====================== + +.. toctree:: + :numbered: + :maxdepth: 3 + + user_guide/cli.rst + Web Frameworks ============== @@ -143,3 +160,12 @@ Web Frameworks :maxdepth: 3 user_guide/web_frameworks.rst + +Concurrent Prompt Processing +============================ + +.. toctree:: + :numbered: + :maxdepth: 3 + + user_guide/concurrent_prompt_processing.rst diff --git a/doc/source/user_guide/actions.rst b/doc/source/user_guide/actions.rst index 8cad7d5..82fafec 100644 --- a/doc/source/user_guide/actions.rst +++ b/doc/source/user_guide/actions.rst @@ -1,45 +1,154 @@ .. _actions: -An action in Select AI is a keyword that instructs Select AI to perform different behavior when acting on the prompt. +An action in Select AI is a keyword that instructs Select AI to perform +different behavior when acting on the prompt. + +Most applications use the convenience methods on ``Profile`` or +``AsyncProfile``, such as ``show_sql()``, ``run_sql()``, ``narrate()``, and +``chat()``. Use ``generate(..., action=...)`` when you want to choose the +action dynamically at runtime. + +The default action for ``generate()`` is ``select_ai.Action.RUNSQL``. ******************** Supported Actions ******************** -Following list of actions can be performed using ``select_ai`` +The following actions can be performed using ``select_ai``: .. list-table:: Select AI Actions - :header-rows: 1 - :widths: 20 30 50 - :align: left - - * - Actions - - Enum - - Description - * - chat - - ``select_ai.Action.CHAT`` - - Enables general conversations with the LLM, potentially for clarifying prompts, exploring data, or generating content. - * - explainsql - - ``select_ai.Action.EXPLAINSQL`` - - Explain the generated SQL query - * - narrate - - ``select_ai.Action.NARRATE`` - - Explains the output of the query in natural language, making the results accessible to users without deep technical expertise. - * - runsql - - ``select_ai.Action.RUNSQL`` - - Executes a SQL query generated from a natural language prompt. This is the default action. - * - showprompt - - ``select_ai.Action.SHOWPROMPT`` - - Show the details of the prompt sent to LLM - * - showsql - - ``select_ai.Action.SHOWSQL`` - - Displays the generated SQL statement without executing it. - * - summarize - - ``select_ai.Action.SUMMARIZE`` - - Generate summary of your large texts - * - feedback - - ``select_ai.Action.FEEDBACK`` - - Provide feedback to improve accuracy of the generated SQL - * - translate - - ``select_ai.Action.TRANSLATE`` - - Translate text from one language to another + :header-rows: 1 + :widths: 20 30 50 + :align: left + + * - Action + - Enum + - Description + * - chat + - ``select_ai.Action.CHAT`` + - Enables general conversations with the LLM, potentially for clarifying + prompts, exploring data, or generating content. + * - explainsql + - ``select_ai.Action.EXPLAINSQL`` + - Explains the generated SQL query. + * - narrate + - ``select_ai.Action.NARRATE`` + - Executes generated SQL and explains the output in natural language. + * - runsql + - ``select_ai.Action.RUNSQL`` + - Executes SQL generated from a natural language prompt. This is the + default action for ``generate()``. + * - showprompt + - ``select_ai.Action.SHOWPROMPT`` + - Shows the prompt sent to the LLM. + * - showsql + - ``select_ai.Action.SHOWSQL`` + - Displays the generated SQL statement without executing it. + * - summarize + - ``select_ai.Action.SUMMARIZE`` + - Generates a summary of inline content or content referenced by a URI. + * - feedback + - ``select_ai.Action.FEEDBACK`` + - Provides feedback to improve the accuracy of generated SQL. + * - translate + - ``select_ai.Action.TRANSLATE`` + - Translates text from one language to another. + +Action methods +============== + +.. list-table:: Action to method mapping + :header-rows: 1 + :widths: 30 35 35 + :align: left + + * - Action + - Convenience method + - Return type + * - ``RUNSQL`` + - ``profile.run_sql(prompt)`` + - ``pandas.DataFrame`` + * - ``SHOWSQL`` + - ``profile.show_sql(prompt)`` + - ``str`` + * - ``EXPLAINSQL`` + - ``profile.explain_sql(prompt)`` + - ``str`` + * - ``NARRATE`` + - ``profile.narrate(prompt)`` + - ``str`` + * - ``CHAT`` + - ``profile.chat(prompt)`` + - ``str`` + * - ``SHOWPROMPT`` + - ``profile.show_prompt(prompt)`` + - ``str`` + * - ``SUMMARIZE`` + - ``profile.summarize(...)`` + - ``str`` + * - ``TRANSLATE`` + - ``profile.translate(...)`` + - ``str`` + +Choosing an action +================== + +Use ``show_sql`` before ``run_sql`` when you want to inspect generated SQL +before executing it. Use ``run_sql`` when the application should return a +tabular result. Use ``narrate`` when users need a natural language answer +instead of a table. Use ``explain_sql`` and ``show_prompt`` when tuning profile +attributes, object lists, comments, constraints, or feedback. + +Examples +======== + +Use a convenience method: + +.. code-block:: python + + profile = select_ai.Profile(profile_name="oci_ai_profile") + sql = profile.show_sql(prompt="How many promotions?") + +Use ``generate`` with an explicit action: + +.. code-block:: python + + profile = select_ai.Profile(profile_name="oci_ai_profile") + + sql = profile.generate( + prompt="How many promotions?", + action=select_ai.Action.SHOWSQL, + ) + + df = profile.generate( + prompt="How many promotions?", + action=select_ai.Action.RUNSQL, + ) + +Use an action selected at runtime: + +.. code-block:: python + + action = select_ai.Action("showsql") + result = profile.generate( + prompt="How many promotions?", + action=action, + ) + +Streaming +========= + +Streaming is supported for text-returning generation actions: +``CHAT``, ``NARRATE``, ``EXPLAINSQL``, ``SHOWSQL``, and ``SHOWPROMPT``. +Streaming is not supported for ``RUNSQL`` because it returns a +``pandas.DataFrame``. + +.. code-block:: python + + for chunk in profile.generate( + prompt="What is OCI?", + action=select_ai.Action.CHAT, + stream=True, + chunk_size=4096, + ): + print(chunk, end="") diff --git a/doc/source/user_guide/agent.rst b/doc/source/user_guide/agent.rst index f2059da..aad3c00 100644 --- a/doc/source/user_guide/agent.rst +++ b/doc/source/user_guide/agent.rst @@ -2,7 +2,8 @@ ``select_ai.agent`` adds a thin Python layer over Oracle Autonomous Database's ``DBMS_CLOUD_AI_AGENT`` package so you can define tools, compose tasks, wire up -agents and run teams from Python using the existing select_ai connection objects +agents and run teams from Python using the existing Select AI connection +objects. - Keep agent state and orchestration in the database @@ -11,6 +12,25 @@ agents and run teams from Python using the existing select_ai connection objects - Group agents into teams and invoke them with a single API call +Agent workflows build on the same setup used by profiles: connect to Oracle +Database, create or reuse a Select AI profile, create credentials for any +external service used by tools, and grant network access for external +endpoints. See :ref:`Connection `, :ref:`Profile `, +:ref:`Credential `, and :ref:`Privileges `. + +The usual agent workflow is: + +* Create tools that an agent can use. +* Create tasks that describe the work and list the tools available for that + task. +* Create an agent with a role and an LLM profile. +* Create a team that pairs agents with tasks. +* Run the team with a user prompt. + +Tools, tasks, agents, and teams are database objects. Use ``replace=True`` when +you want to recreate an existing object with the same name, and ``force=True`` +when cleanup should succeed even if the object does not exist. + .. latex:clearpage:: ******** @@ -21,6 +41,10 @@ A callable which Select AI agent can invoke to accomplish a certain task. Users can either register built-in tools or create a custom tool using a PL/SQL stored procedure. +Use focused tools with clear instructions. The task and agent prompts decide +when tools are used, so tool names, descriptions, and instructions should be +specific enough for the model to choose the right tool. + Supported Tools +++++++++++++++ @@ -53,7 +77,7 @@ Python layer and persist the tool in the Database using - ``select_ai.agent.Tool.create_slack_notification_tool`` - - ``tool_name`` - ``credential_name`` - - ``slack_channel`` + - ``channel`` * - ``WEBSEARCH`` - ``select_ai.agent.Tool.create_websearch_tool`` - - ``tool_name`` @@ -67,6 +91,31 @@ Python layer and persist the tool in the Database using - - ``tool_name`` - ``profile_name`` +Tool selection +++++++++++++++ + +.. list-table:: When to use each tool + :header-rows: 1 + :widths: 25 75 + :align: left + + * - Tool type + - Use case + * - ``SQL`` + - Ask questions over database objects using a Select AI profile. + * - ``RAG`` + - Answer questions using content indexed by a vector index profile. + * - ``WEBSEARCH`` + - Search public web content using a web search credential. + * - ``SLACK`` + - Send a Slack notification from an agent workflow. + * - ``EMAIL`` + - Send an email notification from an agent workflow. + * - ``PL/SQL custom tool`` + - Call a database procedure or function for application-specific work. + +Notification and web search tools require credentials and network access for +the external service. SQL and RAG tools require existing Select AI profiles. .. latex:clearpage:: @@ -108,7 +157,7 @@ output:: profile_name='oci_ai_profile', recipient=None, sender=None, - slack_channel=None, + channel=None, smtp_host=None), tool_inputs=None, tool_type=) @@ -162,6 +211,10 @@ Create Task In the following task, we use the ``MOVIE_SQL_TOOL`` created in the previous step +The ``instruction`` is the main task prompt. Use placeholders such as +``{query}`` when the user prompt should be inserted into the task. The +``tools`` list limits which tools the agent can use for the task. + .. literalinclude:: ../../../samples/agent/task_create.py :language: python :lines: 14- @@ -203,6 +256,10 @@ optional description. The attributes must include key agent properties such as ``profile_name`` which specifies the LLM profile used for prompt generation and ``role``, which outlines the agent’s intended role and behavioral context. +The agent profile supplies the model used for planning and reasoning. The role +should describe the agent's domain, boundaries, and expected behavior. Keep the +role specific to the tasks assigned to the agent. + .. autoclass:: select_ai.agent.AgentAttributes :members: @@ -243,6 +300,22 @@ pairings, allowing users to assign specific tasks to designated agents. User can perform multiple tasks by assigning the same agent to different tasks. The ``process`` attribute defines how tasks should be executed. +Currently, ``process="sequential"`` is used to execute task assignments in +order. Reuse the same agent in multiple team entries when the agent should +perform multiple tasks. + +For example: + +.. code-block:: python + + attributes = TeamAttributes( + agents=[ + {"name": "MOVIE_ANALYST", "task": "ANALYZE_MOVIE_TASK"}, + {"name": "MOVIE_ANALYST", "task": "SUMMARIZE_MOVIE_TASK"}, + ], + process="sequential", + ) + .. autoclass:: select_ai.agent.TeamAttributes :members: @@ -256,6 +329,21 @@ The ``process`` attribute defines how tasks should be executed. Run Team ++++++++ +``Team.run(...)`` starts the team workflow. The ``prompt`` argument is passed to +the task and can be referenced by task instructions using ``{query}``. +``params`` can include ``conversation_id`` to associate multiple runs with the +same conversation and ``variables`` to pass additional key-value inputs. + +.. code-block:: python + + result = team.run( + prompt="Could you list the movies in the database?", + params={ + "conversation_id": conversation_id, + "variables": {"audience": "analyst"}, + }, + ) + .. literalinclude:: ../../../samples/agent/team_create.py :language: python :lines: 14- @@ -292,8 +380,12 @@ service. The specification describes the team composition and the associated agent, task, and tool definitions that are needed to recreate the team. ``Team.export_team()`` returns the specification as a JSON string by default. -``Team.import_team()`` accepts either that JSON string or a Python mapping. On -import, ``profile_name`` identifies the Select AI profile to use in the target +``Team.import_team()`` accepts either that JSON string or a Python mapping +containing the same team definition structure. In most cases, pass a ``dict``, +for example the result of ``json.loads(exported_spec)``. Other +JSON-serializable `collections.abc.Mapping `__ +objects, such as ``OrderedDict``, can also be used. On import, +``profile_name`` identifies the Select AI profile to use in the target database. ``team_name`` can be provided to create the imported team under a new name; this is useful when importing into the same database as the source team. @@ -333,6 +425,25 @@ storage, ``Team.export_team()`` writes the specification to the location and returns ``None``. When importing from object storage, pass the same credential and location instead of ``specification``. +Lifecycle helpers ++++++++++++++++++ + +All agent object types support list, fetch, enable, disable, and delete +operations. + +.. code-block:: python + + for tool in select_ai.agent.Tool.list(): + print(tool.tool_name) + + task = select_ai.agent.Task.fetch("ANALYZE_MOVIE_TASK") + agent = select_ai.agent.Agent.fetch("MOVIE_ANALYST") + team = select_ai.agent.Team.fetch("MOVIE_AGENT_TEAM") + + team.disable() + team.enable() + team.delete(force=True) + .. latex:clearpage:: ***************** @@ -388,14 +499,3 @@ output:: promoting advanced AI technologies, including products like ChatGPT, and provides information about their research, products, and mission to ensure that artificial general intelligence benefits all of humanity. - - -************** -Async AI Agent -************** - -.. toctree:: - :numbered: - :maxdepth: 3 - - async_agent.rst diff --git a/doc/source/user_guide/async_agent.rst b/doc/source/user_guide/async_agent.rst index 3c2cf8a..df17e2d 100644 --- a/doc/source/user_guide/async_agent.rst +++ b/doc/source/user_guide/async_agent.rst @@ -1,8 +1,41 @@ .. _async_agent: ``select_ai.agent`` also provides async interfaces to be used with -``async`` / ``await`` keywords +``async`` / ``await`` keywords. Use these classes in applications that already +use ``asyncio`` and ``select_ai.async_connect()`` or +``select_ai.create_pool_async()``. +The async agent object model mirrors the synchronous agent object model: + +.. list-table:: Sync and async agent APIs + :header-rows: 1 + :widths: 50 50 + :align: left + + * - Sync class + - Async class + * - ``select_ai.agent.Tool`` + - ``select_ai.agent.AsyncTool`` + * - ``select_ai.agent.Task`` + - ``select_ai.agent.AsyncTask`` + * - ``select_ai.agent.Agent`` + - ``select_ai.agent.AsyncAgent`` + * - ``select_ai.agent.Team`` + - ``select_ai.agent.AsyncTeam`` + +Create or reuse the same database objects as the synchronous APIs. Async +methods must be awaited, and async list methods return async iterators. + +.. code-block:: python + + await select_ai.async_connect(user=user, password=password, dsn=dsn) + + async for tool in select_ai.agent.AsyncTool.list(): + print(tool.tool_name) + +Tools, tasks, agents, and teams are database objects. Use ``replace=True`` when +you want to recreate an existing object with the same name, and ``force=True`` +when cleanup should succeed even if the object does not exist. .. list-table:: Select AI Async Agent Tools :header-rows: 1 @@ -27,7 +60,7 @@ - ``select_ai.agent.AsyncTool.create_slack_notification_tool`` - - ``tool_name`` - ``credential_name`` - - ``slack_channel`` + - ``channel`` * - ``WEBSEARCH`` - ``select_ai.agent.AsyncTool.create_websearch_tool`` - - ``tool_name`` @@ -41,6 +74,14 @@ - - ``tool_name`` - ``profile_name`` +Notification and web search tools require credentials and network access for +the external service. SQL and RAG tools require existing Select AI profiles. + +Tool selection follows the same guidance as :ref:`Agent `: use SQL +tools for database questions, RAG tools for vector-index-backed content, +notification tools for Slack or email, web search tools for public web content, +and PL/SQL tools for application-specific database logic. + ************* ``AsyncTool`` ************* @@ -73,7 +114,7 @@ output:: profile_name='oci_ai_profile', recipient=None, sender=None, - slack_channel=None, + channel=None, smtp_host=None), tool_inputs=None, tool_type=) @@ -111,6 +152,10 @@ Create Task In the following task, we use the ``MOVIE_SQL_TOOL`` created in the previous step +The ``instruction`` is the main task prompt. Use placeholders such as +``{query}`` when the user prompt should be inserted into the task. The +``tools`` list limits which tools the agent can use for the task. + .. literalinclude:: ../../../samples/agent/async/task_create.py :language: python :lines: 13- @@ -194,6 +239,22 @@ AsyncTeam Run Team ++++++++ +``AsyncTeam.run(...)`` starts the team workflow. The ``prompt`` argument is +passed to the task and can be referenced by task instructions using +``{query}``. ``params`` can include ``conversation_id`` to associate multiple +runs with the same conversation and ``variables`` to pass additional key-value +inputs. + +.. code-block:: python + + result = await team.run( + prompt="Could you list the movies in the database?", + params={ + "conversation_id": conversation_id, + "variables": {"audience": "analyst"}, + }, + ) + .. literalinclude:: ../../../samples/agent/async/team_create.py :language: python :lines: 14- @@ -232,10 +293,13 @@ agent, task, and tool definitions that are needed to recreate the team. ``AsyncTeam.export_team()`` returns the specification as a JSON string by default. ``AsyncTeam.import_team()`` accepts either that JSON string or a Python -mapping. On import, ``profile_name`` identifies the Select AI profile to use in -the target database. ``team_name`` can be provided to create the imported team -under a new name; this is useful when importing into the same database as the -source team. +mapping containing the same team definition structure. In most cases, pass a +``dict``, for example the result of ``json.loads(exported_spec)``. Other +JSON-serializable `collections.abc.Mapping `__ +objects, such as ``OrderedDict``, can also be used. On import, +``profile_name`` identifies the Select AI profile to use in the target +database. ``team_name`` can be provided to create the imported team under a new +name; this is useful when importing into the same database as the source team. If imported object names conflict with existing agents, tasks, tools, or teams, set ``force=True`` to let the database replace the conflicting objects. Use this @@ -275,6 +339,27 @@ credential and location instead of ``specification``. .. latex:clearpage:: +Lifecycle helpers ++++++++++++++++++ + +All async agent object types support list, fetch, enable, disable, and delete +operations. + +.. code-block:: python + + async for tool in select_ai.agent.AsyncTool.list(): + print(tool.tool_name) + + task = await select_ai.agent.AsyncTask.fetch("ANALYZE_MOVIE_TASK") + agent = await select_ai.agent.AsyncAgent.fetch("MOVIE_ANALYST") + team = await select_ai.agent.AsyncTeam.fetch("MOVIE_AGENT_TEAM") + + await team.disable() + await team.enable() + await team.delete(force=True) + +.. latex:clearpage:: + List Teams ++++++++++ diff --git a/doc/source/user_guide/async_profile.rst b/doc/source/user_guide/async_profile.rst index b602f5e..de1c9f8 100644 --- a/doc/source/user_guide/async_profile.rst +++ b/doc/source/user_guide/async_profile.rst @@ -1,10 +1,76 @@ .. _async_profile: -An AsyncProfile object can be created with ``select_ai.AsyncProfile()`` -``AsyncProfile`` support use of concurrent programming with `asyncio `__. +An ``AsyncProfile`` object can be created with ``select_ai.AsyncProfile()``. +``AsyncProfile`` supports concurrent programming with `asyncio `__. Unless explicitly noted as synchronous, the ``AsyncProfile`` methods should be used with ``await``. +Use ``AsyncProfile`` in applications that already use +``select_ai.async_connect()`` or ``select_ai.create_pool_async()``. The async +profile object uses the same database profile objects as ``Profile``; only the +Python API style changes. + +Because ``AsyncProfile`` initializes itself from the database, create or fetch +instances with ``await``: + +.. code-block:: python + + async_profile = await select_ai.AsyncProfile( + profile_name="async_oci_ai_profile", + ) + +Before creating an async profile, make sure the database user has the required +privileges, a credential for the AI provider, network access to the provider +endpoint, and access to the database objects included in the profile. See +:ref:`Privileges `, :ref:`Credential `, +:ref:`Provider `, and +:ref:`ProfileAttributes `. + +Async profile lifecycle +======================= + +The usual async profile lifecycle is: + +* Create or reuse an async database connection or async pool. +* Create a provider object. +* Create ``ProfileAttributes`` with the provider, credential name, and object + list. +* Create the profile with ``await select_ai.AsyncProfile(...)``. +* Reuse the profile later by name. +* Update profile attributes when provider settings or object scope changes. +* Delete profiles that are no longer needed. + +``replace=True`` recreates a profile when a profile with the same name already +exists. ``merge=True`` fetches the existing profile and updates it with the +non-null attributes passed by the caller. + +Async profile actions +===================== + +.. list-table:: Common async profile actions + :header-rows: 1 + :widths: 25 75 + :align: left + + * - Method + - Description + * - ``show_sql()`` + - Generates SQL for a natural language prompt without executing it. + * - ``run_sql()`` + - Generates SQL, executes it, and returns a ``pandas.DataFrame``. + * - ``narrate()`` + - Generates SQL, executes it, and returns a natural language answer. + * - ``explain_sql()`` + - Explains the generated SQL for a prompt. + * - ``show_prompt()`` + - Shows the prompt sent to the model. + * - ``chat()`` + - Sends a general chat prompt to the model. + * - ``summarize()`` + - Summarizes inline content or content referenced by a URI. + * - ``translate()`` + - Translates text from one language to another. + ******************** ``AsyncProfile`` API ******************** @@ -18,6 +84,9 @@ used with ``await``. Async Profile creation *********************** +The following example creates an OCI Gen AI profile that can generate SQL over +objects in the ``SH`` schema. + .. literalinclude:: ../../../samples/async/profile_create.py :language: python :lines: 14- @@ -55,6 +124,77 @@ output:: .. latex:clearpage:: +*********************** +Reuse Async Profile +*********************** + +After a profile has been created, instantiate ``AsyncProfile`` with only the +profile name to reuse the database profile: + +.. code-block:: python + + async_profile = await select_ai.AsyncProfile( + profile_name="async_oci_ai_profile", + ) + sql = await async_profile.show_sql(prompt="How many promotions?") + +Use ``AsyncProfile.fetch(...)`` when you want to create a proxy object from a +saved database profile and raise an error if the profile does not exist: + +.. code-block:: python + + async_profile = await select_ai.AsyncProfile.fetch( + "async_oci_ai_profile" + ) + +.. latex:clearpage:: + +*********************** +Update Async Profile +*********************** + +Use ``set_attribute(...)`` to update one profile attribute or +``set_attributes(...)`` to update several attributes. Updates are saved to the +database profile. + +.. code-block:: python + + async_profile = await select_ai.AsyncProfile( + profile_name="async_oci_ai_profile", + ) + await async_profile.set_attribute("temperature", 0.1) + + await async_profile.set_attributes( + select_ai.ProfileAttributes( + max_tokens=2048, + enforce_object_list=True, + ) + ) + +.. latex:clearpage:: + +*********************** +Delete Async Profile +*********************** + +Use ``delete(...)`` or ``AsyncProfile.delete_profile(...)`` to remove a profile +from the database. Pass ``force=True`` when cleanup should succeed even if the +profile does not exist. + +.. code-block:: python + + async_profile = await select_ai.AsyncProfile( + profile_name="async_oci_ai_profile", + ) + await async_profile.delete(force=True) + + await select_ai.AsyncProfile.delete_profile( + "async_oci_ai_profile", + force=True, + ) + +.. latex:clearpage:: + *********************** Async explain SQL *********************** @@ -115,6 +255,24 @@ output:: .. latex:clearpage:: +*********************** +Async show prompt +*********************** + +Use ``show_prompt(...)`` to inspect the prompt that Select AI sends to the +model. This is useful when tuning profile attributes, object lists, comments, +constraints, and provider settings. + +.. code-block:: python + + async_profile = await select_ai.AsyncProfile( + profile_name="async_oci_ai_profile", + ) + prompt = await async_profile.show_prompt(prompt="How many promotions?") + print(prompt) + +.. latex:clearpage:: + *********************** Async concurrent SQL *********************** @@ -297,6 +455,9 @@ output:: List profiles asynchronously **************************** +Profile listing returns profiles visible to the connected database user. The +async list API returns an async iterator. + .. literalinclude:: ../../../samples/async/profiles_list.py :language: python :lines: 14- diff --git a/doc/source/user_guide/cli.rst b/doc/source/user_guide/cli.rst index 0f63ad5..d8d084e 100644 --- a/doc/source/user_guide/cli.rst +++ b/doc/source/user_guide/cli.rst @@ -4,6 +4,21 @@ Command line interface ************************** +The ``select-ai`` command line interface (CLI) provides a terminal workflow for +using Select AI profiles without writing Python code. It is intended for quick +exploration, profile validation, prompt testing, SQL generation, +summarization, translation, and interactive chat against an existing profile. + +The CLI is useful for developers who want a fast shell workflow and for +non-developers who are comfortable running terminal commands but do not want to +write Python code. It can help users check whether a profile is configured +correctly, inspect generated SQL, try prompts during development, or interact +with a curated profile through a simple command. + +The CLI works with Select AI profiles. RAG is supported when the selected +profile is already configured with a vector index. Additional CLI options and +workflows will be added in upcoming releases as the CLI evolves. + .. only:: html .. image:: /image/select_ai_cli_demo.gif @@ -23,6 +38,9 @@ CLI extra to use it: pip install 'select_ai[cli]' +Use ``select-ai --help`` to view the available command groups and +``select-ai --help`` to view options for a specific command. + Set the database connection details as environment variables, or pass them as command line options: @@ -32,11 +50,40 @@ command line options: export SELECT_AI_PASSWORD= export SELECT_AI_DB_CONNECT_STRING= +Connection options +================== + +All CLI commands accept the same database connection options: + +.. list-table:: Connection options + :header-rows: 1 + :widths: 30 70 + :align: left + + * - Option + - Environment variable + * - ``--user`` + - ``SELECT_AI_USER`` + * - ``--password`` + - ``SELECT_AI_PASSWORD`` + * - ``--dsn`` + - ``SELECT_AI_DB_CONNECT_STRING`` + * - ``--wallet-location`` + - ``SELECT_AI_WALLET_LOCATION`` + * - ``--wallet-password`` + - ``SELECT_AI_WALLET_PASSWORD`` + +If ``--password`` and ``SELECT_AI_PASSWORD`` are not set, the CLI prompts for +the database password. Wallet options are optional and are only needed for +wallet-based database connections. + Interactive chat ================ -The ``chat`` subcommand starts an interactive profile chat REPL. Pass an -existing Select AI profile with ``--profile``: +The ``chat`` subcommand starts an interactive profile chat +Read-Eval-Print Loop (REPL). A REPL is a terminal session that reads each +prompt you type, evaluates it, prints the response, and then waits for the next +prompt. Pass an existing Select AI profile with ``--profile``: .. code-block:: bash @@ -62,6 +109,24 @@ Useful options: - ``--conversation-length`` controls how many prompts are retained in context. - ``--keep-conversation`` keeps the database conversation after the REPL exits. +Inside the REPL, use these commands: + +.. list-table:: Chat REPL commands + :header-rows: 1 + :widths: 25 75 + :align: left + + * - Command + - Description + * - ``/help`` + - Show available REPL commands. + * - ``/clear`` + - Start a fresh database conversation. + * - ``/exit`` + - Exit the chat session. + * - ``/quit`` + - Exit the chat session. + SQL commands ============ @@ -74,6 +139,14 @@ SQL operations are one-shot subcommands instead of a REPL: select-ai sql explain --profile OCI_AI_PROFILE "count movies by genre" select-ai sql narrate --profile OCI_AI_PROFILE "count movies by genre" +``show``, ``explain``, and ``narrate`` stream text output by default. Use +``--no-stream`` to print the response after it is fully generated, and +``--chunk-size`` to control the number of CLOB characters read per stream +chunk. + +``run`` executes the generated SQL and prints the returned result table. It +does not support streaming. + Profile commands ================ @@ -86,9 +159,51 @@ Summarize and translate are available under the ``profile`` command group: select-ai profile summarize --profile OCI_AI_PROFILE "Text to summarize" select-ai profile summarize --profile OCI_AI_PROFILE --file notes.txt + select-ai profile summarize \ + --profile OCI_AI_PROFILE \ + --location-uri https://example.com/article.txt + select-ai profile summarize \ + --profile OCI_AI_PROFILE \ + --location-uri https://objectstorage.example.com/n/namespace/b/bucket/o/file.txt \ + --credential-name OBJECT_STORE_CRED select-ai profile translate \ --profile OCI_AI_PROFILE \ --source-language English \ --target-language German \ "Thank you" + +``profile list`` prints profile names visible to the connected database user. +Use ``--pattern`` to filter names with a regular expression. + +``profile summarize`` accepts one content source at a time: inline text, +``--file``, or ``--location-uri``. Use ``--prompt`` to guide the summary and +``--credential-name`` when the location URI requires an object storage +credential. + +Command summary +=============== + +.. list-table:: CLI command summary + :header-rows: 1 + :widths: 35 65 + :align: left + + * - Command + - Purpose + * - ``select-ai chat`` + - Start an interactive context-aware chat session. + * - ``select-ai sql show`` + - Generate SQL without executing it. + * - ``select-ai sql run`` + - Generate SQL, execute it, and print the result table. + * - ``select-ai sql explain`` + - Explain generated SQL. + * - ``select-ai sql narrate`` + - Generate and execute SQL, then return a natural language answer. + * - ``select-ai profile list`` + - List saved profile names. + * - ``select-ai profile summarize`` + - Summarize inline content, a file, or a URI. + * - ``select-ai profile translate`` + - Translate text with a saved profile. diff --git a/doc/source/user_guide/concurrent_prompt_processing.rst b/doc/source/user_guide/concurrent_prompt_processing.rst new file mode 100644 index 0000000..1f2e165 --- /dev/null +++ b/doc/source/user_guide/concurrent_prompt_processing.rst @@ -0,0 +1,179 @@ +.. _concurrent_prompt_processing: + +**************************** +Concurrent prompt processing +**************************** + +Use concurrent prompt processing when an application needs to send multiple +independent prompts without waiting for each prompt to finish before starting +the next one. The ``select_ai`` module supports this pattern with both the +synchronous ``Profile`` API and the asynchronous ``AsyncProfile`` API. + +Create a connection pool before running concurrent work. Use +``select_ai.create_pool()`` for synchronous recipes and +``select_ai.create_pool_async()`` for asynchronous recipes. + +Recipe summary +============== + +.. list-table:: + :header-rows: 1 + :widths: 18 26 56 + + * - Recipe + - Script + - When to use + * - Sync completion + - :ref:`sync_thread_pool_recipe` + - Use ``ThreadPoolExecutor`` when prompts are independent and results can + be handled as soon as each prompt completes. + * - Sync input order + - :ref:`sync_ordered_results_recipe` + - Use ``ThreadPoolExecutor.map()`` when result order must match the input + prompt order. + * - Sync queue + - :ref:`sync_queue_workers_recipe` + - Use worker threads and a queue for producer-consumer workloads where + prompts may arrive over time. + * - Async input order + - :ref:`async_gather_recipe` + - Use ``asyncio.gather()`` when result order must match the input prompt + order. + * - Async completion + - :ref:`async_as_completed_recipe` + - Use ``asyncio.as_completed()`` when each result should be processed as + soon as it is available. + * - Async pipeline + - :ref:`async_pipeline_recipe` + - Use ``run_pipeline()`` when all prompt/action pairs are known up front + and should be sent in a single database round trip. + * - Async queue + - :ref:`async_queue_workers_recipe` + - Use async queue workers for long-running async services or background + prompt processors. + +Environment variables +===================== + +The recipes use the same connection environment variables as the other samples: + +.. code-block:: sh + + export SELECT_AI_USER= + export SELECT_AI_PASSWORD= + export SELECT_AI_DB_CONNECT_STRING= + +Optional environment variables control pool sizing and profile names: + +.. code-block:: sh + + export SELECT_AI_POOL_MIN=1 + export SELECT_AI_POOL_MAX=4 + export SELECT_AI_POOL_INCREMENT=1 + export SELECT_AI_PROFILE_NAME=oci_ai_profile + +Use ``SELECT_AI_PROFILE_NAME=async_oci_ai_profile`` for the async recipes if +that is the async profile name in your environment. + +.. _sync_thread_pool_recipe: + +``sync_thread_pool.py`` +======================= + +This recipe uses ``ThreadPoolExecutor`` and ``as_completed()``. Results are +printed in the order they finish. + +.. literalinclude:: ../../../recipes/concurrent_prompt_processing/sync_thread_pool.py + :language: python + :lines: 14- + +.. _sync_ordered_results_recipe: + +``sync_ordered_results.py`` +=========================== + +This recipe uses ``ThreadPoolExecutor.map()``. Prompts run concurrently, but +results are printed in the same order as the input list. + +.. literalinclude:: ../../../recipes/concurrent_prompt_processing/sync_ordered_results.py + :language: python + :lines: 14- + +.. _sync_queue_workers_recipe: + +``sync_queue_workers.py`` +========================= + +This recipe uses worker threads and ``queue.Queue``. It is useful when prompt +producers and prompt processors are separate parts of an application. + +.. literalinclude:: ../../../recipes/concurrent_prompt_processing/sync_queue_workers.py + :language: python + :lines: 14- + +.. _async_gather_recipe: + +``async_gather.py`` +=================== + +This recipe uses ``asyncio.gather()``. Prompts run concurrently, and results +are returned in the same order as the input task list. + +.. literalinclude:: ../../../recipes/concurrent_prompt_processing/async_gather.py + :language: python + :lines: 14- + +.. _async_as_completed_recipe: + +``async_as_completed.py`` +========================= + +This recipe uses ``asyncio.as_completed()``. It is useful for command-line +tools or services that can forward each answer as soon as it is ready. + +.. literalinclude:: ../../../recipes/concurrent_prompt_processing/async_as_completed.py + :language: python + :lines: 14- + +.. _async_pipeline_recipe: + +``async_pipeline.py`` +===================== + +This recipe uses ``AsyncProfile.run_pipeline()`` to send multiple +prompt/action pairs in one database round trip. This is different from Python +task concurrency: the application submits a batch and receives the batch +results when the pipeline completes. + +.. literalinclude:: ../../../recipes/concurrent_prompt_processing/async_pipeline.py + :language: python + :lines: 14- + +.. _async_queue_workers_recipe: + +``async_queue_workers.py`` +========================== + +This recipe uses ``asyncio.Queue`` and async worker tasks. It is useful for +long-running async applications that receive prompts over time. + +.. literalinclude:: ../../../recipes/concurrent_prompt_processing/async_queue_workers.py + :language: python + :lines: 14- + +Pool sizing +=========== + +Pool size controls how many database connections the application can use at +one time. For thread and worker recipes, keep the worker count close to the +pool maximum unless the application intentionally needs additional queued work. + +In multi-process deployments, each process creates its own pool. Total possible +database connections are approximately: + +.. code-block:: text + + processes * SELECT_AI_POOL_MAX + +Choose pool sizes that leave capacity for other database clients and for the +AI provider calls made by ``DBMS_CLOUD_AI``. diff --git a/doc/source/user_guide/connection.rst b/doc/source/user_guide/connection.rst index 9419c9d..66267dd 100644 --- a/doc/source/user_guide/connection.rst +++ b/doc/source/user_guide/connection.rst @@ -7,13 +7,40 @@ Connecting to Oracle Database ``select_ai`` uses the Python thin driver i.e. ``python-oracledb`` to connect to the database and execute PL/SQL subprograms. +The library keeps the active connection or connection pool for the current +process so profile, credential, provider, vector index, and agent APIs can use +it without passing a connection object to each call. Use a standalone +connection for scripts and notebooks. Use a connection pool for applications +that handle concurrent work, such as web services or worker processes. + +Most samples read connection values from environment variables: + +.. code-block:: sh + + export SELECT_AI_USER= + export SELECT_AI_PASSWORD= + export SELECT_AI_DB_CONNECT_STRING= + +Then the Python code can load those values: + +.. code-block:: python + + import os + import select_ai + + user = os.getenv("SELECT_AI_USER") + password = os.getenv("SELECT_AI_PASSWORD") + dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING") + + select_ai.connect(user=user, password=password, dsn=dsn) + .. _sync_conn: Synchronous connection ====================== To connect to an Oracle Database synchronously, use -``select_ai.connect()`` method as shown below +``select_ai.connect()`` as shown below: .. code-block:: python @@ -24,6 +51,12 @@ To connect to an Oracle Database synchronously, use dsn = "" select_ai.connect(user=user, password=password, dsn=dsn) +Close a standalone synchronous connection with ``select_ai.disconnect()``: + +.. code-block:: python + + select_ai.disconnect() + .. _async_conn: Asynchronous connection @@ -41,12 +74,21 @@ with ``await`` keyword: dsn = "" await select_ai.async_connect(user=user, password=password, dsn=dsn) +Close a standalone asynchronous connection with +``await select_ai.async_disconnect()``: + +.. code-block:: python + + await select_ai.async_disconnect() + Connection Pool =============== You can create a connection pool using the ``select_ai.create_pool`` -and ``select_ai.create_pool_async`` methods +and ``select_ai.create_pool_async`` methods. After a pool is created, these +methods configure Select AI operations to acquire and release connections from +the pool for each operation. .. code-block:: python @@ -65,6 +107,7 @@ and ``select_ai.create_pool_async`` methods max_size=10, increment=5 ) + # for async pool select_ai.create_pool_async( user=user, @@ -75,11 +118,68 @@ and ``select_ai.create_pool_async`` methods increment=5 ) -Check this `blog `__ which shows the benefit of connection pooling along with FastAPI service +Close a synchronous pool with ``select_ai.disconnect()`` and an asynchronous +pool with ``await select_ai.async_disconnect()``. + +Create one pool per process. In multi-process deployments, each process creates +its own pool, so total database connections can grow quickly. Size pools based +on request concurrency and database capacity. + +Use pooling for: + +* Web applications and API services. +* Worker processes that handle multiple prompts. +* Concurrent prompt processing. +* Long-running applications that should avoid opening a new database connection + for every request. + +Use a standalone connection for: + +* Short scripts. +* Local examples. +* One-off administration tasks. + +Check this `blog `__ +which shows the benefit of connection pooling with a FastAPI service. + +Connection health +================= + +Use ``select_ai.is_connected()`` or ``await select_ai.async_is_connected()`` +to check whether the current connection or pool is available: + +.. code-block:: python + + if not select_ai.is_connected(): + select_ai.connect(user=user, password=password, dsn=dsn) + +.. code-block:: python + + if not await select_ai.async_is_connected(): + await select_ai.async_connect(user=user, password=password, dsn=dsn) + +Wallet connections +================== .. note:: - For m-TLS (wallet) based connection, additional parameters like - ``wallet_location``, ``wallet_password``, ``https_proxy``, - ``https_proxy_port`` can be passed to the ``connect`` and ``async_connect`` - methods + For m-TLS (wallet) based connections, additional parameters like + ``wallet_location``, ``wallet_password``, ``config_dir``, ``https_proxy``, + and ``https_proxy_port`` can be passed to ``connect``, ``async_connect``, + ``create_pool``, and ``create_pool_async``. + +For example: + +.. code-block:: python + + select_ai.connect( + user=user, + password=password, + dsn=dsn, + wallet_location="/path/to/wallet", + config_dir="/path/to/wallet", + wallet_password="", + ) + +The same keyword arguments can be used with ``async_connect`` and the pool +creation APIs. diff --git a/doc/source/user_guide/conversation.rst b/doc/source/user_guide/conversation.rst index 6e6d7dc..a9db8f7 100644 --- a/doc/source/user_guide/conversation.rst +++ b/doc/source/user_guide/conversation.rst @@ -4,6 +4,26 @@ Conversations in Select AI represent an interactive exchange between the user and the system, enabling users to query or interact with the database through a series of natural language prompts. +A conversation is stored in the database and identified by a +``conversation_id``. Pass that conversation to ``Profile.chat_session()`` or +``AsyncProfile.chat_session()`` when follow-up prompts should use prior prompts +as context. This is useful for chat workflows where the user asks a question, +then asks follow-up questions such as "explain that further" or "show another +example". + +Use conversations when you need context across multiple prompts. For one-off +prompts, call profile methods such as ``chat()``, ``show_sql()``, or +``narrate()`` directly without creating a conversation. + +The usual lifecycle is: + +1. Create ``ConversationAttributes`` with a title, optional description, + retention period, and conversation length. +2. Create a ``Conversation`` or ``AsyncConversation`` object. +3. Use the conversation in ``profile.chat_session(...)``. +4. List, fetch, or update the conversation metadata when needed. +5. Delete the conversation when the stored history is no longer needed. + ***************************** ``Conversation Object model`` ***************************** @@ -17,6 +37,41 @@ a series of natural language prompts. ``ConversationAttributes`` ************************** +``ConversationAttributes`` controls the metadata and retention behavior for a +conversation: + +.. list-table:: + :header-rows: 1 + + * - Attribute + - Use + * - ``title`` + - Human-readable conversation title. If omitted, the default is + ``"New Conversation"``. + * - ``description`` + - Optional description of the conversation topic. + * - ``retention_days`` + - Number of days to keep the conversation in the database from its + creation date. Use ``datetime.timedelta(days=...)``. A value of + ``datetime.timedelta(days=0)`` keeps the conversation until it is + manually deleted. + * - ``conversation_length`` + - Number of prompts retained in the conversation context. The default is + ``10``. + +Example: + +.. code-block:: python + + import datetime + + attributes = select_ai.ConversationAttributes( + title="Sales analysis", + description="Follow-up questions about quarterly sales", + retention_days=datetime.timedelta(days=14), + conversation_length=20, + ) + .. autoclass:: select_ai.ConversationAttributes :members: @@ -29,10 +84,40 @@ a series of natural language prompts. .. autoclass:: select_ai.Conversation :members: +The synchronous API is used with ``select_ai.connect()`` or +``select_ai.create_pool()``. Important methods: + +.. list-table:: + :header-rows: 1 + + * - Method + - Use + * - ``create()`` + - Create a database conversation and return its ``conversation_id``. + * - ``fetch(conversation_id)`` + - Build a ``Conversation`` object from an existing database conversation. + * - ``get_attributes()`` + - Read conversation metadata from the database. + * - ``set_attributes(attributes)`` + - Update the title, description, retention period, or conversation + length. + * - ``list()`` + - Iterate over conversations visible to the current user. + * - ``delete(force=False)`` + - Drop the conversation. Use ``force=True`` to ignore missing-conversation + errors. + +``Profile.chat_session(conversation=..., delete=False)`` is a context manager. +If the conversation has attributes but no ``conversation_id``, the session +creates it automatically. While the context manager is active, every +``session.chat(...)`` call passes the same ``conversation_id`` to Select AI, so +follow-up prompts can use the conversation history. If ``delete=True``, the +conversation is deleted when the session exits. + .. latex:clearpage:: -Create conversion -++++++++++++++++++ +Create conversation ++++++++++++++++++++ .. literalinclude:: ../../../samples/conversation_create.py :language: python @@ -47,6 +132,10 @@ output:: Chat session +++++++++++++ +Use ``chat_session()`` to keep context across multiple chat prompts. The second +prompt in this example can refer to the previous answer because both prompts use +the same database conversation. + .. literalinclude:: ../../../samples/conversation_chat_session.py :language: python :lines: 14- @@ -71,6 +160,9 @@ output:: List conversations ++++++++++++++++++ +Listing returns ``Conversation`` objects with their ``conversation_id`` and +metadata. It does not replay the conversation transcript. + .. literalinclude:: ../../../samples/conversations_list.py :language: python :lines: 14- @@ -88,6 +180,11 @@ output:: Delete conversation +++++++++++++++++++ +Delete conversations that are no longer needed, especially when +``retention_days`` is set to ``0`` or when the content should not remain in the +database after a session ends. For temporary sessions, prefer +``profile.chat_session(conversation=conversation, delete=True)``. + .. literalinclude:: ../../../samples/conversation_delete.py :language: python :lines: 14- @@ -106,11 +203,37 @@ output:: .. autoclass:: select_ai.AsyncConversation :members: +The async API mirrors the synchronous API and is used with +``select_ai.async_connect()`` or ``select_ai.create_pool_async()``. + +.. list-table:: + :header-rows: 1 + + * - Synchronous API + - Async API + * - ``Conversation.create()`` + - ``await AsyncConversation.create()`` + * - ``Conversation.fetch(...)`` + - ``await AsyncConversation.fetch(...)`` + * - ``Conversation.get_attributes()`` + - ``await AsyncConversation.get_attributes()`` + * - ``Conversation.set_attributes(...)`` + - ``await AsyncConversation.set_attributes(...)`` + * - ``for conversation in Conversation.list()`` + - ``async for conversation in AsyncConversation.list()`` + * - ``Conversation.delete(...)`` + - ``await AsyncConversation.delete(...)`` + * - ``with profile.chat_session(...)`` + - ``async with async_profile.chat_session(...)`` + .. latex:clearpage:: Async chat session ++++++++++++++++++ +Use ``AsyncProfile.chat_session()`` in async applications. The conversation is +created automatically when the object has attributes and no ``conversation_id``. + .. literalinclude:: ../../../samples/async/conversation_chat_session.py :language: python :lines: 13- @@ -135,6 +258,8 @@ output:: Async list conversations ++++++++++++++++++++++++ +``AsyncConversation.list()`` is an async iterator. + .. literalinclude:: ../../../samples/async/conversations_list.py :language: python :lines: 14- diff --git a/doc/source/user_guide/credential.rst b/doc/source/user_guide/credential.rst index 8bc8f47..19ad639 100644 --- a/doc/source/user_guide/credential.rst +++ b/doc/source/user_guide/credential.rst @@ -1,34 +1,99 @@ .. _credential: -Credential object securely stores API key from your AI provider for use by Oracle Database. -The following table shows AI Provider and corresponding credential object format - -.. list-table:: AI Provider and expected credential format +A credential object securely stores authentication details from your AI +provider for use by Oracle Database. Select AI profiles, vector indexes, and +agent tools refer to the credential later by ``credential_name``; the secret +values are stored in Oracle Database and are not passed again when the profile +or tool runs. + +A credential is created in the connected user's schema by +``DBMS_CLOUD.CREATE_CREDENTIAL``. Create credentials while connected as the +database user that will own and use them. Before creating credentials, make +sure the user has the required Select AI package privileges. If the credential +will be used to call an external AI provider, the database user also needs +network access to that provider endpoint. + +Every credential object must include ``credential_name`` and the fields +required by the target provider. The library accepts the following credential +keys: ``credential_name``, ``username``, ``password``, ``user_ocid``, +``tenancy_ocid``, ``private_key``, ``fingerprint``, and ``comments``. + +The following table shows AI providers and corresponding credential object +formats. + +.. list-table:: AI provider and expected credential format :header-rows: 1 :widths: 30 70 :align: left - * - AI Provider + * - AI provider - Credential format * - Anthropic - .. code-block:: python - {"username": "anthropic", "password": "sk-xxx"} - * - HuggingFace - - .. code-block:: python + { + "credential_name": "ANTHROPIC_CRED", + "username": "anthropic", + "password": "sk-ant-xxx", + } + * - AWS Bedrock + - .. code-block:: python - {"username": "hf", "password": "hf_xxx"} - * - OCI Gen AI + { + "credential_name": "AWS_BEDROCK_CRED", + "username": "", + "password": "", + } + * - Azure OpenAI - .. code-block:: python - {"user_ocid": "", "tenancy_ocid": "", "private_key": "", "fingerprint": ""} - * - OpenAI + { + "credential_name": "AZURE_OPENAI_CRED", + "username": "azure", + "password": "", + } + * - Cohere - .. code-block:: python - {"username": "openai", "password": "sk-xxx"} + { + "credential_name": "COHERE_CRED", + "username": "cohere", + "password": "", + } + * - Google + - .. code-block:: python + { + "credential_name": "GOOGLE_CRED", + "username": "google", + "password": "", + } + * - HuggingFace + - .. code-block:: python + + { + "credential_name": "HUGGINGFACE_CRED", + "username": "hf", + "password": "hf_xxx", + } + * - OCI Gen AI + - .. code-block:: python + { + "credential_name": "OCI_GENAI_CRED", + "user_ocid": "", + "tenancy_ocid": "", + "private_key": "", + "fingerprint": "", + } + * - OpenAI + - .. code-block:: python + { + "credential_name": "OPENAI_CRED", + "username": "openai", + "password": "sk-xxx", + } .. latex:clearpage:: @@ -39,6 +104,10 @@ Create credential In this example, we create a credential object to authenticate to OCI Gen AI service provider: +Pass ``replace=True`` when you want to recreate an existing credential with the +same name. Without ``replace=True``, creating a credential that already exists +raises a database error. + Sync API ++++++++ @@ -62,3 +131,37 @@ Async API output:: Created credential: my_oci_ai_profile_key + +.. latex:clearpage:: + +************************** +Delete credential +************************** + +Use ``select_ai.delete_credential(...)`` to drop a credential that is no longer +needed. Pass ``force=True`` when cleanup should succeed even if the credential +does not exist. + +Sync API +++++++++ + +.. literalinclude:: ../../../samples/delete_ai_credential.py + :language: python + :lines: 14- + +output:: + + Deleted credential: my_oci_ai_profile_key + +.. latex:clearpage:: + +Async API ++++++++++ + +.. literalinclude:: ../../../samples/async/delete_ai_credential.py + :language: python + :lines: 14- + +output:: + + Deleted credential: my_oci_ai_profile_key diff --git a/doc/source/user_guide/installation.rst b/doc/source/user_guide/installation.rst index 13adc69..078f39d 100644 --- a/doc/source/user_guide/installation.rst +++ b/doc/source/user_guide/installation.rst @@ -11,16 +11,21 @@ Installation requirements To use ``select_ai`` you need: -- Python 3.9, 3.10, 3.11, 3.12, 3.13 or 3.14 +- Python 3.11, 3.12, 3.13, or 3.14. -.. warning:: +- Access to an Oracle Database environment where Select AI is available. - For async APIs, use Python 3.11 or higher. Python 3.11 stabilized the async - event loop management and introduced better-structured APIs +- A database user with the required Select AI package privileges. See + :ref:`Privileges `. -- ``python-oracledb`` - This package is automatically installed as a dependency requirement +- Network access from the database to any AI provider endpoints you plan to + use. -- ``pandas`` - This package is automatically installed as a dependency requirement +- ``python-oracledb`` and ``pandas``. These packages are installed + automatically as dependencies. + +Using a virtual environment is recommended so the package and its dependencies +are isolated from your system Python installation. .. _quickstart: @@ -28,48 +33,106 @@ To use ``select_ai`` you need: ``select_ai`` installation ============================ -``select_ai`` can be installed from Python's package repository +``select_ai`` can be installed from the Python Package Index `PyPI `__ using `pip `__. 1. Install `Python 3 `__ if it is not already - available. Use any version from Python 3.9 through 3.14. + available. Use any version from Python 3.11 through 3.14. + +2. Create and activate a virtual environment: + + .. code-block:: shell + + python3 -m venv .venv + source .venv/bin/activate + + On Windows PowerShell: + + .. code-block:: powershell + + py -3 -m venv .venv + .venv\Scripts\Activate.ps1 + +3. Upgrade ``pip``: + + .. code-block:: shell + + python -m pip install --upgrade pip + +4. Install ``select_ai``: + + .. code-block:: shell + + python -m pip install --upgrade select_ai + +5. If you want the optional command line interface, install the ``cli`` extra: + + .. code-block:: shell + + python -m pip install --upgrade "select_ai[cli]" + + This installs the ``select-ai`` command. See :ref:`Command Line Interface + `. + +6. If you are behind a proxy, use the ``--proxy`` option. For example: + + .. code-block:: shell + + python -m pip install --upgrade select_ai --proxy=http://proxy.example.com:80 + + +Connection smoke test +===================== + +After installation, verify that Python can import ``select_ai`` and connect to +Oracle Database. + +1. Set database connection environment variables: + + .. code-block:: shell + + export SELECT_AI_USER= + export SELECT_AI_PASSWORD= + export SELECT_AI_DB_CONNECT_STRING= -2. Install ``select_ai``: +2. Create a file ``select_ai_connection_test.py``: - .. code-block:: shell + .. code-block:: python - python3 -m pip install select_ai --upgrade --user + import os -3. If you are behind a proxy, use the ``--proxy`` option. For example: + import select_ai - .. code-block:: shell + user = os.getenv("SELECT_AI_USER") + password = os.getenv("SELECT_AI_PASSWORD") + dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING") - python3 -m pip install select_ai --upgrade --user --proxy=http://proxy.example.com:80 + select_ai.connect(user=user, password=password, dsn=dsn) + print("Connected to the Database") +3. Run the script: -4. Create a file ``select_ai_connection_test.py`` such as: + .. code-block:: shell - .. code-block:: python + python select_ai_connection_test.py - import select_ai + If the connection succeeds, the script prints: - user = "" - password = "" - dsn = "" - select_ai.connect(user=user, password=password, dsn=dsn) - print("Connected to the Database") + .. code-block:: shell -5. Run ``select_ai_connection_test.py`` + Connected to the Database - .. code-block:: shell +Install documentation dependencies +================================== - python3 select_ai_connection_test.py +If you are building this documentation locally from the repository, install the +documentation dependencies: - Enter the database password when prompted and message will be shown: +.. code-block:: shell - .. code-block:: shell + python -m pip install -r doc/requirements.txt - Connected to the Database +Then build the docs with the project's Sphinx command or Makefile target. .. latex:clearpage:: diff --git a/doc/source/user_guide/introduction.rst b/doc/source/user_guide/introduction.rst index dd5ad91..ab0774d 100644 --- a/doc/source/user_guide/introduction.rst +++ b/doc/source/user_guide/introduction.rst @@ -9,10 +9,91 @@ using Python. It supports text-to-SQL generation, retrieval augmented generation (RAG), synthetic data generation, and several other features using Oracle-based and third-party AI providers. -``select_ai`` supports both synchronous and concurrent(asynchronous) -programming styles. +Select AI for Python bridges Oracle Database's Select AI capabilities and the +Python ecosystem. It gives Python applications a higher-level API for working +with AI providers, credentials, profiles, natural language prompts, vector +indexes, conversations, summarization, synthetic data, and AI agent workflows. -The Select AI Python API supports Python versions 3.9, 3.10, 3.11, 3.12 and -3.13. +What you can build +================== + +Use ``select_ai`` to: + +* Ask questions about database objects in natural language and generate SQL. +* Run generated SQL and return results as Python objects such as pandas data + frames. +* Generate narrative answers, explanations, prompt previews, translations, and + summaries. +* Use Retrieval Augmented Generation (RAG) with vector indexes over documents + and object storage content. +* Create synthetic data for database tables. +* Build context-aware chat sessions with database-backed conversations. +* Register tools, tasks, agents, and teams for database-backed AI agent + workflows. +* Use the optional ``select-ai`` command line interface for interactive chat + and SQL workflows. +* Use synchronous APIs, asynchronous APIs, and connection pools in scripts, + services, and web applications. + +Core concepts +============= + +Most workflows use the same building blocks: + +.. list-table:: + :header-rows: 1 + + * - Concept + - Purpose + - Start here + * - Connection + - Connect to Oracle Database using a standalone connection or a pool. + - :ref:`Connection ` + * - Privileges + - Grant package privileges and network ACLs required for Select AI calls. + - :ref:`Privileges ` + * - Provider + - Describe the AI service, model, endpoint, region, or provider-specific + options. + - :ref:`Provider ` + * - Credential + - Store provider and service secrets securely in Oracle Database. + - :ref:`Credential ` + * - Profile + - Combine provider, credential, database object scope, and generation + options into a reusable Select AI profile. + - :ref:`Profile ` + * - Actions + - Choose what Select AI should do with a prompt, such as show SQL, run + SQL, chat, narrate, summarize, or translate. + - :ref:`Actions ` + * - Conversation + - Keep prompt history for context-aware chat sessions. + - :ref:`Conversation ` + * - Vector index + - Index document content for RAG over trusted source material. + - :ref:`Vector Index ` + * - Agent + - Define tools, tasks, agents, and teams for multi-step AI workflows. + - :ref:`Agent ` + +Synchronous and asynchronous APIs +================================= + +``select_ai`` supports both synchronous and asynchronous programming styles. +Use the synchronous APIs for scripts, notebooks, command-line tools, and simple +services. Use the asynchronous APIs with ``asyncio`` applications, async web +frameworks, and workloads that need to run many prompts concurrently. + +For long-running services, create a connection pool once during application +startup and close it during shutdown. See :ref:`Connection `, +:ref:`Web Frameworks `, and +:ref:`Concurrent Prompt Processing ` for +patterns. + +Supported Python versions +========================= + +The Select AI Python API supports Python versions 3.11, 3.12, 3.13, and 3.14. .. latex:clearpage:: diff --git a/doc/source/user_guide/privileges.rst b/doc/source/user_guide/privileges.rst index 945bab9..920ddbe 100644 --- a/doc/source/user_guide/privileges.rst +++ b/doc/source/user_guide/privileges.rst @@ -1,14 +1,29 @@ .. _privileges: -Admin user should grant execute privilege to select ai database users -on the packages ``DBMS_CLOUD``, ``DBMS_CLOUD_AI``, ``DBMS_CLOUD_AI_AGENT`` -and ``DBMS_CLOUD_PIPELINE`` +An admin user should grant execute privilege to Select AI database users +on the packages ``DBMS_CLOUD``, ``DBMS_CLOUD_AI``, ``DBMS_CLOUD_AI_AGENT``, +and ``DBMS_CLOUD_PIPELINE``. + +The privilege helper APIs are intended for database administrators who need to +prepare one or more database schemas for Select AI workloads. These operations +should be run from a connection that has permission to grant package execute +privileges and manage database network ACLs. + +There are two separate setup steps: + +* Package privileges allow a Select AI database user to call the Oracle Database + PL/SQL packages used by this library. +* Network access allows the database user to make outbound calls to specific + hosts, such as AI provider endpoints or SMTP servers. + +The ``users`` argument accepts either a single database user name or a list of +database user names. .. note:: All sample scripts in this documentation read Oracle database connection details from the environment. Create a dotenv file ``.env``, export the - the following environment variables and source it before running the + following environment variables and source it before running the scripts. .. code-block:: sh @@ -24,9 +39,11 @@ and ``DBMS_CLOUD_PIPELINE`` Grant privilege *************** -Connect as admin and run the method -``select_ai.grant_privileges(users=select_ai_user)`` to grant relevant select ai -privileges to other users +Connect as an admin user and run +``select_ai.grant_privileges(users=select_ai_user)`` to grant the package +execute privileges required by Select AI. This grants execute access on +``DBMS_CLOUD``, ``DBMS_CLOUD_AI``, ``DBMS_CLOUD_AI_AGENT``, and +``DBMS_CLOUD_PIPELINE``. .. literalinclude:: ../../../samples/select_ai_grant_privilege.py @@ -67,6 +84,15 @@ host access. This wraps ``DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE`` and can be used for hosts that require privileges such as ``connect``, ``http``, or ``smtp``. +Network ACLs are required when the database needs to reach an external host. +For example, use ``http`` access for AI provider endpoints and ``smtp`` access +for mail servers. Include ``connect`` with protocol-specific privileges when +the host requires it. + +When granting access, specify the target host and, when applicable, the port +range. When revoking access, use the same host, privileges, and port range that +were used for the grant. + .. literalinclude:: ../../../samples/grant_network_access.py :language: python :lines: 14- diff --git a/doc/source/user_guide/profile.rst b/doc/source/user_guide/profile.rst index 1cdc1fb..9f1749d 100644 --- a/doc/source/user_guide/profile.rst +++ b/doc/source/user_guide/profile.rst @@ -4,7 +4,61 @@ An AI profile is a specification that includes the AI provider to use and other details regarding metadata and database objects required for generating responses to natural language prompts. -An AI profile object can be created using ``select_ai.Profile()`` +An AI profile object can be created using ``select_ai.Profile()``. Creating a +profile stores the profile in Oracle Database. Later, you can instantiate +``select_ai.Profile(profile_name="...")`` to reuse an existing database profile +without passing all attributes again. + +Before creating a profile, make sure the database user has the required +privileges, a credential for the AI provider, network access to the provider +endpoint, and access to the database objects included in the profile. See +:ref:`Privileges `, :ref:`Credential `, +:ref:`Provider `, and +:ref:`ProfileAttributes `. + +Profile lifecycle +================= + +The usual profile lifecycle is: + +* Create a provider object. +* Create ``ProfileAttributes`` with the provider, credential name, and object + list. +* Create the profile with ``select_ai.Profile(...)``. +* Reuse the profile later by name. +* Update profile attributes when provider settings or object scope changes. +* Delete profiles that are no longer needed. + +``replace=True`` recreates a profile when a profile with the same name already +exists. ``merge=True`` fetches the existing profile and updates it with the +non-null attributes passed by the caller. + +Profile actions +=============== + +.. list-table:: Common profile actions + :header-rows: 1 + :widths: 25 75 + :align: left + + * - Method + - Description + * - ``show_sql()`` + - Generates SQL for a natural language prompt without executing it. + * - ``run_sql()`` + - Generates SQL, executes it, and returns a ``pandas.DataFrame``. + * - ``narrate()`` + - Generates SQL, executes it, and returns a natural language answer. + * - ``explain_sql()`` + - Explains the generated SQL for a prompt. + * - ``show_prompt()`` + - Shows the prompt sent to the model. + * - ``chat()`` + - Sends a general chat prompt to the model. + * - ``summarize()`` + - Summarizes inline content or content referenced by a URI. + * - ``translate()`` + - Translates text from one language to another. ******************** Profile Object Model @@ -37,6 +91,9 @@ Base ``Profile`` API Create Profile ************************** +The following example creates an OCI Gen AI profile that can generate SQL over +objects in the ``SH`` schema. + .. literalinclude:: ../../../samples/profile_create.py :language: python :lines: 14- @@ -74,6 +131,66 @@ output:: .. latex:clearpage:: +************************** +Reuse Profile +************************** + +After a profile has been created, instantiate ``Profile`` with only the profile +name to reuse the database profile: + +.. code-block:: python + + profile = select_ai.Profile(profile_name="oci_ai_profile") + sql = profile.show_sql(prompt="How many promotions?") + +Use ``Profile.fetch(...)`` when you want to create a proxy object from a saved +database profile and raise an error if the profile does not exist: + +.. code-block:: python + + profile = select_ai.Profile.fetch("oci_ai_profile") + +.. latex:clearpage:: + +************************** +Update Profile +************************** + +Use ``set_attribute(...)`` to update one profile attribute or +``set_attributes(...)`` to update several attributes. Updates are saved to the +database profile. + +.. code-block:: python + + profile = select_ai.Profile(profile_name="oci_ai_profile") + profile.set_attribute("temperature", 0.1) + + profile.set_attributes( + select_ai.ProfileAttributes( + max_tokens=2048, + enforce_object_list=True, + ) + ) + +.. latex:clearpage:: + +************************** +Delete Profile +************************** + +Use ``delete(...)`` or ``Profile.delete_profile(...)`` to remove a profile from +the database. Pass ``force=True`` when cleanup should succeed even if the +profile does not exist. + +.. code-block:: python + + profile = select_ai.Profile(profile_name="oci_ai_profile") + profile.delete(force=True) + + select_ai.Profile.delete_profile("oci_ai_profile", force=True) + +.. latex:clearpage:: + ************************** Narrate ************************** @@ -105,6 +222,37 @@ output:: .. latex:clearpage:: +************************** +Explain SQL +************************** + +Use ``explain_sql(...)`` to generate SQL and return a natural language +explanation without executing the SQL. + +.. code-block:: python + + profile = select_ai.Profile(profile_name="oci_ai_profile") + explanation = profile.explain_sql(prompt="How many promotions?") + print(explanation) + +.. latex:clearpage:: + +************************** +Show Prompt +************************** + +Use ``show_prompt(...)`` to inspect the prompt that Select AI sends to the +model. This is useful when tuning profile attributes, object lists, comments, +constraints, and provider settings. + +.. code-block:: python + + profile = select_ai.Profile(profile_name="oci_ai_profile") + prompt = profile.show_prompt(prompt="How many promotions?") + print(prompt) + +.. latex:clearpage:: + ************************** Run SQL ************************** @@ -224,6 +372,10 @@ output:: List profiles ************************** +Profile listing returns profiles visible to the connected database user. +Instantiate ``Profile`` with one of the returned names to reuse the saved +profile. + .. literalinclude:: ../../../samples/profiles_list.py :language: python :lines: 14- @@ -235,15 +387,3 @@ output:: OCI_VECTOR_AI_PROFILE ASYNC_OCI_VECTOR_AI_PROFILE OCI_AI_PROFILE - -.. latex:clearpage:: - -************* -Async Profile -************* - -.. toctree:: - :numbered: - :maxdepth: 3 - - async_profile.rst diff --git a/doc/source/user_guide/profile_attributes.rst b/doc/source/user_guide/profile_attributes.rst index eb5146a..4adf67a 100644 --- a/doc/source/user_guide/profile_attributes.rst +++ b/doc/source/user_guide/profile_attributes.rst @@ -4,9 +4,130 @@ ``ProfileAttributes`` ************************* -This class defines attributes to manage and configure the behavior of -the AI profile. The ``ProfileAttributes`` objects are created -by ``select_ai.ProfileAttributes()``. +This class defines attributes that manage and configure the behavior of an AI +profile. ``ProfileAttributes`` objects are created with +``select_ai.ProfileAttributes()`` and passed to ``select_ai.Profile`` or +``select_ai.AsyncProfile`` when creating or updating a profile. + +Profile attributes describe what the profile can access, which AI provider it +uses, how much metadata is sent to the model, and how generation should behave. +Provider-specific settings, such as OCI region or Azure deployment name, are +configured on the provider object and assigned to the ``provider`` attribute. + +Common required attributes +========================== + +Most profiles need these attributes: + +* ``provider``: A ``select_ai.Provider`` object, such as + ``select_ai.OCIGenAIProvider`` or ``select_ai.OpenAIProvider``. +* ``credential_name``: The database credential used to authenticate with the + AI provider. +* ``object_list``: The schemas, tables, or views that Select AI can use when + generating SQL from natural language prompts. + +For example: + +.. code-block:: python + + attributes = select_ai.ProfileAttributes( + provider=select_ai.OCIGenAIProvider( + region="us-chicago-1", + oci_apiformat="GENERIC", + ), + credential_name="my_oci_ai_profile_key", + object_list=[ + {"owner": "SH", "name": "CUSTOMERS"}, + {"owner": "SH", "name": "SALES"}, + ], + ) + +Attribute groups +================ + +.. list-table:: Profile attribute groups + :header-rows: 1 + :widths: 30 70 + :align: left + + * - Attribute + - Purpose + * - ``provider`` + - Selects the AI provider, model, endpoint, and provider-specific + options. + * - ``credential_name`` + - Names the database credential used to authenticate with the AI provider. + * - ``object_list`` + - Defines which schemas, tables, or views are eligible for natural + language to SQL generation. + * - ``object_list_mode`` + - Controls whether Select AI sends metadata for the most relevant objects + or for all eligible objects. + * - ``enforce_object_list`` + - Restricts generated SQL to objects in ``object_list``. + * - ``comments``, ``constraints``, ``annotations`` + - Controls whether additional database metadata is included in the prompt + sent to the model. + * - ``case_sensitive_values`` + - Helps prompts that depend on case-sensitive database values. + * - ``max_tokens``, ``temperature``, ``stop_tokens``, ``seed`` + - Tunes model generation behavior. + * - ``conversation`` + - Enables conversation history for context-aware chat workflows. + * - ``vector_index_name``, ``enable_sources``, + ``enable_source_offsets``, ``enable_custom_source_uri`` + - Configures retrieval-augmented generation and source reporting for + vector index workflows. + +Object list examples +==================== + +Grant access to every supported object in a schema: + +.. code-block:: python + + object_list = [{"owner": "SH"}] + +Grant access to selected tables: + +.. code-block:: python + + object_list = [ + {"owner": "SH", "name": "CUSTOMERS"}, + {"owner": "SH", "name": "SALES"}, + {"owner": "SH", "name": "PRODUCTS"}, + ] + +Restrict generated SQL to the selected objects: + +.. code-block:: python + + attributes = select_ai.ProfileAttributes( + provider=provider, + credential_name="my_oci_ai_profile_key", + object_list=[ + {"owner": "SH", "name": "CUSTOMERS"}, + {"owner": "SH", "name": "SALES"}, + ], + enforce_object_list=True, + ) + +Generation controls +=================== + +Use generation controls when you need more predictable or constrained model +responses: + +.. code-block:: python + + attributes = select_ai.ProfileAttributes( + provider=provider, + credential_name="my_oci_ai_profile_key", + object_list=[{"owner": "SH"}], + max_tokens=1024, + temperature=0.1, + stop_tokens='[";"]', + ) .. autoclass:: select_ai.ProfileAttributes :members: diff --git a/doc/source/user_guide/provider.rst b/doc/source/user_guide/provider.rst index c5e5a7f..f75f007 100644 --- a/doc/source/user_guide/provider.rst +++ b/doc/source/user_guide/provider.rst @@ -1,97 +1,211 @@ .. _provider: +Provider +======== + An AI Provider in Select AI refers to the service provider of the LLM, transformer or both for processing and generating responses to natural language prompts. These providers offer models that can interpret and convert natural language for the use cases highlighted under the LLM concept. See `Select your AI Provider `__ -for the supported providers +for the supported providers. + +A provider object describes the AI service that a Select AI profile, vector +index, or agent tool should call. The provider object is separate from the +credential object: the provider selects the service, model, endpoint, region, +and provider-specific options, while the credential stores authentication +details. + +Most applications should instantiate one of the concrete provider classes +instead of using ``Provider`` directly. Use the base ``Provider`` class when +you need to call a compatible provider endpoint that does not have a dedicated +class in this library. + +.. list-table:: Provider classes + :header-rows: 1 + :widths: 30 35 35 + :align: left + + * - Provider class + - Provider name + - Default endpoint behavior + * - ``AnthropicProvider`` + - ``anthropic`` + - Uses ``api.anthropic.com``. + * - ``AWSProvider`` + - ``aws`` + - Builds ``bedrock-runtime..amazonaws.com`` from ``region``. + * - ``AzureProvider`` + - ``azure`` + - Builds ``.openai.azure.com``. + * - ``CohereProvider`` + - ``cohere`` + - Uses ``api.cohere.ai``. + * - ``GoogleProvider`` + - ``google`` + - Uses ``generativelanguage.googleapis.com``. + * - ``HuggingFaceProvider`` + - ``huggingface`` + - Uses ``api-inference.huggingface.co``. + * - ``OCIGenAIProvider`` + - ``oci`` + - Uses OCI region and OCI Gen AI attributes. + * - ``OpenAIProvider`` + - ``openai`` + - Uses ``api.openai.com``. + +Examples +-------- + +OCI Gen AI provider: + +.. code-block:: python + + provider = select_ai.OCIGenAIProvider( + region="us-chicago-1", + oci_apiformat="GENERIC", + model="cohere.command-r-plus", + ) + +OpenAI provider: + +.. code-block:: python + + provider = select_ai.OpenAIProvider( + model="gpt-4.1", + ) + +Azure OpenAI provider: + +.. code-block:: python + + provider = select_ai.AzureProvider( + azure_resource_name="my-azure-openai-resource", + azure_deployment_name="gpt-4o-deployment", + azure_embedding_deployment_name="text-embedding-deployment", + ) + +AWS Bedrock provider: + +.. code-block:: python + + provider = select_ai.AWSProvider( + region="us-east-1", + aws_apiformat="ANTHROPIC", + model="anthropic.claude-3-5-sonnet-20240620-v1:0", + ) + +Custom provider endpoint: + +.. code-block:: python + + select_ai.create_credential( + credential={ + "credential_name": "xai_credential", + "username": "xai", + "password": "", + }, + replace=True, + ) + + xai_profile = select_ai.Profile( + profile_name="xai", + attributes=select_ai.ProfileAttributes( + provider=select_ai.Provider( + provider_endpoint="https://api.x.ai", + model="grok-4-1-fast-reasoning", + ), + credential_name="xai_credential", + object_list=[ + {"owner": "SH", "name": "CUSTOMERS"}, + {"owner": "SH", "name": "SALES"}, + {"owner": "SH", "name": "PRODUCTS"}, + {"owner": "SH", "name": "COUNTRIES"}, + ], + ), + replace=True, + ) + + sql = xai_profile.show_sql( + prompt="How many customers do I have?", + ) .. latex:clearpage:: -********************** ``Provider`` -********************** +------------ .. autoclass:: select_ai.Provider :members: .. latex:clearpage:: -********************************* ``AnthropicProvider`` -********************************* +--------------------- .. autoclass:: select_ai.AnthropicProvider :members: .. latex:clearpage:: -***************************** ``AzureProvider`` -***************************** +----------------- .. autoclass:: select_ai.AzureProvider :members: .. latex:clearpage:: -***************************** ``AWSProvider`` -***************************** +--------------- .. autoclass:: select_ai.AWSProvider :members: .. latex:clearpage:: -****************************** ``CohereProvider`` -****************************** +------------------ .. autoclass:: select_ai.CohereProvider :members: .. latex:clearpage:: -***************************** ``OpenAIProvider`` -***************************** +------------------ .. autoclass:: select_ai.OpenAIProvider :members: .. latex:clearpage:: -****************************** ``OCIGenAIProvider`` -****************************** +-------------------- .. autoclass:: select_ai.OCIGenAIProvider :members: .. latex:clearpage:: -****************************** ``GoogleProvider`` -****************************** +------------------ .. autoclass:: select_ai.GoogleProvider :members: .. latex:clearpage:: -*********************************** ``HuggingFaceProvider`` -*********************************** +----------------------- .. autoclass:: select_ai.HuggingFaceProvider :members: .. latex:clearpage:: -************************** Enable AI service provider -************************** +-------------------------- Enable using Sync API +++++++++++++++++++++ This method adds ACL allowing database users to invoke AI provider's -HTTP endpoint +HTTP endpoint. For non-HTTP or port-specific network access, use the network +ACL helpers described in :ref:`Privileges `. .. literalinclude:: ../../../samples/enable_ai_provider.py :language: python @@ -115,12 +229,11 @@ output:: .. latex:clearpage:: -*************************** Disable AI service provider -*************************** +--------------------------- -This method removes ACL blocking database users to invoke AI provider's -HTTP endpoint +This method removes the ACL entry that allows database users to invoke an AI +provider's HTTP endpoint. Disable using Sync API ++++++++++++++++++++++ diff --git a/doc/source/user_guide/summary.rst b/doc/source/user_guide/summary.rst index 300394d..d21c9f0 100644 --- a/doc/source/user_guide/summary.rst +++ b/doc/source/user_guide/summary.rst @@ -1,5 +1,109 @@ .. _summary: +Summarization uses a Select AI profile to summarize inline text or content +available from a URI. The profile supplies the AI provider, model, credential, +and generation settings. The ``summarize`` APIs are available on both +``Profile`` and ``AsyncProfile``. + +Use one content source per call: + +* ``content`` for inline text. +* ``location_uri`` for content available from a URL, object storage URI, or + supported file location. + +Use ``credential_name`` when the ``location_uri`` requires a database +credential, such as object storage access. Use ``prompt`` to guide what the +summary should focus on. + +Inline content +============== + +.. code-block:: python + + profile = select_ai.Profile(profile_name="oci_ai_profile") + + summary = profile.summarize( + content="Long text to summarize...", + prompt="Summarize the key business implications.", + ) + print(summary) + +Content from a URI +================== + +.. code-block:: python + + profile = select_ai.Profile(profile_name="oci_ai_profile") + + summary = profile.summarize( + location_uri="https://en.wikipedia.org/wiki/Astronomy", + ) + print(summary) + +Content from object storage +=========================== + +Pass ``credential_name`` when the target location requires authentication: + +.. code-block:: python + + profile = select_ai.Profile(profile_name="oci_ai_profile") + + summary = profile.summarize( + location_uri=( + "https://objectstorage.us-ashburn-1.oraclecloud.com/" + "n/namespace/b/bucket/o/document.txt" + ), + credential_name="OBJECT_STORE_CRED", + ) + print(summary) + +Summary parameters +================== + +Use ``SummaryParams`` to control output length, output style, chunk processing, +and extractiveness: + +.. code-block:: python + + params = select_ai.summary.SummaryParams( + min_words=50, + max_words=150, + summary_style=select_ai.summary.Style.LIST, + chunk_processing_method=( + select_ai.summary.ChunkProcessingMethod.MAP_REDUCE + ), + extractiveness_level=select_ai.summary.ExtractivenessLevel.MEDIUM, + ) + + summary = profile.summarize( + content="Long text to summarize...", + params=params, + ) + +Async summary +============= + +.. code-block:: python + + async_profile = await select_ai.AsyncProfile( + profile_name="async_oci_ai_profile", + ) + + summary = await async_profile.summarize( + content="Long text to summarize...", + prompt="Summarize the main points.", + ) + print(summary) + +Validation +========== + +``summarize`` requires exactly one of ``content`` or ``location_uri``. Passing +both, or passing neither, raises an error. + +.. latex:clearpage:: + ******************************* SummaryParams ******************************* diff --git a/doc/source/user_guide/synthetic_data.rst b/doc/source/user_guide/synthetic_data.rst index 4e4170d..c607360 100644 --- a/doc/source/user_guide/synthetic_data.rst +++ b/doc/source/user_guide/synthetic_data.rst @@ -1,5 +1,107 @@ .. _synthetic_data: +Synthetic data generation uses a Select AI profile to populate database tables +with generated rows. It is useful for demos, development, testing, and +prototyping when representative data is needed but production data should not +be copied. + +Synthetic data is inserted into the target tables in the connected database +schema or in the schema identified by ``owner_name`` or ``object_list``. Before +running generation, make sure the connected user has privileges on the target +tables and that the Select AI profile is configured with a provider and +credential. + +Use synthetic data generation with care in shared schemas. The API writes rows +to the target tables; use dedicated test tables or schemas when experimenting. + +Generation modes +================ + +Use ``object_name`` for a single target table: + +.. code-block:: python + + attributes = select_ai.SyntheticDataAttributes( + object_name="MOVIE", + record_count=100, + user_prompt="the release date for the movies should be in 2019", + ) + +Use ``object_list`` for multiple target tables in one request: + +.. code-block:: python + + attributes = select_ai.SyntheticDataAttributes( + object_list=[ + { + "owner": "SH", + "name": "MOVIE", + "record_count": 100, + "user_prompt": ( + "the release date for the movies should be in 2019" + ), + }, + {"owner": "SH", "name": "ACTOR", "record_count": 10}, + {"owner": "SH", "name": "DIRECTOR", "record_count": 5}, + ] + ) + +Exactly one of ``object_name`` or ``object_list`` must be set. + +Generation parameters +===================== + +Use ``SyntheticDataParams`` to control how generation is performed: + +.. code-block:: python + + params = select_ai.SyntheticDataParams( + sample_rows=100, + table_statistics=True, + priority="HIGH", + comments=True, + ) + + attributes = select_ai.SyntheticDataAttributes( + object_name="MOVIE", + record_count=100, + user_prompt="Generate movie data for releases in 2019.", + params=params, + ) + +``sample_rows`` controls how many existing rows are used as examples for the +model. ``table_statistics`` and ``comments`` include additional table metadata. +``priority`` controls resource priority for generation work; supported values +are ``HIGH``, ``MEDIUM``, and ``LOW``. + +Sync and async APIs +=================== + +Use ``Profile.generate_synthetic_data(...)`` for synchronous applications and +``await AsyncProfile.generate_synthetic_data(...)`` for asynchronous +applications: + +.. code-block:: python + + profile = select_ai.Profile(profile_name="oci_ai_profile") + profile.generate_synthetic_data( + synthetic_data_attributes=attributes, + ) + +.. code-block:: python + + async_profile = await select_ai.AsyncProfile( + profile_name="async_oci_ai_profile", + ) + await async_profile.generate_synthetic_data( + synthetic_data_attributes=attributes, + ) + +For additional database-side attribute details, see the +`generate_synthetic_data PL/SQL API `__. + +.. latex:clearpage:: + *************************** ``SyntheticDataAttributes`` *************************** @@ -16,9 +118,6 @@ .. autoclass:: select_ai.SyntheticDataParams :members: -Also, check the `generate_synthetic_data PL/SQL API `__ -for attribute details - .. latex:clearpage:: **************************** @@ -44,7 +143,7 @@ output:: .. latex:clearpage:: -Singe Table Async API +Single Table Async API +++++++++++++++++++++ .. literalinclude:: ../../../samples/async/profile_gen_single_table_synthetic_data.py @@ -66,7 +165,7 @@ output:: Multi table synthetic data **************************** -The below example shows multitable synthetic data generation +The below example shows multi-table synthetic data generation Multi table Sync API ++++++++++++++++++++ diff --git a/doc/source/user_guide/vector_index.rst b/doc/source/user_guide/vector_index.rst index d423e4c..f90e4d4 100644 --- a/doc/source/user_guide/vector_index.rst +++ b/doc/source/user_guide/vector_index.rst @@ -1,9 +1,39 @@ .. _vector_index: -``VectorIndex`` supports Retrieval Augmented Generation (RAG). -For e.g., you can convert text into vector embeddings and store them in a -vector store. Select AI will augment the natural language prompt by retrieving -content from the vector store using semantic similarity search. +************ +Vector Index +************ + +``VectorIndex`` supports Retrieval Augmented Generation (RAG). It converts +source documents into vector embeddings, stores the embeddings in a vector +store, and links the vector index to a Select AI profile. When that profile is +used for natural language generation, Select AI can retrieve semantically +similar content from the vector index and use that content as grounding context +for the response. + +A vector index is useful when the answer should come from files or documents +that are not represented as relational tables. Typical sources include +documents in Object Storage, product manuals, generated reports, logs, JSON +files, and other text-heavy content that should be searched by meaning rather +than exact keywords. + +Before creating a vector index, make sure the database user has: + +* A Select AI profile with an AI provider that supports embeddings. +* A credential for the AI provider used by the profile. +* A credential for the object storage location if the source objects are not + public. +* Network access to the AI provider endpoint and the source location. See + :ref:`Privileges ` for network ACL helpers. + +The usual lifecycle is: + +1. Create a profile with a provider and embedding model. +2. Create ``OracleVectorIndexAttributes`` with the source location and storage + credential. +3. Create ``VectorIndex`` and call ``create()``. +4. Use the linked profile for RAG actions such as ``narrate()``. +5. Fetch, list, update, disable, enable, or delete the index as needed. **************************** ``VectorIndex`` Object Model @@ -23,6 +53,69 @@ A ``VectorIndexAttributes`` object can be created with ``select_ai.VectorIndexAttributes()``. Also check `vector index attributes `__ +For Oracle vector indexes, use ``OracleVectorIndexAttributes``. It sets +``vector_db_provider`` to ``VectorDBProvider.ORACLE`` and is the preferred +attribute class for the examples in this guide. + +Common attributes: + +.. list-table:: + :header-rows: 1 + + * - Attribute + - Use + * - ``location`` + - Object Storage URI or source location containing the documents to + embed. + * - ``object_storage_credential_name`` + - Credential used to read the source location. + * - ``profile_name`` + - Select AI profile used to create embeddings and answer RAG prompts. + If omitted during ``create()``, it is taken from the ``profile`` object + passed to ``VectorIndex``. + * - ``chunk_size`` and ``chunk_overlap`` + - Control how source text is split before embedding. Larger chunks keep + more context together; overlap helps preserve context across chunk + boundaries. + * - ``match_limit`` + - Maximum number of matching chunks returned during semantic search. + * - ``similarity_threshold`` + - Minimum similarity score required for retrieved chunks to be considered + relevant. + * - ``vector_distance_metric`` + - Distance metric used to compare embeddings. Supported values include + ``COSINE``, ``EUCLIDEAN``, ``L2_SQUARED``, ``DOT``, ``MANHATTAN``, and + ``HAMMING``. + * - ``refresh_rate`` + - Refresh interval, in minutes, for loading new or changed source data. + * - ``vector_table_name`` + - Name of the table used to store vector embeddings and chunked data. + Leave unset unless you need to control the storage table name. + * - ``enable_sources`` + - Include filenames and source links in RAG output when supported by the + profile and model response. + +Example attributes: + +.. code-block:: python + + attributes = select_ai.OracleVectorIndexAttributes( + location="https://objectstorage.us-ashburn-1.oraclecloud.com/n/example/b/docs/o/product-guides", + object_storage_credential_name="object_store_credential", + chunk_size=1024, + chunk_overlap=128, + match_limit=5, + similarity_threshold=0.5, + vector_distance_metric=select_ai.VectorDistanceMetric.COSINE, + refresh_rate=1440, + ) + +The embedding model is configured on the provider inside the linked +``ProfileAttributes``. Keep the profile provider and vector index attributes +together conceptually: the profile decides how embeddings are generated, while +the vector index attributes decide where content is read from, how it is +chunked, and how the vector store is searched. + .. autoclass:: select_ai.VectorIndexAttributes :members: @@ -40,14 +133,47 @@ A ``VectorIndexAttributes`` object can be created with ``VectorIndex`` API ******************** - A ``VectorIndex`` object can be created with ``select_ai.VectorIndex()`` .. autoclass:: select_ai.VectorIndex :members: -Check the examples below to understand how to create vector indexes +Use the synchronous API in scripts, notebooks, and command-line tools that use +``select_ai.connect()``. Use ``AsyncVectorIndex`` in applications already using +``asyncio`` and ``select_ai.async_connect()`` or an async connection pool. + +Important lifecycle methods: + +.. list-table:: + :header-rows: 1 + + * - Method + - Use + * - ``create(replace=False, wait_for_completion=False)`` + - Create the database vector index and start the load pipeline. If + ``replace=True`` and the index already exists, the existing index is + dropped and recreated. Use ``wait_for_completion=True`` when the next + step depends on the initial load being complete. + * - ``fetch(index_name)`` + - Build a ``VectorIndex`` proxy from database metadata, including + attributes and the linked profile when it still exists. + * - ``list(index_name_pattern=".*")`` + - Iterate over vector indexes visible to the current user. The pattern is + evaluated with Oracle ``REGEXP_LIKE``. + * - ``set_attribute()`` and ``set_attributes()`` + - Update one or more index attributes. + * - ``get_next_refresh_timestamp()`` + - Return the next scheduled refresh timestamp in UTC when the index has a + refresh rate and a recorded pipeline execution. + * - ``disable()`` and ``enable()`` + - Pause or resume use of the vector index for loading, indexing, + searching, and querying. + * - ``delete(include_data=True, force=False)`` + - Drop the vector index. ``include_data=True`` also removes associated + vector store data. ``force=True`` ignores missing-index errors. + +Check the examples below to understand how to create vector indexes. .. latex:clearpage:: @@ -55,7 +181,9 @@ Create vector index +++++++++++++++++++ In the following example, vector database provider is Oracle and -objects (to create embedding for) reside in OCI's object store +objects used to create embeddings reside in OCI Object Storage. The profile +uses an OCI Generative AI provider with an embedding model, and the vector +index is linked to that profile during ``create()``. .. literalinclude:: ../../../samples/vector_index_create.py :language: python @@ -86,7 +214,9 @@ Fetch vector index +++++++++++++++++++++++++++ You can fetch the vector index attributes and associated AI profile using -the class method ``VectorIndex.fetch(index_name)`` +the class method ``VectorIndex.fetch(index_name)``. Fetch is useful when the +index was created earlier or by another process and you want to inspect or +update it without recreating the original Python object. .. literalinclude:: ../../../samples/vector_index_fetch.py :language: python @@ -104,7 +234,8 @@ Update vector index attributes ++++++++++++++++++++++++++++++ To update attributes, use either ``vector_index.set_attribute()`` or -``vector_index.set_attributes()`` +``vector_index.set_attributes()``. Use ``set_attribute()`` for a single value +and ``set_attributes()`` when updating several values together. .. literalinclude:: ../../../samples/vector_index_update_attributes.py :language: python @@ -119,6 +250,11 @@ output:: RAG using vector index ++++++++++++++++++++++ +After ``create()`` succeeds, the profile has its ``vector_index_name`` set to +the new index. Use that profile with text-returning actions such as +``narrate()`` to retrieve relevant chunks from the vector index and ground the +answer in the indexed content. + .. literalinclude:: ../../../samples/vector_index_rag.py :language: python :lines: 14- @@ -144,6 +280,11 @@ output:: Delete vector index +++++++++++++++++++ +Use ``delete()`` when the index is no longer needed. By default, +``include_data=True`` removes the vector index metadata and the associated +vector store data. Set ``include_data=False`` only when you intentionally want +to keep the underlying vector store data. + .. literalinclude:: ../../../samples/vector_index_delete.py :language: python :lines: 12- @@ -158,11 +299,34 @@ output:: ``AsyncVectorIndex`` API ************************ -A ``AsyncVectorIndex`` object can be created with ``select_ai.AsyncVectorIndex()`` +An ``AsyncVectorIndex`` object can be created with +``select_ai.AsyncVectorIndex()`` .. autoclass:: select_ai.AsyncVectorIndex :members: +The async API mirrors the synchronous API. Async profile construction and +vector index methods that access the database must be awaited, and +``AsyncVectorIndex.list()`` is an async iterator. + +.. list-table:: + :header-rows: 1 + + * - Synchronous API + - Async API + * - ``select_ai.connect(...)`` + - ``await select_ai.async_connect(...)`` + * - ``Profile(...)`` + - ``await AsyncProfile(...)`` + * - ``VectorIndex.create(...)`` + - ``await AsyncVectorIndex.create(...)`` + * - ``VectorIndex.fetch(...)`` + - ``await AsyncVectorIndex.fetch(...)`` + * - ``for index in VectorIndex.list(...)`` + - ``async for index in AsyncVectorIndex.list(...)`` + * - ``profile.narrate(...)`` + - ``await async_profile.narrate(...)`` + .. latex:clearpage:: Async create vector index diff --git a/doc/source/user_guide/web_frameworks.rst b/doc/source/user_guide/web_frameworks.rst index 40f354e..42baefb 100644 --- a/doc/source/user_guide/web_frameworks.rst +++ b/doc/source/user_guide/web_frameworks.rst @@ -9,15 +9,64 @@ application starts and close it when the application shuts down. A pool lets concurrent requests share a bounded set of database connections instead of creating standalone connections per request. -This pattern works with Python WSGI and ASGI frameworks. FastAPI is used below +This pattern works with Python Web Server Gateway Interface (WSGI) and +Asynchronous Server Gateway Interface (ASGI) frameworks. FastAPI is used below as a concrete example, but the same approach applies to frameworks such as Flask, Django, Starlette, Sanic, and Quart: initialize the pool during application startup, use ``select_ai`` APIs inside request handlers, and close the pool during application shutdown. +Do not call ``select_ai.connect()`` or ``select_ai.create_pool()`` inside every +request handler. Creating connections per request adds latency, increases +database connection churn, and can exhaust the database connection limit under +load. Create one pool per worker process and let ``select_ai`` acquire and +release connections from that pool for each API call. + For background and concurrency measurements, see this `connection pooling blog `__. +Framework patterns +================== + +Use the framework lifecycle API that runs once per process: + +* `FastAPI `__ / + `Starlette `__: use a ``lifespan`` async + context manager. Create the pool before ``yield`` and close it after + ``yield``. + +* `Flask `__: + create the pool in ``create_app()``. Close the pool from the shutdown hook + provided by the process that runs Flask, such as a Gunicorn ``worker_exit`` + hook. For simple local applications, ``atexit.register()`` can be used for + normal interpreter shutdown. + +* `Django `__: + create the pool in ``AppConfig.ready()``. Close the pool from the shutdown + hook provided by the process that runs Django, such as a Gunicorn + ``worker_exit`` hook. For simple local applications, ``atexit.register()`` + can be used for normal interpreter shutdown. + +* `Quart `__: + use ``@app.before_serving`` / ``@app.after_serving``, or + ``@app.while_serving`` with cleanup after ``yield``. + +* `Sanic `__: use + ``@app.before_server_start`` and ``@app.after_server_stop``. + +Use ``select_ai.create_pool()`` for synchronous request handlers and +``select_ai.create_pool_async()`` for asynchronous request handlers. In +general, synchronous routes should call synchronous Select AI methods, and async +routes should call async Select AI methods. Avoid mixing blocking synchronous +database calls into async routes unless the framework runs them in a worker +thread. + +For Flask and Django, be careful with hooks that run per request or per +application context. A Select AI pool should live for the worker process, not +for a single request. For example, Flask's ``teardown_appcontext`` runs when an +application context is popped, so it is not a good place to close a process-wide +pool after every request. + Install dependencies ==================== @@ -42,6 +91,10 @@ variables: If you use an mTLS wallet, also set ``TNS_ADMIN`` or pass wallet parameters to ``select_ai.create_pool()`` / ``select_ai.create_pool_async()``. +For production deployments, store these values in your deployment platform's +secret manager or environment configuration. Do not hard-code database +passwords, wallet passwords, or provider credentials in application source. + FastAPI synchronous endpoints ============================= @@ -109,6 +162,10 @@ Stop the server by pressing ``Ctrl+C`` in the terminal where ``uvicorn`` is running. FastAPI runs the lifespan shutdown hook and ``select_ai.disconnect()`` closes the pool. +This example creates the ``Profile`` proxy inside each handler. The proxy is +lightweight; the database connection is acquired from the pool only when the +profile method calls the database. + FastAPI asynchronous endpoints ============================== @@ -162,6 +219,95 @@ Start and stop the server the same way: Press ``Ctrl+C`` to stop it. +Flask example +============= + +Flask applications normally use synchronous request handlers, so initialize a +synchronous Select AI pool when the application is created. + +.. code-block:: python + + import atexit + import os + + from flask import Flask, jsonify, request + + import select_ai + + + def create_app(): + app = Flask(__name__) + + select_ai.create_pool( + user=os.getenv("SELECT_AI_USER"), + password=os.getenv("SELECT_AI_PASSWORD"), + dsn=os.getenv("SELECT_AI_DB_CONNECT_STRING"), + min_size=int(os.getenv("SELECT_AI_POOL_MIN", "1")), + max_size=int(os.getenv("SELECT_AI_POOL_MAX", "4")), + increment=int(os.getenv("SELECT_AI_POOL_INCREMENT", "1")), + ) + + @app.get("/show_sql") + def show_sql(): + prompt = request.args["prompt"] + profile = select_ai.Profile(profile_name="oci_ai_profile") + return jsonify({"sql": profile.show_sql(prompt=prompt)}) + + @atexit.register + def close_select_ai_pool(): + if select_ai.is_connected(): + select_ai.disconnect() + + return app + +Django example +============== + +Django has its own database connection management, but ``select_ai`` uses the +Oracle Database connection pool created by this package. Create the Select AI +pool once per process, then call ``Profile`` APIs inside views. + +.. code-block:: python + + # myapp/apps.py + import os + + from django.apps import AppConfig + + import select_ai + + + class MyAppConfig(AppConfig): + name = "myapp" + + def ready(self): + if not select_ai.is_connected(): + select_ai.create_pool( + user=os.getenv("SELECT_AI_USER"), + password=os.getenv("SELECT_AI_PASSWORD"), + dsn=os.getenv("SELECT_AI_DB_CONNECT_STRING"), + min_size=int(os.getenv("SELECT_AI_POOL_MIN", "1")), + max_size=int(os.getenv("SELECT_AI_POOL_MAX", "4")), + increment=int(os.getenv("SELECT_AI_POOL_INCREMENT", "1")), + ) + +.. code-block:: python + + # myapp/views.py + from django.http import JsonResponse + + import select_ai + + + def show_sql(request): + profile = select_ai.Profile(profile_name="oci_ai_profile") + sql = profile.show_sql(prompt=request.GET["prompt"]) + return JsonResponse({"sql": sql}) + +When using Django's development autoreloader, startup hooks may run more than +once. The ``is_connected()`` check prevents this example from creating a second +pool in the same process. + Pool sizing =========== @@ -180,3 +326,49 @@ possible database connections are approximately: Choose pool sizes that leave capacity for other database clients and avoid overwhelming small database deployments. + +For example, a service running four worker processes with +``SELECT_AI_POOL_MAX=10`` can open up to forty Select AI database connections. +If the database can only spare twenty connections for the application, use fewer +workers, reduce ``SELECT_AI_POOL_MAX``, or both. + +Pool wait behavior +================== + +``select_ai.create_pool()`` and ``select_ai.create_pool_async()`` pass pool +options through to ``python-oracledb``. Use ``wait_timeout`` and ``getmode`` to +control what happens when all pooled connections are busy. + +.. code-block:: python + + select_ai.create_pool( + user=user, + password=password, + dsn=dsn, + min_size=2, + max_size=8, + increment=2, + wait_timeout=10, + ) + +Choose a timeout that matches your API latency budget. For public HTTP APIs, +it is usually better to fail fast and return an application error than to let +requests pile up until every worker is blocked. + +Request handling +================ + +Validate prompts and profile names before calling Select AI methods. If clients +can choose a profile, check the requested profile against an application +allowlist instead of passing arbitrary user input directly into +``Profile(profile_name=...)``. + +For long-running prompts, set HTTP server timeouts and client timeouts +deliberately. Text generation and RAG calls can take longer than simple SQL +metadata operations, especially when external AI providers or object storage +are involved. + +For streaming responses, prefer async frameworks and async Select AI methods when +the rest of the application is already async. For ordinary JSON responses, +either synchronous or asynchronous routes are fine as long as the connection +pool matches the route style. diff --git a/docs/.buildinfo b/docs/.buildinfo index d21919a..3c0d0de 100644 --- a/docs/.buildinfo +++ b/docs/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file records the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 04c93cb781f3bb6be839c34359e8a2a4 +config: 294c5088c994145410d499729f743721 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/.buildinfo.bak b/docs/.buildinfo.bak index 260b419..65be50c 100644 --- a/docs/.buildinfo.bak +++ b/docs/.buildinfo.bak @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file records the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 3f9e662855e6bc50d7a46d00f43eb9be +config: 096e407c9f16dcad04a2dc3cf4917f24 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/_images/select_ai_cli_demo.gif b/docs/_images/select_ai_cli_demo.gif new file mode 100644 index 0000000..2483fd2 Binary files /dev/null and b/docs/_images/select_ai_cli_demo.gif differ diff --git a/docs/_sources/index.rst.txt b/docs/_sources/index.rst.txt index 55b2e84..0a2dc6a 100644 --- a/docs/_sources/index.rst.txt +++ b/docs/_sources/index.rst.txt @@ -48,7 +48,7 @@ Provider :numbered: :maxdepth: 3 - user_guide/provider.rst + Provider Credential ========== @@ -78,6 +78,14 @@ Profile user_guide/profile.rst +Async Profile +============= + +.. toctree:: + :numbered: + :maxdepth: 3 + + user_guide/async_profile.rst Conversation ============ @@ -125,3 +133,39 @@ AI Agent :maxdepth: 3 user_guide/agent.rst + +Async AI Agent +============== + +.. toctree:: + :numbered: + :maxdepth: 3 + + user_guide/async_agent.rst + +Command Line Interface +====================== + +.. toctree:: + :numbered: + :maxdepth: 3 + + user_guide/cli.rst + +Web Frameworks +============== + +.. toctree:: + :numbered: + :maxdepth: 3 + + user_guide/web_frameworks.rst + +Concurrent Prompt Processing +============================ + +.. toctree:: + :numbered: + :maxdepth: 3 + + user_guide/concurrent_prompt_processing.rst diff --git a/docs/_sources/user_guide/actions.rst.txt b/docs/_sources/user_guide/actions.rst.txt index 8cad7d5..82fafec 100644 --- a/docs/_sources/user_guide/actions.rst.txt +++ b/docs/_sources/user_guide/actions.rst.txt @@ -1,45 +1,154 @@ .. _actions: -An action in Select AI is a keyword that instructs Select AI to perform different behavior when acting on the prompt. +An action in Select AI is a keyword that instructs Select AI to perform +different behavior when acting on the prompt. + +Most applications use the convenience methods on ``Profile`` or +``AsyncProfile``, such as ``show_sql()``, ``run_sql()``, ``narrate()``, and +``chat()``. Use ``generate(..., action=...)`` when you want to choose the +action dynamically at runtime. + +The default action for ``generate()`` is ``select_ai.Action.RUNSQL``. ******************** Supported Actions ******************** -Following list of actions can be performed using ``select_ai`` +The following actions can be performed using ``select_ai``: .. list-table:: Select AI Actions - :header-rows: 1 - :widths: 20 30 50 - :align: left - - * - Actions - - Enum - - Description - * - chat - - ``select_ai.Action.CHAT`` - - Enables general conversations with the LLM, potentially for clarifying prompts, exploring data, or generating content. - * - explainsql - - ``select_ai.Action.EXPLAINSQL`` - - Explain the generated SQL query - * - narrate - - ``select_ai.Action.NARRATE`` - - Explains the output of the query in natural language, making the results accessible to users without deep technical expertise. - * - runsql - - ``select_ai.Action.RUNSQL`` - - Executes a SQL query generated from a natural language prompt. This is the default action. - * - showprompt - - ``select_ai.Action.SHOWPROMPT`` - - Show the details of the prompt sent to LLM - * - showsql - - ``select_ai.Action.SHOWSQL`` - - Displays the generated SQL statement without executing it. - * - summarize - - ``select_ai.Action.SUMMARIZE`` - - Generate summary of your large texts - * - feedback - - ``select_ai.Action.FEEDBACK`` - - Provide feedback to improve accuracy of the generated SQL - * - translate - - ``select_ai.Action.TRANSLATE`` - - Translate text from one language to another + :header-rows: 1 + :widths: 20 30 50 + :align: left + + * - Action + - Enum + - Description + * - chat + - ``select_ai.Action.CHAT`` + - Enables general conversations with the LLM, potentially for clarifying + prompts, exploring data, or generating content. + * - explainsql + - ``select_ai.Action.EXPLAINSQL`` + - Explains the generated SQL query. + * - narrate + - ``select_ai.Action.NARRATE`` + - Executes generated SQL and explains the output in natural language. + * - runsql + - ``select_ai.Action.RUNSQL`` + - Executes SQL generated from a natural language prompt. This is the + default action for ``generate()``. + * - showprompt + - ``select_ai.Action.SHOWPROMPT`` + - Shows the prompt sent to the LLM. + * - showsql + - ``select_ai.Action.SHOWSQL`` + - Displays the generated SQL statement without executing it. + * - summarize + - ``select_ai.Action.SUMMARIZE`` + - Generates a summary of inline content or content referenced by a URI. + * - feedback + - ``select_ai.Action.FEEDBACK`` + - Provides feedback to improve the accuracy of generated SQL. + * - translate + - ``select_ai.Action.TRANSLATE`` + - Translates text from one language to another. + +Action methods +============== + +.. list-table:: Action to method mapping + :header-rows: 1 + :widths: 30 35 35 + :align: left + + * - Action + - Convenience method + - Return type + * - ``RUNSQL`` + - ``profile.run_sql(prompt)`` + - ``pandas.DataFrame`` + * - ``SHOWSQL`` + - ``profile.show_sql(prompt)`` + - ``str`` + * - ``EXPLAINSQL`` + - ``profile.explain_sql(prompt)`` + - ``str`` + * - ``NARRATE`` + - ``profile.narrate(prompt)`` + - ``str`` + * - ``CHAT`` + - ``profile.chat(prompt)`` + - ``str`` + * - ``SHOWPROMPT`` + - ``profile.show_prompt(prompt)`` + - ``str`` + * - ``SUMMARIZE`` + - ``profile.summarize(...)`` + - ``str`` + * - ``TRANSLATE`` + - ``profile.translate(...)`` + - ``str`` + +Choosing an action +================== + +Use ``show_sql`` before ``run_sql`` when you want to inspect generated SQL +before executing it. Use ``run_sql`` when the application should return a +tabular result. Use ``narrate`` when users need a natural language answer +instead of a table. Use ``explain_sql`` and ``show_prompt`` when tuning profile +attributes, object lists, comments, constraints, or feedback. + +Examples +======== + +Use a convenience method: + +.. code-block:: python + + profile = select_ai.Profile(profile_name="oci_ai_profile") + sql = profile.show_sql(prompt="How many promotions?") + +Use ``generate`` with an explicit action: + +.. code-block:: python + + profile = select_ai.Profile(profile_name="oci_ai_profile") + + sql = profile.generate( + prompt="How many promotions?", + action=select_ai.Action.SHOWSQL, + ) + + df = profile.generate( + prompt="How many promotions?", + action=select_ai.Action.RUNSQL, + ) + +Use an action selected at runtime: + +.. code-block:: python + + action = select_ai.Action("showsql") + result = profile.generate( + prompt="How many promotions?", + action=action, + ) + +Streaming +========= + +Streaming is supported for text-returning generation actions: +``CHAT``, ``NARRATE``, ``EXPLAINSQL``, ``SHOWSQL``, and ``SHOWPROMPT``. +Streaming is not supported for ``RUNSQL`` because it returns a +``pandas.DataFrame``. + +.. code-block:: python + + for chunk in profile.generate( + prompt="What is OCI?", + action=select_ai.Action.CHAT, + stream=True, + chunk_size=4096, + ): + print(chunk, end="") diff --git a/docs/_sources/user_guide/agent.rst.txt b/docs/_sources/user_guide/agent.rst.txt index ad549e7..aad3c00 100644 --- a/docs/_sources/user_guide/agent.rst.txt +++ b/docs/_sources/user_guide/agent.rst.txt @@ -2,7 +2,8 @@ ``select_ai.agent`` adds a thin Python layer over Oracle Autonomous Database's ``DBMS_CLOUD_AI_AGENT`` package so you can define tools, compose tasks, wire up -agents and run teams from Python using the existing select_ai connection objects +agents and run teams from Python using the existing Select AI connection +objects. - Keep agent state and orchestration in the database @@ -11,6 +12,25 @@ agents and run teams from Python using the existing select_ai connection objects - Group agents into teams and invoke them with a single API call +Agent workflows build on the same setup used by profiles: connect to Oracle +Database, create or reuse a Select AI profile, create credentials for any +external service used by tools, and grant network access for external +endpoints. See :ref:`Connection `, :ref:`Profile `, +:ref:`Credential `, and :ref:`Privileges `. + +The usual agent workflow is: + +* Create tools that an agent can use. +* Create tasks that describe the work and list the tools available for that + task. +* Create an agent with a role and an LLM profile. +* Create a team that pairs agents with tasks. +* Run the team with a user prompt. + +Tools, tasks, agents, and teams are database objects. Use ``replace=True`` when +you want to recreate an existing object with the same name, and ``force=True`` +when cleanup should succeed even if the object does not exist. + .. latex:clearpage:: ******** @@ -21,6 +41,10 @@ A callable which Select AI agent can invoke to accomplish a certain task. Users can either register built-in tools or create a custom tool using a PL/SQL stored procedure. +Use focused tools with clear instructions. The task and agent prompts decide +when tools are used, so tool names, descriptions, and instructions should be +specific enough for the model to choose the right tool. + Supported Tools +++++++++++++++ @@ -45,11 +69,6 @@ Python layer and persist the tool in the Database using - ``recipient`` - ``sender`` - ``smtp_host`` - * - ``HTTP`` - - ``select_ai.agent.Tool.create_http_tool`` - - - ``tool_name`` - - ``credential_name`` - - ``endpoint`` * - ``SQL`` - ``select_ai.agent.Tool.create_sql_tool`` - - ``tool_name`` @@ -58,7 +77,7 @@ Python layer and persist the tool in the Database using - ``select_ai.agent.Tool.create_slack_notification_tool`` - - ``tool_name`` - ``credential_name`` - - ``slack_channel`` + - ``channel`` * - ``WEBSEARCH`` - ``select_ai.agent.Tool.create_websearch_tool`` - - ``tool_name`` @@ -72,6 +91,31 @@ Python layer and persist the tool in the Database using - - ``tool_name`` - ``profile_name`` +Tool selection +++++++++++++++ + +.. list-table:: When to use each tool + :header-rows: 1 + :widths: 25 75 + :align: left + + * - Tool type + - Use case + * - ``SQL`` + - Ask questions over database objects using a Select AI profile. + * - ``RAG`` + - Answer questions using content indexed by a vector index profile. + * - ``WEBSEARCH`` + - Search public web content using a web search credential. + * - ``SLACK`` + - Send a Slack notification from an agent workflow. + * - ``EMAIL`` + - Send an email notification from an agent workflow. + * - ``PL/SQL custom tool`` + - Call a database procedure or function for application-specific work. + +Notification and web search tools require credentials and network access for +the external service. SQL and RAG tools require existing Select AI profiles. .. latex:clearpage:: @@ -113,7 +157,7 @@ output:: profile_name='oci_ai_profile', recipient=None, sender=None, - slack_channel=None, + channel=None, smtp_host=None), tool_inputs=None, tool_type=) @@ -167,6 +211,10 @@ Create Task In the following task, we use the ``MOVIE_SQL_TOOL`` created in the previous step +The ``instruction`` is the main task prompt. Use placeholders such as +``{query}`` when the user prompt should be inserted into the task. The +``tools`` list limits which tools the agent can use for the task. + .. literalinclude:: ../../../samples/agent/task_create.py :language: python :lines: 14- @@ -208,6 +256,10 @@ optional description. The attributes must include key agent properties such as ``profile_name`` which specifies the LLM profile used for prompt generation and ``role``, which outlines the agent’s intended role and behavioral context. +The agent profile supplies the model used for planning and reasoning. The role +should describe the agent's domain, boundaries, and expected behavior. Keep the +role specific to the tasks assigned to the agent. + .. autoclass:: select_ai.agent.AgentAttributes :members: @@ -248,6 +300,22 @@ pairings, allowing users to assign specific tasks to designated agents. User can perform multiple tasks by assigning the same agent to different tasks. The ``process`` attribute defines how tasks should be executed. +Currently, ``process="sequential"`` is used to execute task assignments in +order. Reuse the same agent in multiple team entries when the agent should +perform multiple tasks. + +For example: + +.. code-block:: python + + attributes = TeamAttributes( + agents=[ + {"name": "MOVIE_ANALYST", "task": "ANALYZE_MOVIE_TASK"}, + {"name": "MOVIE_ANALYST", "task": "SUMMARIZE_MOVIE_TASK"}, + ], + process="sequential", + ) + .. autoclass:: select_ai.agent.TeamAttributes :members: @@ -261,6 +329,21 @@ The ``process`` attribute defines how tasks should be executed. Run Team ++++++++ +``Team.run(...)`` starts the team workflow. The ``prompt`` argument is passed to +the task and can be referenced by task instructions using ``{query}``. +``params`` can include ``conversation_id`` to associate multiple runs with the +same conversation and ``variables`` to pass additional key-value inputs. + +.. code-block:: python + + result = team.run( + prompt="Could you list the movies in the database?", + params={ + "conversation_id": conversation_id, + "variables": {"audience": "analyst"}, + }, + ) + .. literalinclude:: ../../../samples/agent/team_create.py :language: python :lines: 14- @@ -288,6 +371,81 @@ output:: .. latex:clearpage:: +Export and Import Team +++++++++++++++++++++++ + +Select AI agent teams can be exported into a portable specification and +imported into the same database, a different database, or another Select AI +service. The specification describes the team composition and the associated +agent, task, and tool definitions that are needed to recreate the team. + +``Team.export_team()`` returns the specification as a JSON string by default. +``Team.import_team()`` accepts either that JSON string or a Python mapping +containing the same team definition structure. In most cases, pass a ``dict``, +for example the result of ``json.loads(exported_spec)``. Other +JSON-serializable `collections.abc.Mapping `__ +objects, such as ``OrderedDict``, can also be used. On import, +``profile_name`` identifies the Select AI profile to use in the target +database. ``team_name`` can be provided to create the imported team under a new +name; this is useful when importing into the same database as the source team. + +If imported object names conflict with existing agents, tasks, tools, or teams, +set ``force=True`` to let the database replace the conflicting objects. Use this +carefully when importing into a shared schema because conflicting components can +be dropped and recreated. + +.. literalinclude:: ../../../samples/agent/team_export_import.py + :language: python + :lines: 14- + +output:: + + Exported specification: + { + "name": "EXPORT_IMPORT_MOVIE_ANALYST", + "component_type": "Agent", + "task": { + "task_name": "EXPORT_IMPORT_MOVIE_TASK", + "instruction": "Help the user with movie questions. Question: {query}", + "task_attributes": { + "enable_human_tool": "false", + "tools": [] + } + }, + "llm_config": { + "name": "LLAMA_4_MAVERICK", + "component_type": "oci" + } + } + Imported team: Team(team_name=IMPORTED_MOVIE_AGENT_TEAM, ...) + +The same APIs can also read from or write to object storage by passing both +``object_storage_credential_name`` and ``location``. When exporting to object +storage, ``Team.export_team()`` writes the specification to the location and +returns ``None``. When importing from object storage, pass the same credential +and location instead of ``specification``. + +Lifecycle helpers ++++++++++++++++++ + +All agent object types support list, fetch, enable, disable, and delete +operations. + +.. code-block:: python + + for tool in select_ai.agent.Tool.list(): + print(tool.tool_name) + + task = select_ai.agent.Task.fetch("ANALYZE_MOVIE_TASK") + agent = select_ai.agent.Agent.fetch("MOVIE_ANALYST") + team = select_ai.agent.Team.fetch("MOVIE_AGENT_TEAM") + + team.disable() + team.enable() + team.delete(force=True) + +.. latex:clearpage:: + ***************** AI agent examples ***************** @@ -341,14 +499,3 @@ output:: promoting advanced AI technologies, including products like ChatGPT, and provides information about their research, products, and mission to ensure that artificial general intelligence benefits all of humanity. - - -************** -Async AI Agent -************** - -.. toctree:: - :numbered: - :maxdepth: 3 - - async_agent.rst diff --git a/docs/_sources/user_guide/async_agent.rst.txt b/docs/_sources/user_guide/async_agent.rst.txt index 9d64737..df17e2d 100644 --- a/docs/_sources/user_guide/async_agent.rst.txt +++ b/docs/_sources/user_guide/async_agent.rst.txt @@ -1,8 +1,41 @@ .. _async_agent: ``select_ai.agent`` also provides async interfaces to be used with -``async`` / ``await`` keywords +``async`` / ``await`` keywords. Use these classes in applications that already +use ``asyncio`` and ``select_ai.async_connect()`` or +``select_ai.create_pool_async()``. +The async agent object model mirrors the synchronous agent object model: + +.. list-table:: Sync and async agent APIs + :header-rows: 1 + :widths: 50 50 + :align: left + + * - Sync class + - Async class + * - ``select_ai.agent.Tool`` + - ``select_ai.agent.AsyncTool`` + * - ``select_ai.agent.Task`` + - ``select_ai.agent.AsyncTask`` + * - ``select_ai.agent.Agent`` + - ``select_ai.agent.AsyncAgent`` + * - ``select_ai.agent.Team`` + - ``select_ai.agent.AsyncTeam`` + +Create or reuse the same database objects as the synchronous APIs. Async +methods must be awaited, and async list methods return async iterators. + +.. code-block:: python + + await select_ai.async_connect(user=user, password=password, dsn=dsn) + + async for tool in select_ai.agent.AsyncTool.list(): + print(tool.tool_name) + +Tools, tasks, agents, and teams are database objects. Use ``replace=True`` when +you want to recreate an existing object with the same name, and ``force=True`` +when cleanup should succeed even if the object does not exist. .. list-table:: Select AI Async Agent Tools :header-rows: 1 @@ -19,11 +52,6 @@ - ``recipient`` - ``sender`` - ``smtp_host`` - * - ``HTTP`` - - ``select_ai.agent.AsyncTool.create_http_tool`` - - - ``tool_name`` - - ``credential_name`` - - ``endpoint`` * - ``SQL`` - ``select_ai.agent.AsyncTool.create_sql_tool`` - - ``tool_name`` @@ -32,7 +60,7 @@ - ``select_ai.agent.AsyncTool.create_slack_notification_tool`` - - ``tool_name`` - ``credential_name`` - - ``slack_channel`` + - ``channel`` * - ``WEBSEARCH`` - ``select_ai.agent.AsyncTool.create_websearch_tool`` - - ``tool_name`` @@ -46,6 +74,14 @@ - - ``tool_name`` - ``profile_name`` +Notification and web search tools require credentials and network access for +the external service. SQL and RAG tools require existing Select AI profiles. + +Tool selection follows the same guidance as :ref:`Agent `: use SQL +tools for database questions, RAG tools for vector-index-backed content, +notification tools for Slack or email, web search tools for public web content, +and PL/SQL tools for application-specific database logic. + ************* ``AsyncTool`` ************* @@ -78,7 +114,7 @@ output:: profile_name='oci_ai_profile', recipient=None, sender=None, - slack_channel=None, + channel=None, smtp_host=None), tool_inputs=None, tool_type=) @@ -116,6 +152,10 @@ Create Task In the following task, we use the ``MOVIE_SQL_TOOL`` created in the previous step +The ``instruction`` is the main task prompt. Use placeholders such as +``{query}`` when the user prompt should be inserted into the task. The +``tools`` list limits which tools the agent can use for the task. + .. literalinclude:: ../../../samples/agent/async/task_create.py :language: python :lines: 13- @@ -199,6 +239,22 @@ AsyncTeam Run Team ++++++++ +``AsyncTeam.run(...)`` starts the team workflow. The ``prompt`` argument is +passed to the task and can be referenced by task instructions using +``{query}``. ``params`` can include ``conversation_id`` to associate multiple +runs with the same conversation and ``variables`` to pass additional key-value +inputs. + +.. code-block:: python + + result = await team.run( + prompt="Could you list the movies in the database?", + params={ + "conversation_id": conversation_id, + "variables": {"audience": "analyst"}, + }, + ) + .. literalinclude:: ../../../samples/agent/async/team_create.py :language: python :lines: 14- @@ -227,6 +283,84 @@ output:: .. latex:clearpage:: +Export and Import Team +++++++++++++++++++++++ + +Select AI agent teams can be exported into a portable specification and +imported into the same database, a different database, or another Select AI +service. The specification describes the team composition and the associated +agent, task, and tool definitions that are needed to recreate the team. + +``AsyncTeam.export_team()`` returns the specification as a JSON string by +default. ``AsyncTeam.import_team()`` accepts either that JSON string or a Python +mapping containing the same team definition structure. In most cases, pass a +``dict``, for example the result of ``json.loads(exported_spec)``. Other +JSON-serializable `collections.abc.Mapping `__ +objects, such as ``OrderedDict``, can also be used. On import, +``profile_name`` identifies the Select AI profile to use in the target +database. ``team_name`` can be provided to create the imported team under a new +name; this is useful when importing into the same database as the source team. + +If imported object names conflict with existing agents, tasks, tools, or teams, +set ``force=True`` to let the database replace the conflicting objects. Use this +carefully when importing into a shared schema because conflicting components can +be dropped and recreated. + +.. literalinclude:: ../../../samples/agent/async/team_export_import.py + :language: python + :lines: 14- + +output:: + + Exported specification: + { + "name": "EXPORT_IMPORT_MOVIE_ANALYST", + "component_type": "Agent", + "task": { + "task_name": "EXPORT_IMPORT_MOVIE_TASK", + "instruction": "Help the user with movie questions. Question: {query}", + "task_attributes": { + "enable_human_tool": "false", + "tools": [] + } + }, + "llm_config": { + "name": "LLAMA_4_MAVERICK", + "component_type": "oci" + } + } + Imported team: AsyncTeam(team_name=IMPORTED_MOVIE_AGENT_TEAM, ...) + +The same APIs can also read from or write to object storage by passing both +``object_storage_credential_name`` and ``location``. When exporting to object +storage, ``AsyncTeam.export_team()`` writes the specification to the location +and returns ``None``. When importing from object storage, pass the same +credential and location instead of ``specification``. + +.. latex:clearpage:: + +Lifecycle helpers ++++++++++++++++++ + +All async agent object types support list, fetch, enable, disable, and delete +operations. + +.. code-block:: python + + async for tool in select_ai.agent.AsyncTool.list(): + print(tool.tool_name) + + task = await select_ai.agent.AsyncTask.fetch("ANALYZE_MOVIE_TASK") + agent = await select_ai.agent.AsyncAgent.fetch("MOVIE_ANALYST") + team = await select_ai.agent.AsyncTeam.fetch("MOVIE_AGENT_TEAM") + + await team.disable() + await team.enable() + await team.delete(force=True) + +.. latex:clearpage:: + + List Teams ++++++++++ diff --git a/docs/_sources/user_guide/async_profile.rst.txt b/docs/_sources/user_guide/async_profile.rst.txt index 8280857..de1c9f8 100644 --- a/docs/_sources/user_guide/async_profile.rst.txt +++ b/docs/_sources/user_guide/async_profile.rst.txt @@ -1,10 +1,76 @@ .. _async_profile: -An AsyncProfile object can be created with ``select_ai.AsyncProfile()`` -``AsyncProfile`` support use of concurrent programming with `asyncio `__. +An ``AsyncProfile`` object can be created with ``select_ai.AsyncProfile()``. +``AsyncProfile`` supports concurrent programming with `asyncio `__. Unless explicitly noted as synchronous, the ``AsyncProfile`` methods should be used with ``await``. +Use ``AsyncProfile`` in applications that already use +``select_ai.async_connect()`` or ``select_ai.create_pool_async()``. The async +profile object uses the same database profile objects as ``Profile``; only the +Python API style changes. + +Because ``AsyncProfile`` initializes itself from the database, create or fetch +instances with ``await``: + +.. code-block:: python + + async_profile = await select_ai.AsyncProfile( + profile_name="async_oci_ai_profile", + ) + +Before creating an async profile, make sure the database user has the required +privileges, a credential for the AI provider, network access to the provider +endpoint, and access to the database objects included in the profile. See +:ref:`Privileges `, :ref:`Credential `, +:ref:`Provider `, and +:ref:`ProfileAttributes `. + +Async profile lifecycle +======================= + +The usual async profile lifecycle is: + +* Create or reuse an async database connection or async pool. +* Create a provider object. +* Create ``ProfileAttributes`` with the provider, credential name, and object + list. +* Create the profile with ``await select_ai.AsyncProfile(...)``. +* Reuse the profile later by name. +* Update profile attributes when provider settings or object scope changes. +* Delete profiles that are no longer needed. + +``replace=True`` recreates a profile when a profile with the same name already +exists. ``merge=True`` fetches the existing profile and updates it with the +non-null attributes passed by the caller. + +Async profile actions +===================== + +.. list-table:: Common async profile actions + :header-rows: 1 + :widths: 25 75 + :align: left + + * - Method + - Description + * - ``show_sql()`` + - Generates SQL for a natural language prompt without executing it. + * - ``run_sql()`` + - Generates SQL, executes it, and returns a ``pandas.DataFrame``. + * - ``narrate()`` + - Generates SQL, executes it, and returns a natural language answer. + * - ``explain_sql()`` + - Explains the generated SQL for a prompt. + * - ``show_prompt()`` + - Shows the prompt sent to the model. + * - ``chat()`` + - Sends a general chat prompt to the model. + * - ``summarize()`` + - Summarizes inline content or content referenced by a URI. + * - ``translate()`` + - Translates text from one language to another. + ******************** ``AsyncProfile`` API ******************** @@ -18,6 +84,9 @@ used with ``await``. Async Profile creation *********************** +The following example creates an OCI Gen AI profile that can generate SQL over +objects in the ``SH`` schema. + .. literalinclude:: ../../../samples/async/profile_create.py :language: python :lines: 14- @@ -55,6 +124,77 @@ output:: .. latex:clearpage:: +*********************** +Reuse Async Profile +*********************** + +After a profile has been created, instantiate ``AsyncProfile`` with only the +profile name to reuse the database profile: + +.. code-block:: python + + async_profile = await select_ai.AsyncProfile( + profile_name="async_oci_ai_profile", + ) + sql = await async_profile.show_sql(prompt="How many promotions?") + +Use ``AsyncProfile.fetch(...)`` when you want to create a proxy object from a +saved database profile and raise an error if the profile does not exist: + +.. code-block:: python + + async_profile = await select_ai.AsyncProfile.fetch( + "async_oci_ai_profile" + ) + +.. latex:clearpage:: + +*********************** +Update Async Profile +*********************** + +Use ``set_attribute(...)`` to update one profile attribute or +``set_attributes(...)`` to update several attributes. Updates are saved to the +database profile. + +.. code-block:: python + + async_profile = await select_ai.AsyncProfile( + profile_name="async_oci_ai_profile", + ) + await async_profile.set_attribute("temperature", 0.1) + + await async_profile.set_attributes( + select_ai.ProfileAttributes( + max_tokens=2048, + enforce_object_list=True, + ) + ) + +.. latex:clearpage:: + +*********************** +Delete Async Profile +*********************** + +Use ``delete(...)`` or ``AsyncProfile.delete_profile(...)`` to remove a profile +from the database. Pass ``force=True`` when cleanup should succeed even if the +profile does not exist. + +.. code-block:: python + + async_profile = await select_ai.AsyncProfile( + profile_name="async_oci_ai_profile", + ) + await async_profile.delete(force=True) + + await select_ai.AsyncProfile.delete_profile( + "async_oci_ai_profile", + force=True, + ) + +.. latex:clearpage:: + *********************** Async explain SQL *********************** @@ -115,6 +255,24 @@ output:: .. latex:clearpage:: +*********************** +Async show prompt +*********************** + +Use ``show_prompt(...)`` to inspect the prompt that Select AI sends to the +model. This is useful when tuning profile attributes, object lists, comments, +constraints, and provider settings. + +.. code-block:: python + + async_profile = await select_ai.AsyncProfile( + profile_name="async_oci_ai_profile", + ) + prompt = await async_profile.show_prompt(prompt="How many promotions?") + print(prompt) + +.. latex:clearpage:: + *********************** Async concurrent SQL *********************** @@ -177,6 +335,27 @@ output:: .. latex:clearpage:: +*********************** +Async streaming chat +*********************** + +.. literalinclude:: ../../../samples/async/profile_chat_stream.py + :language: python + :lines: 14- + +``stream=True`` lets callers consume generated CLOB responses chunk by chunk, +reducing memory pressure and making it easier to progressively forward output +to files, services, or user interfaces. Async streaming text APIs return an +async iterator of ``str`` chunks after the awaited method call. The +``chunk_size`` parameter controls the number of CLOB characters read per chunk; +it is not a byte count. + +Streaming is supported by ``generate()``, ``chat()``, ``narrate()``, +``explain_sql()``, ``show_sql()``, and ``show_prompt()``. It is not supported +for ``run_sql()``, which returns a ``pandas.DataFrame``. + +.. latex:clearpage:: + ************************** Summarize ************************** @@ -276,6 +455,9 @@ output:: List profiles asynchronously **************************** +Profile listing returns profiles visible to the connected database user. The +async list API returns an async iterator. + .. literalinclude:: ../../../samples/async/profiles_list.py :language: python :lines: 14- diff --git a/docs/_sources/user_guide/cli.rst.txt b/docs/_sources/user_guide/cli.rst.txt new file mode 100644 index 0000000..d8d084e --- /dev/null +++ b/docs/_sources/user_guide/cli.rst.txt @@ -0,0 +1,209 @@ +.. _cli: + +************************** +Command line interface +************************** + +The ``select-ai`` command line interface (CLI) provides a terminal workflow for +using Select AI profiles without writing Python code. It is intended for quick +exploration, profile validation, prompt testing, SQL generation, +summarization, translation, and interactive chat against an existing profile. + +The CLI is useful for developers who want a fast shell workflow and for +non-developers who are comfortable running terminal commands but do not want to +write Python code. It can help users check whether a profile is configured +correctly, inspect generated SQL, try prompts during development, or interact +with a curated profile through a simple command. + +The CLI works with Select AI profiles. RAG is supported when the selected +profile is already configured with a vector index. Additional CLI options and +workflows will be added in upcoming releases as the CLI evolves. + +.. only:: html + + .. image:: /image/select_ai_cli_demo.gif + :alt: Select AI CLI demo + :width: 100% + +.. only:: latex + + .. image:: /image/select_ai_cli_demo.png + :alt: Select AI CLI demo + :width: 100% + +The package provides an optional ``select-ai`` command line tool. Install the +CLI extra to use it: + +.. code-block:: bash + + pip install 'select_ai[cli]' + +Use ``select-ai --help`` to view the available command groups and +``select-ai --help`` to view options for a specific command. + +Set the database connection details as environment variables, or pass them as +command line options: + +.. code-block:: bash + + export SELECT_AI_USER= + export SELECT_AI_PASSWORD= + export SELECT_AI_DB_CONNECT_STRING= + +Connection options +================== + +All CLI commands accept the same database connection options: + +.. list-table:: Connection options + :header-rows: 1 + :widths: 30 70 + :align: left + + * - Option + - Environment variable + * - ``--user`` + - ``SELECT_AI_USER`` + * - ``--password`` + - ``SELECT_AI_PASSWORD`` + * - ``--dsn`` + - ``SELECT_AI_DB_CONNECT_STRING`` + * - ``--wallet-location`` + - ``SELECT_AI_WALLET_LOCATION`` + * - ``--wallet-password`` + - ``SELECT_AI_WALLET_PASSWORD`` + +If ``--password`` and ``SELECT_AI_PASSWORD`` are not set, the CLI prompts for +the database password. Wallet options are optional and are only needed for +wallet-based database connections. + +Interactive chat +================ + +The ``chat`` subcommand starts an interactive profile chat +Read-Eval-Print Loop (REPL). A REPL is a terminal session that reads each +prompt you type, evaluates it, prints the response, and then waits for the next +prompt. Pass an existing Select AI profile with ``--profile``: + +.. code-block:: bash + + select-ai chat --profile OCI_AI_PROFILE + +The REPL uses ``Profile.chat_session()`` so prompts in the same terminal session +share conversation context. Responses stream by default. Use ``--no-stream`` to +print each response after it is fully generated. + +.. code-block:: text + + Connected to Select AI profile: OCI_AI_PROFILE + Type /help for commands. Type /exit to quit. + select_ai> What tables can I ask about? + ... + select_ai> /exit + +Useful options: + +- ``--user``, ``--password``, and ``--dsn`` override the environment values. +- ``--wallet-location`` and ``--wallet-password`` configure wallet connections. +- ``--chunk-size`` controls the number of CLOB characters read per stream chunk. +- ``--conversation-length`` controls how many prompts are retained in context. +- ``--keep-conversation`` keeps the database conversation after the REPL exits. + +Inside the REPL, use these commands: + +.. list-table:: Chat REPL commands + :header-rows: 1 + :widths: 25 75 + :align: left + + * - Command + - Description + * - ``/help`` + - Show available REPL commands. + * - ``/clear`` + - Start a fresh database conversation. + * - ``/exit`` + - Exit the chat session. + * - ``/quit`` + - Exit the chat session. + +SQL commands +============ + +SQL operations are one-shot subcommands instead of a REPL: + +.. code-block:: bash + + select-ai sql show --profile OCI_AI_PROFILE "count movies by genre" + select-ai sql run --profile OCI_AI_PROFILE "count movies by genre" + select-ai sql explain --profile OCI_AI_PROFILE "count movies by genre" + select-ai sql narrate --profile OCI_AI_PROFILE "count movies by genre" + +``show``, ``explain``, and ``narrate`` stream text output by default. Use +``--no-stream`` to print the response after it is fully generated, and +``--chunk-size`` to control the number of CLOB characters read per stream +chunk. + +``run`` executes the generated SQL and prints the returned result table. It +does not support streaming. + +Profile commands +================ + +Summarize and translate are available under the ``profile`` command group: + +.. code-block:: bash + + select-ai profile list + select-ai profile list --pattern "OCI.*" + + select-ai profile summarize --profile OCI_AI_PROFILE "Text to summarize" + select-ai profile summarize --profile OCI_AI_PROFILE --file notes.txt + select-ai profile summarize \ + --profile OCI_AI_PROFILE \ + --location-uri https://example.com/article.txt + select-ai profile summarize \ + --profile OCI_AI_PROFILE \ + --location-uri https://objectstorage.example.com/n/namespace/b/bucket/o/file.txt \ + --credential-name OBJECT_STORE_CRED + + select-ai profile translate \ + --profile OCI_AI_PROFILE \ + --source-language English \ + --target-language German \ + "Thank you" + +``profile list`` prints profile names visible to the connected database user. +Use ``--pattern`` to filter names with a regular expression. + +``profile summarize`` accepts one content source at a time: inline text, +``--file``, or ``--location-uri``. Use ``--prompt`` to guide the summary and +``--credential-name`` when the location URI requires an object storage +credential. + +Command summary +=============== + +.. list-table:: CLI command summary + :header-rows: 1 + :widths: 35 65 + :align: left + + * - Command + - Purpose + * - ``select-ai chat`` + - Start an interactive context-aware chat session. + * - ``select-ai sql show`` + - Generate SQL without executing it. + * - ``select-ai sql run`` + - Generate SQL, execute it, and print the result table. + * - ``select-ai sql explain`` + - Explain generated SQL. + * - ``select-ai sql narrate`` + - Generate and execute SQL, then return a natural language answer. + * - ``select-ai profile list`` + - List saved profile names. + * - ``select-ai profile summarize`` + - Summarize inline content, a file, or a URI. + * - ``select-ai profile translate`` + - Translate text with a saved profile. diff --git a/docs/_sources/user_guide/concurrent_prompt_processing.rst.txt b/docs/_sources/user_guide/concurrent_prompt_processing.rst.txt new file mode 100644 index 0000000..1f2e165 --- /dev/null +++ b/docs/_sources/user_guide/concurrent_prompt_processing.rst.txt @@ -0,0 +1,179 @@ +.. _concurrent_prompt_processing: + +**************************** +Concurrent prompt processing +**************************** + +Use concurrent prompt processing when an application needs to send multiple +independent prompts without waiting for each prompt to finish before starting +the next one. The ``select_ai`` module supports this pattern with both the +synchronous ``Profile`` API and the asynchronous ``AsyncProfile`` API. + +Create a connection pool before running concurrent work. Use +``select_ai.create_pool()`` for synchronous recipes and +``select_ai.create_pool_async()`` for asynchronous recipes. + +Recipe summary +============== + +.. list-table:: + :header-rows: 1 + :widths: 18 26 56 + + * - Recipe + - Script + - When to use + * - Sync completion + - :ref:`sync_thread_pool_recipe` + - Use ``ThreadPoolExecutor`` when prompts are independent and results can + be handled as soon as each prompt completes. + * - Sync input order + - :ref:`sync_ordered_results_recipe` + - Use ``ThreadPoolExecutor.map()`` when result order must match the input + prompt order. + * - Sync queue + - :ref:`sync_queue_workers_recipe` + - Use worker threads and a queue for producer-consumer workloads where + prompts may arrive over time. + * - Async input order + - :ref:`async_gather_recipe` + - Use ``asyncio.gather()`` when result order must match the input prompt + order. + * - Async completion + - :ref:`async_as_completed_recipe` + - Use ``asyncio.as_completed()`` when each result should be processed as + soon as it is available. + * - Async pipeline + - :ref:`async_pipeline_recipe` + - Use ``run_pipeline()`` when all prompt/action pairs are known up front + and should be sent in a single database round trip. + * - Async queue + - :ref:`async_queue_workers_recipe` + - Use async queue workers for long-running async services or background + prompt processors. + +Environment variables +===================== + +The recipes use the same connection environment variables as the other samples: + +.. code-block:: sh + + export SELECT_AI_USER= + export SELECT_AI_PASSWORD= + export SELECT_AI_DB_CONNECT_STRING= + +Optional environment variables control pool sizing and profile names: + +.. code-block:: sh + + export SELECT_AI_POOL_MIN=1 + export SELECT_AI_POOL_MAX=4 + export SELECT_AI_POOL_INCREMENT=1 + export SELECT_AI_PROFILE_NAME=oci_ai_profile + +Use ``SELECT_AI_PROFILE_NAME=async_oci_ai_profile`` for the async recipes if +that is the async profile name in your environment. + +.. _sync_thread_pool_recipe: + +``sync_thread_pool.py`` +======================= + +This recipe uses ``ThreadPoolExecutor`` and ``as_completed()``. Results are +printed in the order they finish. + +.. literalinclude:: ../../../recipes/concurrent_prompt_processing/sync_thread_pool.py + :language: python + :lines: 14- + +.. _sync_ordered_results_recipe: + +``sync_ordered_results.py`` +=========================== + +This recipe uses ``ThreadPoolExecutor.map()``. Prompts run concurrently, but +results are printed in the same order as the input list. + +.. literalinclude:: ../../../recipes/concurrent_prompt_processing/sync_ordered_results.py + :language: python + :lines: 14- + +.. _sync_queue_workers_recipe: + +``sync_queue_workers.py`` +========================= + +This recipe uses worker threads and ``queue.Queue``. It is useful when prompt +producers and prompt processors are separate parts of an application. + +.. literalinclude:: ../../../recipes/concurrent_prompt_processing/sync_queue_workers.py + :language: python + :lines: 14- + +.. _async_gather_recipe: + +``async_gather.py`` +=================== + +This recipe uses ``asyncio.gather()``. Prompts run concurrently, and results +are returned in the same order as the input task list. + +.. literalinclude:: ../../../recipes/concurrent_prompt_processing/async_gather.py + :language: python + :lines: 14- + +.. _async_as_completed_recipe: + +``async_as_completed.py`` +========================= + +This recipe uses ``asyncio.as_completed()``. It is useful for command-line +tools or services that can forward each answer as soon as it is ready. + +.. literalinclude:: ../../../recipes/concurrent_prompt_processing/async_as_completed.py + :language: python + :lines: 14- + +.. _async_pipeline_recipe: + +``async_pipeline.py`` +===================== + +This recipe uses ``AsyncProfile.run_pipeline()`` to send multiple +prompt/action pairs in one database round trip. This is different from Python +task concurrency: the application submits a batch and receives the batch +results when the pipeline completes. + +.. literalinclude:: ../../../recipes/concurrent_prompt_processing/async_pipeline.py + :language: python + :lines: 14- + +.. _async_queue_workers_recipe: + +``async_queue_workers.py`` +========================== + +This recipe uses ``asyncio.Queue`` and async worker tasks. It is useful for +long-running async applications that receive prompts over time. + +.. literalinclude:: ../../../recipes/concurrent_prompt_processing/async_queue_workers.py + :language: python + :lines: 14- + +Pool sizing +=========== + +Pool size controls how many database connections the application can use at +one time. For thread and worker recipes, keep the worker count close to the +pool maximum unless the application intentionally needs additional queued work. + +In multi-process deployments, each process creates its own pool. Total possible +database connections are approximately: + +.. code-block:: text + + processes * SELECT_AI_POOL_MAX + +Choose pool sizes that leave capacity for other database clients and for the +AI provider calls made by ``DBMS_CLOUD_AI``. diff --git a/docs/_sources/user_guide/connection.rst.txt b/docs/_sources/user_guide/connection.rst.txt index 9419c9d..66267dd 100644 --- a/docs/_sources/user_guide/connection.rst.txt +++ b/docs/_sources/user_guide/connection.rst.txt @@ -7,13 +7,40 @@ Connecting to Oracle Database ``select_ai`` uses the Python thin driver i.e. ``python-oracledb`` to connect to the database and execute PL/SQL subprograms. +The library keeps the active connection or connection pool for the current +process so profile, credential, provider, vector index, and agent APIs can use +it without passing a connection object to each call. Use a standalone +connection for scripts and notebooks. Use a connection pool for applications +that handle concurrent work, such as web services or worker processes. + +Most samples read connection values from environment variables: + +.. code-block:: sh + + export SELECT_AI_USER= + export SELECT_AI_PASSWORD= + export SELECT_AI_DB_CONNECT_STRING= + +Then the Python code can load those values: + +.. code-block:: python + + import os + import select_ai + + user = os.getenv("SELECT_AI_USER") + password = os.getenv("SELECT_AI_PASSWORD") + dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING") + + select_ai.connect(user=user, password=password, dsn=dsn) + .. _sync_conn: Synchronous connection ====================== To connect to an Oracle Database synchronously, use -``select_ai.connect()`` method as shown below +``select_ai.connect()`` as shown below: .. code-block:: python @@ -24,6 +51,12 @@ To connect to an Oracle Database synchronously, use dsn = "" select_ai.connect(user=user, password=password, dsn=dsn) +Close a standalone synchronous connection with ``select_ai.disconnect()``: + +.. code-block:: python + + select_ai.disconnect() + .. _async_conn: Asynchronous connection @@ -41,12 +74,21 @@ with ``await`` keyword: dsn = "" await select_ai.async_connect(user=user, password=password, dsn=dsn) +Close a standalone asynchronous connection with +``await select_ai.async_disconnect()``: + +.. code-block:: python + + await select_ai.async_disconnect() + Connection Pool =============== You can create a connection pool using the ``select_ai.create_pool`` -and ``select_ai.create_pool_async`` methods +and ``select_ai.create_pool_async`` methods. After a pool is created, these +methods configure Select AI operations to acquire and release connections from +the pool for each operation. .. code-block:: python @@ -65,6 +107,7 @@ and ``select_ai.create_pool_async`` methods max_size=10, increment=5 ) + # for async pool select_ai.create_pool_async( user=user, @@ -75,11 +118,68 @@ and ``select_ai.create_pool_async`` methods increment=5 ) -Check this `blog `__ which shows the benefit of connection pooling along with FastAPI service +Close a synchronous pool with ``select_ai.disconnect()`` and an asynchronous +pool with ``await select_ai.async_disconnect()``. + +Create one pool per process. In multi-process deployments, each process creates +its own pool, so total database connections can grow quickly. Size pools based +on request concurrency and database capacity. + +Use pooling for: + +* Web applications and API services. +* Worker processes that handle multiple prompts. +* Concurrent prompt processing. +* Long-running applications that should avoid opening a new database connection + for every request. + +Use a standalone connection for: + +* Short scripts. +* Local examples. +* One-off administration tasks. + +Check this `blog `__ +which shows the benefit of connection pooling with a FastAPI service. + +Connection health +================= + +Use ``select_ai.is_connected()`` or ``await select_ai.async_is_connected()`` +to check whether the current connection or pool is available: + +.. code-block:: python + + if not select_ai.is_connected(): + select_ai.connect(user=user, password=password, dsn=dsn) + +.. code-block:: python + + if not await select_ai.async_is_connected(): + await select_ai.async_connect(user=user, password=password, dsn=dsn) + +Wallet connections +================== .. note:: - For m-TLS (wallet) based connection, additional parameters like - ``wallet_location``, ``wallet_password``, ``https_proxy``, - ``https_proxy_port`` can be passed to the ``connect`` and ``async_connect`` - methods + For m-TLS (wallet) based connections, additional parameters like + ``wallet_location``, ``wallet_password``, ``config_dir``, ``https_proxy``, + and ``https_proxy_port`` can be passed to ``connect``, ``async_connect``, + ``create_pool``, and ``create_pool_async``. + +For example: + +.. code-block:: python + + select_ai.connect( + user=user, + password=password, + dsn=dsn, + wallet_location="/path/to/wallet", + config_dir="/path/to/wallet", + wallet_password="", + ) + +The same keyword arguments can be used with ``async_connect`` and the pool +creation APIs. diff --git a/docs/_sources/user_guide/conversation.rst.txt b/docs/_sources/user_guide/conversation.rst.txt index 6e6d7dc..a9db8f7 100644 --- a/docs/_sources/user_guide/conversation.rst.txt +++ b/docs/_sources/user_guide/conversation.rst.txt @@ -4,6 +4,26 @@ Conversations in Select AI represent an interactive exchange between the user and the system, enabling users to query or interact with the database through a series of natural language prompts. +A conversation is stored in the database and identified by a +``conversation_id``. Pass that conversation to ``Profile.chat_session()`` or +``AsyncProfile.chat_session()`` when follow-up prompts should use prior prompts +as context. This is useful for chat workflows where the user asks a question, +then asks follow-up questions such as "explain that further" or "show another +example". + +Use conversations when you need context across multiple prompts. For one-off +prompts, call profile methods such as ``chat()``, ``show_sql()``, or +``narrate()`` directly without creating a conversation. + +The usual lifecycle is: + +1. Create ``ConversationAttributes`` with a title, optional description, + retention period, and conversation length. +2. Create a ``Conversation`` or ``AsyncConversation`` object. +3. Use the conversation in ``profile.chat_session(...)``. +4. List, fetch, or update the conversation metadata when needed. +5. Delete the conversation when the stored history is no longer needed. + ***************************** ``Conversation Object model`` ***************************** @@ -17,6 +37,41 @@ a series of natural language prompts. ``ConversationAttributes`` ************************** +``ConversationAttributes`` controls the metadata and retention behavior for a +conversation: + +.. list-table:: + :header-rows: 1 + + * - Attribute + - Use + * - ``title`` + - Human-readable conversation title. If omitted, the default is + ``"New Conversation"``. + * - ``description`` + - Optional description of the conversation topic. + * - ``retention_days`` + - Number of days to keep the conversation in the database from its + creation date. Use ``datetime.timedelta(days=...)``. A value of + ``datetime.timedelta(days=0)`` keeps the conversation until it is + manually deleted. + * - ``conversation_length`` + - Number of prompts retained in the conversation context. The default is + ``10``. + +Example: + +.. code-block:: python + + import datetime + + attributes = select_ai.ConversationAttributes( + title="Sales analysis", + description="Follow-up questions about quarterly sales", + retention_days=datetime.timedelta(days=14), + conversation_length=20, + ) + .. autoclass:: select_ai.ConversationAttributes :members: @@ -29,10 +84,40 @@ a series of natural language prompts. .. autoclass:: select_ai.Conversation :members: +The synchronous API is used with ``select_ai.connect()`` or +``select_ai.create_pool()``. Important methods: + +.. list-table:: + :header-rows: 1 + + * - Method + - Use + * - ``create()`` + - Create a database conversation and return its ``conversation_id``. + * - ``fetch(conversation_id)`` + - Build a ``Conversation`` object from an existing database conversation. + * - ``get_attributes()`` + - Read conversation metadata from the database. + * - ``set_attributes(attributes)`` + - Update the title, description, retention period, or conversation + length. + * - ``list()`` + - Iterate over conversations visible to the current user. + * - ``delete(force=False)`` + - Drop the conversation. Use ``force=True`` to ignore missing-conversation + errors. + +``Profile.chat_session(conversation=..., delete=False)`` is a context manager. +If the conversation has attributes but no ``conversation_id``, the session +creates it automatically. While the context manager is active, every +``session.chat(...)`` call passes the same ``conversation_id`` to Select AI, so +follow-up prompts can use the conversation history. If ``delete=True``, the +conversation is deleted when the session exits. + .. latex:clearpage:: -Create conversion -++++++++++++++++++ +Create conversation ++++++++++++++++++++ .. literalinclude:: ../../../samples/conversation_create.py :language: python @@ -47,6 +132,10 @@ output:: Chat session +++++++++++++ +Use ``chat_session()`` to keep context across multiple chat prompts. The second +prompt in this example can refer to the previous answer because both prompts use +the same database conversation. + .. literalinclude:: ../../../samples/conversation_chat_session.py :language: python :lines: 14- @@ -71,6 +160,9 @@ output:: List conversations ++++++++++++++++++ +Listing returns ``Conversation`` objects with their ``conversation_id`` and +metadata. It does not replay the conversation transcript. + .. literalinclude:: ../../../samples/conversations_list.py :language: python :lines: 14- @@ -88,6 +180,11 @@ output:: Delete conversation +++++++++++++++++++ +Delete conversations that are no longer needed, especially when +``retention_days`` is set to ``0`` or when the content should not remain in the +database after a session ends. For temporary sessions, prefer +``profile.chat_session(conversation=conversation, delete=True)``. + .. literalinclude:: ../../../samples/conversation_delete.py :language: python :lines: 14- @@ -106,11 +203,37 @@ output:: .. autoclass:: select_ai.AsyncConversation :members: +The async API mirrors the synchronous API and is used with +``select_ai.async_connect()`` or ``select_ai.create_pool_async()``. + +.. list-table:: + :header-rows: 1 + + * - Synchronous API + - Async API + * - ``Conversation.create()`` + - ``await AsyncConversation.create()`` + * - ``Conversation.fetch(...)`` + - ``await AsyncConversation.fetch(...)`` + * - ``Conversation.get_attributes()`` + - ``await AsyncConversation.get_attributes()`` + * - ``Conversation.set_attributes(...)`` + - ``await AsyncConversation.set_attributes(...)`` + * - ``for conversation in Conversation.list()`` + - ``async for conversation in AsyncConversation.list()`` + * - ``Conversation.delete(...)`` + - ``await AsyncConversation.delete(...)`` + * - ``with profile.chat_session(...)`` + - ``async with async_profile.chat_session(...)`` + .. latex:clearpage:: Async chat session ++++++++++++++++++ +Use ``AsyncProfile.chat_session()`` in async applications. The conversation is +created automatically when the object has attributes and no ``conversation_id``. + .. literalinclude:: ../../../samples/async/conversation_chat_session.py :language: python :lines: 13- @@ -135,6 +258,8 @@ output:: Async list conversations ++++++++++++++++++++++++ +``AsyncConversation.list()`` is an async iterator. + .. literalinclude:: ../../../samples/async/conversations_list.py :language: python :lines: 14- diff --git a/docs/_sources/user_guide/credential.rst.txt b/docs/_sources/user_guide/credential.rst.txt index 8bc8f47..19ad639 100644 --- a/docs/_sources/user_guide/credential.rst.txt +++ b/docs/_sources/user_guide/credential.rst.txt @@ -1,34 +1,99 @@ .. _credential: -Credential object securely stores API key from your AI provider for use by Oracle Database. -The following table shows AI Provider and corresponding credential object format - -.. list-table:: AI Provider and expected credential format +A credential object securely stores authentication details from your AI +provider for use by Oracle Database. Select AI profiles, vector indexes, and +agent tools refer to the credential later by ``credential_name``; the secret +values are stored in Oracle Database and are not passed again when the profile +or tool runs. + +A credential is created in the connected user's schema by +``DBMS_CLOUD.CREATE_CREDENTIAL``. Create credentials while connected as the +database user that will own and use them. Before creating credentials, make +sure the user has the required Select AI package privileges. If the credential +will be used to call an external AI provider, the database user also needs +network access to that provider endpoint. + +Every credential object must include ``credential_name`` and the fields +required by the target provider. The library accepts the following credential +keys: ``credential_name``, ``username``, ``password``, ``user_ocid``, +``tenancy_ocid``, ``private_key``, ``fingerprint``, and ``comments``. + +The following table shows AI providers and corresponding credential object +formats. + +.. list-table:: AI provider and expected credential format :header-rows: 1 :widths: 30 70 :align: left - * - AI Provider + * - AI provider - Credential format * - Anthropic - .. code-block:: python - {"username": "anthropic", "password": "sk-xxx"} - * - HuggingFace - - .. code-block:: python + { + "credential_name": "ANTHROPIC_CRED", + "username": "anthropic", + "password": "sk-ant-xxx", + } + * - AWS Bedrock + - .. code-block:: python - {"username": "hf", "password": "hf_xxx"} - * - OCI Gen AI + { + "credential_name": "AWS_BEDROCK_CRED", + "username": "", + "password": "", + } + * - Azure OpenAI - .. code-block:: python - {"user_ocid": "", "tenancy_ocid": "", "private_key": "", "fingerprint": ""} - * - OpenAI + { + "credential_name": "AZURE_OPENAI_CRED", + "username": "azure", + "password": "", + } + * - Cohere - .. code-block:: python - {"username": "openai", "password": "sk-xxx"} + { + "credential_name": "COHERE_CRED", + "username": "cohere", + "password": "", + } + * - Google + - .. code-block:: python + { + "credential_name": "GOOGLE_CRED", + "username": "google", + "password": "", + } + * - HuggingFace + - .. code-block:: python + + { + "credential_name": "HUGGINGFACE_CRED", + "username": "hf", + "password": "hf_xxx", + } + * - OCI Gen AI + - .. code-block:: python + { + "credential_name": "OCI_GENAI_CRED", + "user_ocid": "", + "tenancy_ocid": "", + "private_key": "", + "fingerprint": "", + } + * - OpenAI + - .. code-block:: python + { + "credential_name": "OPENAI_CRED", + "username": "openai", + "password": "sk-xxx", + } .. latex:clearpage:: @@ -39,6 +104,10 @@ Create credential In this example, we create a credential object to authenticate to OCI Gen AI service provider: +Pass ``replace=True`` when you want to recreate an existing credential with the +same name. Without ``replace=True``, creating a credential that already exists +raises a database error. + Sync API ++++++++ @@ -62,3 +131,37 @@ Async API output:: Created credential: my_oci_ai_profile_key + +.. latex:clearpage:: + +************************** +Delete credential +************************** + +Use ``select_ai.delete_credential(...)`` to drop a credential that is no longer +needed. Pass ``force=True`` when cleanup should succeed even if the credential +does not exist. + +Sync API +++++++++ + +.. literalinclude:: ../../../samples/delete_ai_credential.py + :language: python + :lines: 14- + +output:: + + Deleted credential: my_oci_ai_profile_key + +.. latex:clearpage:: + +Async API ++++++++++ + +.. literalinclude:: ../../../samples/async/delete_ai_credential.py + :language: python + :lines: 14- + +output:: + + Deleted credential: my_oci_ai_profile_key diff --git a/docs/_sources/user_guide/installation.rst.txt b/docs/_sources/user_guide/installation.rst.txt index 13adc69..078f39d 100644 --- a/docs/_sources/user_guide/installation.rst.txt +++ b/docs/_sources/user_guide/installation.rst.txt @@ -11,16 +11,21 @@ Installation requirements To use ``select_ai`` you need: -- Python 3.9, 3.10, 3.11, 3.12, 3.13 or 3.14 +- Python 3.11, 3.12, 3.13, or 3.14. -.. warning:: +- Access to an Oracle Database environment where Select AI is available. - For async APIs, use Python 3.11 or higher. Python 3.11 stabilized the async - event loop management and introduced better-structured APIs +- A database user with the required Select AI package privileges. See + :ref:`Privileges `. -- ``python-oracledb`` - This package is automatically installed as a dependency requirement +- Network access from the database to any AI provider endpoints you plan to + use. -- ``pandas`` - This package is automatically installed as a dependency requirement +- ``python-oracledb`` and ``pandas``. These packages are installed + automatically as dependencies. + +Using a virtual environment is recommended so the package and its dependencies +are isolated from your system Python installation. .. _quickstart: @@ -28,48 +33,106 @@ To use ``select_ai`` you need: ``select_ai`` installation ============================ -``select_ai`` can be installed from Python's package repository +``select_ai`` can be installed from the Python Package Index `PyPI `__ using `pip `__. 1. Install `Python 3 `__ if it is not already - available. Use any version from Python 3.9 through 3.14. + available. Use any version from Python 3.11 through 3.14. + +2. Create and activate a virtual environment: + + .. code-block:: shell + + python3 -m venv .venv + source .venv/bin/activate + + On Windows PowerShell: + + .. code-block:: powershell + + py -3 -m venv .venv + .venv\Scripts\Activate.ps1 + +3. Upgrade ``pip``: + + .. code-block:: shell + + python -m pip install --upgrade pip + +4. Install ``select_ai``: + + .. code-block:: shell + + python -m pip install --upgrade select_ai + +5. If you want the optional command line interface, install the ``cli`` extra: + + .. code-block:: shell + + python -m pip install --upgrade "select_ai[cli]" + + This installs the ``select-ai`` command. See :ref:`Command Line Interface + `. + +6. If you are behind a proxy, use the ``--proxy`` option. For example: + + .. code-block:: shell + + python -m pip install --upgrade select_ai --proxy=http://proxy.example.com:80 + + +Connection smoke test +===================== + +After installation, verify that Python can import ``select_ai`` and connect to +Oracle Database. + +1. Set database connection environment variables: + + .. code-block:: shell + + export SELECT_AI_USER= + export SELECT_AI_PASSWORD= + export SELECT_AI_DB_CONNECT_STRING= -2. Install ``select_ai``: +2. Create a file ``select_ai_connection_test.py``: - .. code-block:: shell + .. code-block:: python - python3 -m pip install select_ai --upgrade --user + import os -3. If you are behind a proxy, use the ``--proxy`` option. For example: + import select_ai - .. code-block:: shell + user = os.getenv("SELECT_AI_USER") + password = os.getenv("SELECT_AI_PASSWORD") + dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING") - python3 -m pip install select_ai --upgrade --user --proxy=http://proxy.example.com:80 + select_ai.connect(user=user, password=password, dsn=dsn) + print("Connected to the Database") +3. Run the script: -4. Create a file ``select_ai_connection_test.py`` such as: + .. code-block:: shell - .. code-block:: python + python select_ai_connection_test.py - import select_ai + If the connection succeeds, the script prints: - user = "" - password = "" - dsn = "" - select_ai.connect(user=user, password=password, dsn=dsn) - print("Connected to the Database") + .. code-block:: shell -5. Run ``select_ai_connection_test.py`` + Connected to the Database - .. code-block:: shell +Install documentation dependencies +================================== - python3 select_ai_connection_test.py +If you are building this documentation locally from the repository, install the +documentation dependencies: - Enter the database password when prompted and message will be shown: +.. code-block:: shell - .. code-block:: shell + python -m pip install -r doc/requirements.txt - Connected to the Database +Then build the docs with the project's Sphinx command or Makefile target. .. latex:clearpage:: diff --git a/docs/_sources/user_guide/introduction.rst.txt b/docs/_sources/user_guide/introduction.rst.txt index dd5ad91..ab0774d 100644 --- a/docs/_sources/user_guide/introduction.rst.txt +++ b/docs/_sources/user_guide/introduction.rst.txt @@ -9,10 +9,91 @@ using Python. It supports text-to-SQL generation, retrieval augmented generation (RAG), synthetic data generation, and several other features using Oracle-based and third-party AI providers. -``select_ai`` supports both synchronous and concurrent(asynchronous) -programming styles. +Select AI for Python bridges Oracle Database's Select AI capabilities and the +Python ecosystem. It gives Python applications a higher-level API for working +with AI providers, credentials, profiles, natural language prompts, vector +indexes, conversations, summarization, synthetic data, and AI agent workflows. -The Select AI Python API supports Python versions 3.9, 3.10, 3.11, 3.12 and -3.13. +What you can build +================== + +Use ``select_ai`` to: + +* Ask questions about database objects in natural language and generate SQL. +* Run generated SQL and return results as Python objects such as pandas data + frames. +* Generate narrative answers, explanations, prompt previews, translations, and + summaries. +* Use Retrieval Augmented Generation (RAG) with vector indexes over documents + and object storage content. +* Create synthetic data for database tables. +* Build context-aware chat sessions with database-backed conversations. +* Register tools, tasks, agents, and teams for database-backed AI agent + workflows. +* Use the optional ``select-ai`` command line interface for interactive chat + and SQL workflows. +* Use synchronous APIs, asynchronous APIs, and connection pools in scripts, + services, and web applications. + +Core concepts +============= + +Most workflows use the same building blocks: + +.. list-table:: + :header-rows: 1 + + * - Concept + - Purpose + - Start here + * - Connection + - Connect to Oracle Database using a standalone connection or a pool. + - :ref:`Connection ` + * - Privileges + - Grant package privileges and network ACLs required for Select AI calls. + - :ref:`Privileges ` + * - Provider + - Describe the AI service, model, endpoint, region, or provider-specific + options. + - :ref:`Provider ` + * - Credential + - Store provider and service secrets securely in Oracle Database. + - :ref:`Credential ` + * - Profile + - Combine provider, credential, database object scope, and generation + options into a reusable Select AI profile. + - :ref:`Profile ` + * - Actions + - Choose what Select AI should do with a prompt, such as show SQL, run + SQL, chat, narrate, summarize, or translate. + - :ref:`Actions ` + * - Conversation + - Keep prompt history for context-aware chat sessions. + - :ref:`Conversation ` + * - Vector index + - Index document content for RAG over trusted source material. + - :ref:`Vector Index ` + * - Agent + - Define tools, tasks, agents, and teams for multi-step AI workflows. + - :ref:`Agent ` + +Synchronous and asynchronous APIs +================================= + +``select_ai`` supports both synchronous and asynchronous programming styles. +Use the synchronous APIs for scripts, notebooks, command-line tools, and simple +services. Use the asynchronous APIs with ``asyncio`` applications, async web +frameworks, and workloads that need to run many prompts concurrently. + +For long-running services, create a connection pool once during application +startup and close it during shutdown. See :ref:`Connection `, +:ref:`Web Frameworks `, and +:ref:`Concurrent Prompt Processing ` for +patterns. + +Supported Python versions +========================= + +The Select AI Python API supports Python versions 3.11, 3.12, 3.13, and 3.14. .. latex:clearpage:: diff --git a/docs/_sources/user_guide/privileges.rst.txt b/docs/_sources/user_guide/privileges.rst.txt index b61d135..920ddbe 100644 --- a/docs/_sources/user_guide/privileges.rst.txt +++ b/docs/_sources/user_guide/privileges.rst.txt @@ -1,14 +1,29 @@ .. _privileges: -Admin user should grant execute privilege to select ai database users -on the packages ``DBMS_CLOUD``, ``DBMS_CLOUD_AI``, ``DBMS_CLOUD_AI_AGENT`` -and ``DBMS_CLOUD_PIPELINE`` +An admin user should grant execute privilege to Select AI database users +on the packages ``DBMS_CLOUD``, ``DBMS_CLOUD_AI``, ``DBMS_CLOUD_AI_AGENT``, +and ``DBMS_CLOUD_PIPELINE``. + +The privilege helper APIs are intended for database administrators who need to +prepare one or more database schemas for Select AI workloads. These operations +should be run from a connection that has permission to grant package execute +privileges and manage database network ACLs. + +There are two separate setup steps: + +* Package privileges allow a Select AI database user to call the Oracle Database + PL/SQL packages used by this library. +* Network access allows the database user to make outbound calls to specific + hosts, such as AI provider endpoints or SMTP servers. + +The ``users`` argument accepts either a single database user name or a list of +database user names. .. note:: All sample scripts in this documentation read Oracle database connection details from the environment. Create a dotenv file ``.env``, export the - the following environment variables and source it before running the + following environment variables and source it before running the scripts. .. code-block:: sh @@ -24,9 +39,11 @@ and ``DBMS_CLOUD_PIPELINE`` Grant privilege *************** -Connect as admin and run the method -``select_ai.grant_privileges(users=select_ai_user)`` to grant relevant select ai -privileges to other users +Connect as an admin user and run +``select_ai.grant_privileges(users=select_ai_user)`` to grant the package +execute privileges required by Select AI. This grants execute access on +``DBMS_CLOUD``, ``DBMS_CLOUD_AI``, ``DBMS_CLOUD_AI_AGENT``, and +``DBMS_CLOUD_PIPELINE``. .. literalinclude:: ../../../samples/select_ai_grant_privilege.py @@ -37,6 +54,7 @@ output:: Granted privileges to: +.. latex:clearpage:: **************** Revoke privilege @@ -52,4 +70,64 @@ Similarly, to revoke use the method output:: - Granted privileges to: + Revoked privileges from: + +.. latex:clearpage:: + +*************************** +Grant network access +*************************** + +Connect as admin and run +``select_ai.grant_network_access(...)`` to add a network ACL entry for +host access. This wraps ``DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE`` and can be +used for hosts that require privileges such as ``connect``, ``http``, or +``smtp``. + +Network ACLs are required when the database needs to reach an external host. +For example, use ``http`` access for AI provider endpoints and ``smtp`` access +for mail servers. Include ``connect`` with protocol-specific privileges when +the host requires it. + +When granting access, specify the target host and, when applicable, the port +range. When revoking access, use the same host, privileges, and port range that +were used for the grant. + +.. literalinclude:: ../../../samples/grant_network_access.py + :language: python + :lines: 14- + +output:: + + Granted network access to: + +The async API is ``select_ai.async_grant_network_access(...)``. + +.. literalinclude:: ../../../samples/async/grant_network_access.py + :language: python + :lines: 14- + +.. latex:clearpage:: + +*************************** +Revoke network access +*************************** + +Connect as admin and run +``select_ai.revoke_network_access(...)`` to remove a network ACL entry for +host access. This wraps ``DBMS_NETWORK_ACL_ADMIN.REMOVE_HOST_ACE`` and should +use the same host, privileges, and port range that were used to grant access. + +.. literalinclude:: ../../../samples/revoke_network_access.py + :language: python + :lines: 14- + +output:: + + Revoked network access from: + +The async API is ``select_ai.async_revoke_network_access(...)``. + +.. literalinclude:: ../../../samples/async/revoke_network_access.py + :language: python + :lines: 14- diff --git a/docs/_sources/user_guide/profile.rst.txt b/docs/_sources/user_guide/profile.rst.txt index bc0dbc6..9f1749d 100644 --- a/docs/_sources/user_guide/profile.rst.txt +++ b/docs/_sources/user_guide/profile.rst.txt @@ -4,7 +4,61 @@ An AI profile is a specification that includes the AI provider to use and other details regarding metadata and database objects required for generating responses to natural language prompts. -An AI profile object can be created using ``select_ai.Profile()`` +An AI profile object can be created using ``select_ai.Profile()``. Creating a +profile stores the profile in Oracle Database. Later, you can instantiate +``select_ai.Profile(profile_name="...")`` to reuse an existing database profile +without passing all attributes again. + +Before creating a profile, make sure the database user has the required +privileges, a credential for the AI provider, network access to the provider +endpoint, and access to the database objects included in the profile. See +:ref:`Privileges `, :ref:`Credential `, +:ref:`Provider `, and +:ref:`ProfileAttributes `. + +Profile lifecycle +================= + +The usual profile lifecycle is: + +* Create a provider object. +* Create ``ProfileAttributes`` with the provider, credential name, and object + list. +* Create the profile with ``select_ai.Profile(...)``. +* Reuse the profile later by name. +* Update profile attributes when provider settings or object scope changes. +* Delete profiles that are no longer needed. + +``replace=True`` recreates a profile when a profile with the same name already +exists. ``merge=True`` fetches the existing profile and updates it with the +non-null attributes passed by the caller. + +Profile actions +=============== + +.. list-table:: Common profile actions + :header-rows: 1 + :widths: 25 75 + :align: left + + * - Method + - Description + * - ``show_sql()`` + - Generates SQL for a natural language prompt without executing it. + * - ``run_sql()`` + - Generates SQL, executes it, and returns a ``pandas.DataFrame``. + * - ``narrate()`` + - Generates SQL, executes it, and returns a natural language answer. + * - ``explain_sql()`` + - Explains the generated SQL for a prompt. + * - ``show_prompt()`` + - Shows the prompt sent to the model. + * - ``chat()`` + - Sends a general chat prompt to the model. + * - ``summarize()`` + - Summarizes inline content or content referenced by a URI. + * - ``translate()`` + - Translates text from one language to another. ******************** Profile Object Model @@ -37,6 +91,9 @@ Base ``Profile`` API Create Profile ************************** +The following example creates an OCI Gen AI profile that can generate SQL over +objects in the ``SH`` schema. + .. literalinclude:: ../../../samples/profile_create.py :language: python :lines: 14- @@ -74,6 +131,66 @@ output:: .. latex:clearpage:: +************************** +Reuse Profile +************************** + +After a profile has been created, instantiate ``Profile`` with only the profile +name to reuse the database profile: + +.. code-block:: python + + profile = select_ai.Profile(profile_name="oci_ai_profile") + sql = profile.show_sql(prompt="How many promotions?") + +Use ``Profile.fetch(...)`` when you want to create a proxy object from a saved +database profile and raise an error if the profile does not exist: + +.. code-block:: python + + profile = select_ai.Profile.fetch("oci_ai_profile") + +.. latex:clearpage:: + +************************** +Update Profile +************************** + +Use ``set_attribute(...)`` to update one profile attribute or +``set_attributes(...)`` to update several attributes. Updates are saved to the +database profile. + +.. code-block:: python + + profile = select_ai.Profile(profile_name="oci_ai_profile") + profile.set_attribute("temperature", 0.1) + + profile.set_attributes( + select_ai.ProfileAttributes( + max_tokens=2048, + enforce_object_list=True, + ) + ) + +.. latex:clearpage:: + +************************** +Delete Profile +************************** + +Use ``delete(...)`` or ``Profile.delete_profile(...)`` to remove a profile from +the database. Pass ``force=True`` when cleanup should succeed even if the +profile does not exist. + +.. code-block:: python + + profile = select_ai.Profile(profile_name="oci_ai_profile") + profile.delete(force=True) + + select_ai.Profile.delete_profile("oci_ai_profile", force=True) + +.. latex:clearpage:: + ************************** Narrate ************************** @@ -105,6 +222,37 @@ output:: .. latex:clearpage:: +************************** +Explain SQL +************************** + +Use ``explain_sql(...)`` to generate SQL and return a natural language +explanation without executing the SQL. + +.. code-block:: python + + profile = select_ai.Profile(profile_name="oci_ai_profile") + explanation = profile.explain_sql(prompt="How many promotions?") + print(explanation) + +.. latex:clearpage:: + +************************** +Show Prompt +************************** + +Use ``show_prompt(...)`` to inspect the prompt that Select AI sends to the +model. This is useful when tuning profile attributes, object lists, comments, +constraints, and provider settings. + +.. code-block:: python + + profile = select_ai.Profile(profile_name="oci_ai_profile") + prompt = profile.show_prompt(prompt="How many promotions?") + print(prompt) + +.. latex:clearpage:: + ************************** Run SQL ************************** @@ -139,6 +287,26 @@ output:: .. latex:clearpage:: +************************** +Streaming chat +************************** + +.. literalinclude:: ../../../samples/profile_chat_stream.py + :language: python + :lines: 14- + +``stream=True`` lets callers consume generated CLOB responses chunk by chunk, +reducing memory pressure and making it easier to progressively forward output +to files, services, or user interfaces. Streaming text APIs return an iterator +of ``str`` chunks. The ``chunk_size`` parameter controls the number of CLOB +characters read per chunk; it is not a byte count. + +Streaming is supported by ``generate()``, ``chat()``, ``narrate()``, +``explain_sql()``, ``show_sql()``, and ``show_prompt()``. It is not supported +for ``run_sql()``, which returns a ``pandas.DataFrame``. + +.. latex:clearpage:: + ************************** Summarize ************************** @@ -204,6 +372,10 @@ output:: List profiles ************************** +Profile listing returns profiles visible to the connected database user. +Instantiate ``Profile`` with one of the returned names to reuse the saved +profile. + .. literalinclude:: ../../../samples/profiles_list.py :language: python :lines: 14- @@ -215,15 +387,3 @@ output:: OCI_VECTOR_AI_PROFILE ASYNC_OCI_VECTOR_AI_PROFILE OCI_AI_PROFILE - -.. latex:clearpage:: - -************* -Async Profile -************* - -.. toctree:: - :numbered: - :maxdepth: 3 - - async_profile.rst diff --git a/docs/_sources/user_guide/profile_attributes.rst.txt b/docs/_sources/user_guide/profile_attributes.rst.txt index eb5146a..4adf67a 100644 --- a/docs/_sources/user_guide/profile_attributes.rst.txt +++ b/docs/_sources/user_guide/profile_attributes.rst.txt @@ -4,9 +4,130 @@ ``ProfileAttributes`` ************************* -This class defines attributes to manage and configure the behavior of -the AI profile. The ``ProfileAttributes`` objects are created -by ``select_ai.ProfileAttributes()``. +This class defines attributes that manage and configure the behavior of an AI +profile. ``ProfileAttributes`` objects are created with +``select_ai.ProfileAttributes()`` and passed to ``select_ai.Profile`` or +``select_ai.AsyncProfile`` when creating or updating a profile. + +Profile attributes describe what the profile can access, which AI provider it +uses, how much metadata is sent to the model, and how generation should behave. +Provider-specific settings, such as OCI region or Azure deployment name, are +configured on the provider object and assigned to the ``provider`` attribute. + +Common required attributes +========================== + +Most profiles need these attributes: + +* ``provider``: A ``select_ai.Provider`` object, such as + ``select_ai.OCIGenAIProvider`` or ``select_ai.OpenAIProvider``. +* ``credential_name``: The database credential used to authenticate with the + AI provider. +* ``object_list``: The schemas, tables, or views that Select AI can use when + generating SQL from natural language prompts. + +For example: + +.. code-block:: python + + attributes = select_ai.ProfileAttributes( + provider=select_ai.OCIGenAIProvider( + region="us-chicago-1", + oci_apiformat="GENERIC", + ), + credential_name="my_oci_ai_profile_key", + object_list=[ + {"owner": "SH", "name": "CUSTOMERS"}, + {"owner": "SH", "name": "SALES"}, + ], + ) + +Attribute groups +================ + +.. list-table:: Profile attribute groups + :header-rows: 1 + :widths: 30 70 + :align: left + + * - Attribute + - Purpose + * - ``provider`` + - Selects the AI provider, model, endpoint, and provider-specific + options. + * - ``credential_name`` + - Names the database credential used to authenticate with the AI provider. + * - ``object_list`` + - Defines which schemas, tables, or views are eligible for natural + language to SQL generation. + * - ``object_list_mode`` + - Controls whether Select AI sends metadata for the most relevant objects + or for all eligible objects. + * - ``enforce_object_list`` + - Restricts generated SQL to objects in ``object_list``. + * - ``comments``, ``constraints``, ``annotations`` + - Controls whether additional database metadata is included in the prompt + sent to the model. + * - ``case_sensitive_values`` + - Helps prompts that depend on case-sensitive database values. + * - ``max_tokens``, ``temperature``, ``stop_tokens``, ``seed`` + - Tunes model generation behavior. + * - ``conversation`` + - Enables conversation history for context-aware chat workflows. + * - ``vector_index_name``, ``enable_sources``, + ``enable_source_offsets``, ``enable_custom_source_uri`` + - Configures retrieval-augmented generation and source reporting for + vector index workflows. + +Object list examples +==================== + +Grant access to every supported object in a schema: + +.. code-block:: python + + object_list = [{"owner": "SH"}] + +Grant access to selected tables: + +.. code-block:: python + + object_list = [ + {"owner": "SH", "name": "CUSTOMERS"}, + {"owner": "SH", "name": "SALES"}, + {"owner": "SH", "name": "PRODUCTS"}, + ] + +Restrict generated SQL to the selected objects: + +.. code-block:: python + + attributes = select_ai.ProfileAttributes( + provider=provider, + credential_name="my_oci_ai_profile_key", + object_list=[ + {"owner": "SH", "name": "CUSTOMERS"}, + {"owner": "SH", "name": "SALES"}, + ], + enforce_object_list=True, + ) + +Generation controls +=================== + +Use generation controls when you need more predictable or constrained model +responses: + +.. code-block:: python + + attributes = select_ai.ProfileAttributes( + provider=provider, + credential_name="my_oci_ai_profile_key", + object_list=[{"owner": "SH"}], + max_tokens=1024, + temperature=0.1, + stop_tokens='[";"]', + ) .. autoclass:: select_ai.ProfileAttributes :members: diff --git a/docs/_sources/user_guide/provider.rst.txt b/docs/_sources/user_guide/provider.rst.txt index c5e5a7f..f75f007 100644 --- a/docs/_sources/user_guide/provider.rst.txt +++ b/docs/_sources/user_guide/provider.rst.txt @@ -1,97 +1,211 @@ .. _provider: +Provider +======== + An AI Provider in Select AI refers to the service provider of the LLM, transformer or both for processing and generating responses to natural language prompts. These providers offer models that can interpret and convert natural language for the use cases highlighted under the LLM concept. See `Select your AI Provider `__ -for the supported providers +for the supported providers. + +A provider object describes the AI service that a Select AI profile, vector +index, or agent tool should call. The provider object is separate from the +credential object: the provider selects the service, model, endpoint, region, +and provider-specific options, while the credential stores authentication +details. + +Most applications should instantiate one of the concrete provider classes +instead of using ``Provider`` directly. Use the base ``Provider`` class when +you need to call a compatible provider endpoint that does not have a dedicated +class in this library. + +.. list-table:: Provider classes + :header-rows: 1 + :widths: 30 35 35 + :align: left + + * - Provider class + - Provider name + - Default endpoint behavior + * - ``AnthropicProvider`` + - ``anthropic`` + - Uses ``api.anthropic.com``. + * - ``AWSProvider`` + - ``aws`` + - Builds ``bedrock-runtime..amazonaws.com`` from ``region``. + * - ``AzureProvider`` + - ``azure`` + - Builds ``.openai.azure.com``. + * - ``CohereProvider`` + - ``cohere`` + - Uses ``api.cohere.ai``. + * - ``GoogleProvider`` + - ``google`` + - Uses ``generativelanguage.googleapis.com``. + * - ``HuggingFaceProvider`` + - ``huggingface`` + - Uses ``api-inference.huggingface.co``. + * - ``OCIGenAIProvider`` + - ``oci`` + - Uses OCI region and OCI Gen AI attributes. + * - ``OpenAIProvider`` + - ``openai`` + - Uses ``api.openai.com``. + +Examples +-------- + +OCI Gen AI provider: + +.. code-block:: python + + provider = select_ai.OCIGenAIProvider( + region="us-chicago-1", + oci_apiformat="GENERIC", + model="cohere.command-r-plus", + ) + +OpenAI provider: + +.. code-block:: python + + provider = select_ai.OpenAIProvider( + model="gpt-4.1", + ) + +Azure OpenAI provider: + +.. code-block:: python + + provider = select_ai.AzureProvider( + azure_resource_name="my-azure-openai-resource", + azure_deployment_name="gpt-4o-deployment", + azure_embedding_deployment_name="text-embedding-deployment", + ) + +AWS Bedrock provider: + +.. code-block:: python + + provider = select_ai.AWSProvider( + region="us-east-1", + aws_apiformat="ANTHROPIC", + model="anthropic.claude-3-5-sonnet-20240620-v1:0", + ) + +Custom provider endpoint: + +.. code-block:: python + + select_ai.create_credential( + credential={ + "credential_name": "xai_credential", + "username": "xai", + "password": "", + }, + replace=True, + ) + + xai_profile = select_ai.Profile( + profile_name="xai", + attributes=select_ai.ProfileAttributes( + provider=select_ai.Provider( + provider_endpoint="https://api.x.ai", + model="grok-4-1-fast-reasoning", + ), + credential_name="xai_credential", + object_list=[ + {"owner": "SH", "name": "CUSTOMERS"}, + {"owner": "SH", "name": "SALES"}, + {"owner": "SH", "name": "PRODUCTS"}, + {"owner": "SH", "name": "COUNTRIES"}, + ], + ), + replace=True, + ) + + sql = xai_profile.show_sql( + prompt="How many customers do I have?", + ) .. latex:clearpage:: -********************** ``Provider`` -********************** +------------ .. autoclass:: select_ai.Provider :members: .. latex:clearpage:: -********************************* ``AnthropicProvider`` -********************************* +--------------------- .. autoclass:: select_ai.AnthropicProvider :members: .. latex:clearpage:: -***************************** ``AzureProvider`` -***************************** +----------------- .. autoclass:: select_ai.AzureProvider :members: .. latex:clearpage:: -***************************** ``AWSProvider`` -***************************** +--------------- .. autoclass:: select_ai.AWSProvider :members: .. latex:clearpage:: -****************************** ``CohereProvider`` -****************************** +------------------ .. autoclass:: select_ai.CohereProvider :members: .. latex:clearpage:: -***************************** ``OpenAIProvider`` -***************************** +------------------ .. autoclass:: select_ai.OpenAIProvider :members: .. latex:clearpage:: -****************************** ``OCIGenAIProvider`` -****************************** +-------------------- .. autoclass:: select_ai.OCIGenAIProvider :members: .. latex:clearpage:: -****************************** ``GoogleProvider`` -****************************** +------------------ .. autoclass:: select_ai.GoogleProvider :members: .. latex:clearpage:: -*********************************** ``HuggingFaceProvider`` -*********************************** +----------------------- .. autoclass:: select_ai.HuggingFaceProvider :members: .. latex:clearpage:: -************************** Enable AI service provider -************************** +-------------------------- Enable using Sync API +++++++++++++++++++++ This method adds ACL allowing database users to invoke AI provider's -HTTP endpoint +HTTP endpoint. For non-HTTP or port-specific network access, use the network +ACL helpers described in :ref:`Privileges `. .. literalinclude:: ../../../samples/enable_ai_provider.py :language: python @@ -115,12 +229,11 @@ output:: .. latex:clearpage:: -*************************** Disable AI service provider -*************************** +--------------------------- -This method removes ACL blocking database users to invoke AI provider's -HTTP endpoint +This method removes the ACL entry that allows database users to invoke an AI +provider's HTTP endpoint. Disable using Sync API ++++++++++++++++++++++ diff --git a/docs/_sources/user_guide/summary.rst.txt b/docs/_sources/user_guide/summary.rst.txt index 300394d..d21c9f0 100644 --- a/docs/_sources/user_guide/summary.rst.txt +++ b/docs/_sources/user_guide/summary.rst.txt @@ -1,5 +1,109 @@ .. _summary: +Summarization uses a Select AI profile to summarize inline text or content +available from a URI. The profile supplies the AI provider, model, credential, +and generation settings. The ``summarize`` APIs are available on both +``Profile`` and ``AsyncProfile``. + +Use one content source per call: + +* ``content`` for inline text. +* ``location_uri`` for content available from a URL, object storage URI, or + supported file location. + +Use ``credential_name`` when the ``location_uri`` requires a database +credential, such as object storage access. Use ``prompt`` to guide what the +summary should focus on. + +Inline content +============== + +.. code-block:: python + + profile = select_ai.Profile(profile_name="oci_ai_profile") + + summary = profile.summarize( + content="Long text to summarize...", + prompt="Summarize the key business implications.", + ) + print(summary) + +Content from a URI +================== + +.. code-block:: python + + profile = select_ai.Profile(profile_name="oci_ai_profile") + + summary = profile.summarize( + location_uri="https://en.wikipedia.org/wiki/Astronomy", + ) + print(summary) + +Content from object storage +=========================== + +Pass ``credential_name`` when the target location requires authentication: + +.. code-block:: python + + profile = select_ai.Profile(profile_name="oci_ai_profile") + + summary = profile.summarize( + location_uri=( + "https://objectstorage.us-ashburn-1.oraclecloud.com/" + "n/namespace/b/bucket/o/document.txt" + ), + credential_name="OBJECT_STORE_CRED", + ) + print(summary) + +Summary parameters +================== + +Use ``SummaryParams`` to control output length, output style, chunk processing, +and extractiveness: + +.. code-block:: python + + params = select_ai.summary.SummaryParams( + min_words=50, + max_words=150, + summary_style=select_ai.summary.Style.LIST, + chunk_processing_method=( + select_ai.summary.ChunkProcessingMethod.MAP_REDUCE + ), + extractiveness_level=select_ai.summary.ExtractivenessLevel.MEDIUM, + ) + + summary = profile.summarize( + content="Long text to summarize...", + params=params, + ) + +Async summary +============= + +.. code-block:: python + + async_profile = await select_ai.AsyncProfile( + profile_name="async_oci_ai_profile", + ) + + summary = await async_profile.summarize( + content="Long text to summarize...", + prompt="Summarize the main points.", + ) + print(summary) + +Validation +========== + +``summarize`` requires exactly one of ``content`` or ``location_uri``. Passing +both, or passing neither, raises an error. + +.. latex:clearpage:: + ******************************* SummaryParams ******************************* diff --git a/docs/_sources/user_guide/synthetic_data.rst.txt b/docs/_sources/user_guide/synthetic_data.rst.txt index 4e4170d..c607360 100644 --- a/docs/_sources/user_guide/synthetic_data.rst.txt +++ b/docs/_sources/user_guide/synthetic_data.rst.txt @@ -1,5 +1,107 @@ .. _synthetic_data: +Synthetic data generation uses a Select AI profile to populate database tables +with generated rows. It is useful for demos, development, testing, and +prototyping when representative data is needed but production data should not +be copied. + +Synthetic data is inserted into the target tables in the connected database +schema or in the schema identified by ``owner_name`` or ``object_list``. Before +running generation, make sure the connected user has privileges on the target +tables and that the Select AI profile is configured with a provider and +credential. + +Use synthetic data generation with care in shared schemas. The API writes rows +to the target tables; use dedicated test tables or schemas when experimenting. + +Generation modes +================ + +Use ``object_name`` for a single target table: + +.. code-block:: python + + attributes = select_ai.SyntheticDataAttributes( + object_name="MOVIE", + record_count=100, + user_prompt="the release date for the movies should be in 2019", + ) + +Use ``object_list`` for multiple target tables in one request: + +.. code-block:: python + + attributes = select_ai.SyntheticDataAttributes( + object_list=[ + { + "owner": "SH", + "name": "MOVIE", + "record_count": 100, + "user_prompt": ( + "the release date for the movies should be in 2019" + ), + }, + {"owner": "SH", "name": "ACTOR", "record_count": 10}, + {"owner": "SH", "name": "DIRECTOR", "record_count": 5}, + ] + ) + +Exactly one of ``object_name`` or ``object_list`` must be set. + +Generation parameters +===================== + +Use ``SyntheticDataParams`` to control how generation is performed: + +.. code-block:: python + + params = select_ai.SyntheticDataParams( + sample_rows=100, + table_statistics=True, + priority="HIGH", + comments=True, + ) + + attributes = select_ai.SyntheticDataAttributes( + object_name="MOVIE", + record_count=100, + user_prompt="Generate movie data for releases in 2019.", + params=params, + ) + +``sample_rows`` controls how many existing rows are used as examples for the +model. ``table_statistics`` and ``comments`` include additional table metadata. +``priority`` controls resource priority for generation work; supported values +are ``HIGH``, ``MEDIUM``, and ``LOW``. + +Sync and async APIs +=================== + +Use ``Profile.generate_synthetic_data(...)`` for synchronous applications and +``await AsyncProfile.generate_synthetic_data(...)`` for asynchronous +applications: + +.. code-block:: python + + profile = select_ai.Profile(profile_name="oci_ai_profile") + profile.generate_synthetic_data( + synthetic_data_attributes=attributes, + ) + +.. code-block:: python + + async_profile = await select_ai.AsyncProfile( + profile_name="async_oci_ai_profile", + ) + await async_profile.generate_synthetic_data( + synthetic_data_attributes=attributes, + ) + +For additional database-side attribute details, see the +`generate_synthetic_data PL/SQL API `__. + +.. latex:clearpage:: + *************************** ``SyntheticDataAttributes`` *************************** @@ -16,9 +118,6 @@ .. autoclass:: select_ai.SyntheticDataParams :members: -Also, check the `generate_synthetic_data PL/SQL API `__ -for attribute details - .. latex:clearpage:: **************************** @@ -44,7 +143,7 @@ output:: .. latex:clearpage:: -Singe Table Async API +Single Table Async API +++++++++++++++++++++ .. literalinclude:: ../../../samples/async/profile_gen_single_table_synthetic_data.py @@ -66,7 +165,7 @@ output:: Multi table synthetic data **************************** -The below example shows multitable synthetic data generation +The below example shows multi-table synthetic data generation Multi table Sync API ++++++++++++++++++++ diff --git a/docs/_sources/user_guide/vector_index.rst.txt b/docs/_sources/user_guide/vector_index.rst.txt index d423e4c..f90e4d4 100644 --- a/docs/_sources/user_guide/vector_index.rst.txt +++ b/docs/_sources/user_guide/vector_index.rst.txt @@ -1,9 +1,39 @@ .. _vector_index: -``VectorIndex`` supports Retrieval Augmented Generation (RAG). -For e.g., you can convert text into vector embeddings and store them in a -vector store. Select AI will augment the natural language prompt by retrieving -content from the vector store using semantic similarity search. +************ +Vector Index +************ + +``VectorIndex`` supports Retrieval Augmented Generation (RAG). It converts +source documents into vector embeddings, stores the embeddings in a vector +store, and links the vector index to a Select AI profile. When that profile is +used for natural language generation, Select AI can retrieve semantically +similar content from the vector index and use that content as grounding context +for the response. + +A vector index is useful when the answer should come from files or documents +that are not represented as relational tables. Typical sources include +documents in Object Storage, product manuals, generated reports, logs, JSON +files, and other text-heavy content that should be searched by meaning rather +than exact keywords. + +Before creating a vector index, make sure the database user has: + +* A Select AI profile with an AI provider that supports embeddings. +* A credential for the AI provider used by the profile. +* A credential for the object storage location if the source objects are not + public. +* Network access to the AI provider endpoint and the source location. See + :ref:`Privileges ` for network ACL helpers. + +The usual lifecycle is: + +1. Create a profile with a provider and embedding model. +2. Create ``OracleVectorIndexAttributes`` with the source location and storage + credential. +3. Create ``VectorIndex`` and call ``create()``. +4. Use the linked profile for RAG actions such as ``narrate()``. +5. Fetch, list, update, disable, enable, or delete the index as needed. **************************** ``VectorIndex`` Object Model @@ -23,6 +53,69 @@ A ``VectorIndexAttributes`` object can be created with ``select_ai.VectorIndexAttributes()``. Also check `vector index attributes `__ +For Oracle vector indexes, use ``OracleVectorIndexAttributes``. It sets +``vector_db_provider`` to ``VectorDBProvider.ORACLE`` and is the preferred +attribute class for the examples in this guide. + +Common attributes: + +.. list-table:: + :header-rows: 1 + + * - Attribute + - Use + * - ``location`` + - Object Storage URI or source location containing the documents to + embed. + * - ``object_storage_credential_name`` + - Credential used to read the source location. + * - ``profile_name`` + - Select AI profile used to create embeddings and answer RAG prompts. + If omitted during ``create()``, it is taken from the ``profile`` object + passed to ``VectorIndex``. + * - ``chunk_size`` and ``chunk_overlap`` + - Control how source text is split before embedding. Larger chunks keep + more context together; overlap helps preserve context across chunk + boundaries. + * - ``match_limit`` + - Maximum number of matching chunks returned during semantic search. + * - ``similarity_threshold`` + - Minimum similarity score required for retrieved chunks to be considered + relevant. + * - ``vector_distance_metric`` + - Distance metric used to compare embeddings. Supported values include + ``COSINE``, ``EUCLIDEAN``, ``L2_SQUARED``, ``DOT``, ``MANHATTAN``, and + ``HAMMING``. + * - ``refresh_rate`` + - Refresh interval, in minutes, for loading new or changed source data. + * - ``vector_table_name`` + - Name of the table used to store vector embeddings and chunked data. + Leave unset unless you need to control the storage table name. + * - ``enable_sources`` + - Include filenames and source links in RAG output when supported by the + profile and model response. + +Example attributes: + +.. code-block:: python + + attributes = select_ai.OracleVectorIndexAttributes( + location="https://objectstorage.us-ashburn-1.oraclecloud.com/n/example/b/docs/o/product-guides", + object_storage_credential_name="object_store_credential", + chunk_size=1024, + chunk_overlap=128, + match_limit=5, + similarity_threshold=0.5, + vector_distance_metric=select_ai.VectorDistanceMetric.COSINE, + refresh_rate=1440, + ) + +The embedding model is configured on the provider inside the linked +``ProfileAttributes``. Keep the profile provider and vector index attributes +together conceptually: the profile decides how embeddings are generated, while +the vector index attributes decide where content is read from, how it is +chunked, and how the vector store is searched. + .. autoclass:: select_ai.VectorIndexAttributes :members: @@ -40,14 +133,47 @@ A ``VectorIndexAttributes`` object can be created with ``VectorIndex`` API ******************** - A ``VectorIndex`` object can be created with ``select_ai.VectorIndex()`` .. autoclass:: select_ai.VectorIndex :members: -Check the examples below to understand how to create vector indexes +Use the synchronous API in scripts, notebooks, and command-line tools that use +``select_ai.connect()``. Use ``AsyncVectorIndex`` in applications already using +``asyncio`` and ``select_ai.async_connect()`` or an async connection pool. + +Important lifecycle methods: + +.. list-table:: + :header-rows: 1 + + * - Method + - Use + * - ``create(replace=False, wait_for_completion=False)`` + - Create the database vector index and start the load pipeline. If + ``replace=True`` and the index already exists, the existing index is + dropped and recreated. Use ``wait_for_completion=True`` when the next + step depends on the initial load being complete. + * - ``fetch(index_name)`` + - Build a ``VectorIndex`` proxy from database metadata, including + attributes and the linked profile when it still exists. + * - ``list(index_name_pattern=".*")`` + - Iterate over vector indexes visible to the current user. The pattern is + evaluated with Oracle ``REGEXP_LIKE``. + * - ``set_attribute()`` and ``set_attributes()`` + - Update one or more index attributes. + * - ``get_next_refresh_timestamp()`` + - Return the next scheduled refresh timestamp in UTC when the index has a + refresh rate and a recorded pipeline execution. + * - ``disable()`` and ``enable()`` + - Pause or resume use of the vector index for loading, indexing, + searching, and querying. + * - ``delete(include_data=True, force=False)`` + - Drop the vector index. ``include_data=True`` also removes associated + vector store data. ``force=True`` ignores missing-index errors. + +Check the examples below to understand how to create vector indexes. .. latex:clearpage:: @@ -55,7 +181,9 @@ Create vector index +++++++++++++++++++ In the following example, vector database provider is Oracle and -objects (to create embedding for) reside in OCI's object store +objects used to create embeddings reside in OCI Object Storage. The profile +uses an OCI Generative AI provider with an embedding model, and the vector +index is linked to that profile during ``create()``. .. literalinclude:: ../../../samples/vector_index_create.py :language: python @@ -86,7 +214,9 @@ Fetch vector index +++++++++++++++++++++++++++ You can fetch the vector index attributes and associated AI profile using -the class method ``VectorIndex.fetch(index_name)`` +the class method ``VectorIndex.fetch(index_name)``. Fetch is useful when the +index was created earlier or by another process and you want to inspect or +update it without recreating the original Python object. .. literalinclude:: ../../../samples/vector_index_fetch.py :language: python @@ -104,7 +234,8 @@ Update vector index attributes ++++++++++++++++++++++++++++++ To update attributes, use either ``vector_index.set_attribute()`` or -``vector_index.set_attributes()`` +``vector_index.set_attributes()``. Use ``set_attribute()`` for a single value +and ``set_attributes()`` when updating several values together. .. literalinclude:: ../../../samples/vector_index_update_attributes.py :language: python @@ -119,6 +250,11 @@ output:: RAG using vector index ++++++++++++++++++++++ +After ``create()`` succeeds, the profile has its ``vector_index_name`` set to +the new index. Use that profile with text-returning actions such as +``narrate()`` to retrieve relevant chunks from the vector index and ground the +answer in the indexed content. + .. literalinclude:: ../../../samples/vector_index_rag.py :language: python :lines: 14- @@ -144,6 +280,11 @@ output:: Delete vector index +++++++++++++++++++ +Use ``delete()`` when the index is no longer needed. By default, +``include_data=True`` removes the vector index metadata and the associated +vector store data. Set ``include_data=False`` only when you intentionally want +to keep the underlying vector store data. + .. literalinclude:: ../../../samples/vector_index_delete.py :language: python :lines: 12- @@ -158,11 +299,34 @@ output:: ``AsyncVectorIndex`` API ************************ -A ``AsyncVectorIndex`` object can be created with ``select_ai.AsyncVectorIndex()`` +An ``AsyncVectorIndex`` object can be created with +``select_ai.AsyncVectorIndex()`` .. autoclass:: select_ai.AsyncVectorIndex :members: +The async API mirrors the synchronous API. Async profile construction and +vector index methods that access the database must be awaited, and +``AsyncVectorIndex.list()`` is an async iterator. + +.. list-table:: + :header-rows: 1 + + * - Synchronous API + - Async API + * - ``select_ai.connect(...)`` + - ``await select_ai.async_connect(...)`` + * - ``Profile(...)`` + - ``await AsyncProfile(...)`` + * - ``VectorIndex.create(...)`` + - ``await AsyncVectorIndex.create(...)`` + * - ``VectorIndex.fetch(...)`` + - ``await AsyncVectorIndex.fetch(...)`` + * - ``for index in VectorIndex.list(...)`` + - ``async for index in AsyncVectorIndex.list(...)`` + * - ``profile.narrate(...)`` + - ``await async_profile.narrate(...)`` + .. latex:clearpage:: Async create vector index diff --git a/docs/_sources/user_guide/web_frameworks.rst.txt b/docs/_sources/user_guide/web_frameworks.rst.txt new file mode 100644 index 0000000..42baefb --- /dev/null +++ b/docs/_sources/user_guide/web_frameworks.rst.txt @@ -0,0 +1,374 @@ +.. _web_frameworks: + +************************************************** +Using ``select_ai`` with Python web frameworks +************************************************** + +Python web applications should create a Select AI connection pool when the +application starts and close it when the application shuts down. A pool lets +concurrent requests share a bounded set of database connections instead of +creating standalone connections per request. + +This pattern works with Python Web Server Gateway Interface (WSGI) and +Asynchronous Server Gateway Interface (ASGI) frameworks. FastAPI is used below +as a concrete example, but the same approach applies to frameworks such as +Flask, Django, Starlette, Sanic, and Quart: initialize the pool during +application startup, use ``select_ai`` APIs inside request handlers, and close +the pool during application shutdown. + +Do not call ``select_ai.connect()`` or ``select_ai.create_pool()`` inside every +request handler. Creating connections per request adds latency, increases +database connection churn, and can exhaust the database connection limit under +load. Create one pool per worker process and let ``select_ai`` acquire and +release connections from that pool for each API call. + +For background and concurrency measurements, see this +`connection pooling blog `__. + +Framework patterns +================== + +Use the framework lifecycle API that runs once per process: + +* `FastAPI `__ / + `Starlette `__: use a ``lifespan`` async + context manager. Create the pool before ``yield`` and close it after + ``yield``. + +* `Flask `__: + create the pool in ``create_app()``. Close the pool from the shutdown hook + provided by the process that runs Flask, such as a Gunicorn ``worker_exit`` + hook. For simple local applications, ``atexit.register()`` can be used for + normal interpreter shutdown. + +* `Django `__: + create the pool in ``AppConfig.ready()``. Close the pool from the shutdown + hook provided by the process that runs Django, such as a Gunicorn + ``worker_exit`` hook. For simple local applications, ``atexit.register()`` + can be used for normal interpreter shutdown. + +* `Quart `__: + use ``@app.before_serving`` / ``@app.after_serving``, or + ``@app.while_serving`` with cleanup after ``yield``. + +* `Sanic `__: use + ``@app.before_server_start`` and ``@app.after_server_stop``. + +Use ``select_ai.create_pool()`` for synchronous request handlers and +``select_ai.create_pool_async()`` for asynchronous request handlers. In +general, synchronous routes should call synchronous Select AI methods, and async +routes should call async Select AI methods. Avoid mixing blocking synchronous +database calls into async routes unless the framework runs them in a worker +thread. + +For Flask and Django, be careful with hooks that run per request or per +application context. A Select AI pool should live for the worker process, not +for a single request. For example, Flask's ``teardown_appcontext`` runs when an +application context is popped, so it is not a good place to close a process-wide +pool after every request. + +Install dependencies +==================== + +Install ``select_ai`` and FastAPI server dependencies: + +.. code-block:: sh + + python -m pip install select_ai fastapi uvicorn + +For local development, set the database connection details as environment +variables: + +.. code-block:: sh + + export SELECT_AI_USER= + export SELECT_AI_PASSWORD= + export SELECT_AI_DB_CONNECT_STRING= + export SELECT_AI_POOL_MIN=5 + export SELECT_AI_POOL_MAX=10 + export SELECT_AI_POOL_INCREMENT=5 + +If you use an mTLS wallet, also set ``TNS_ADMIN`` or pass wallet parameters to +``select_ai.create_pool()`` / ``select_ai.create_pool_async()``. + +For production deployments, store these values in your deployment platform's +secret manager or environment configuration. Do not hard-code database +passwords, wallet passwords, or provider credentials in application source. + +FastAPI synchronous endpoints +============================= + +Create a file named ``app.py``: + +.. code-block:: python + + import os + from contextlib import asynccontextmanager + + from fastapi import FastAPI + + import select_ai + + user = os.getenv("SELECT_AI_USER") + password = os.getenv("SELECT_AI_PASSWORD") + dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING") + + pool_min = int(os.getenv("SELECT_AI_POOL_MIN", "5")) + pool_max = int(os.getenv("SELECT_AI_POOL_MAX", "10")) + pool_increment = int(os.getenv("SELECT_AI_POOL_INCREMENT", "5")) + + + @asynccontextmanager + async def lifespan(app: FastAPI): + select_ai.create_pool( + user=user, + password=password, + dsn=dsn, + min_size=pool_min, + max_size=pool_max, + increment=pool_increment, + ) + yield + select_ai.disconnect() + + + app = FastAPI(lifespan=lifespan) + + + @app.get("/chat") + def chat(prompt: str): + profile = select_ai.Profile(profile_name="oci_ai_profile") + return {"response": profile.chat(prompt=prompt)} + + + @app.get("/show_sql") + def show_sql(prompt: str): + profile = select_ai.Profile(profile_name="oci_ai_profile") + return {"sql": profile.show_sql(prompt=prompt)} + +Start the server: + +.. code-block:: sh + + uvicorn app:app --host 0.0.0.0 --port 8000 + +Call the service: + +.. code-block:: sh + + curl "http://localhost:8000/chat?prompt=What%20is%20OCI%3F" + +Stop the server by pressing ``Ctrl+C`` in the terminal where ``uvicorn`` is +running. FastAPI runs the lifespan shutdown hook and ``select_ai.disconnect()`` +closes the pool. + +This example creates the ``Profile`` proxy inside each handler. The proxy is +lightweight; the database connection is acquired from the pool only when the +profile method calls the database. + +FastAPI asynchronous endpoints +============================== + +For async endpoints, initialize the async pool with +``select_ai.create_pool_async()`` and close it with +``select_ai.async_disconnect()``. + +.. code-block:: python + + import os + from contextlib import asynccontextmanager + + from fastapi import FastAPI + + import select_ai + + user = os.getenv("SELECT_AI_USER") + password = os.getenv("SELECT_AI_PASSWORD") + dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING") + + + @asynccontextmanager + async def lifespan(app: FastAPI): + select_ai.create_pool_async( + user=user, + password=password, + dsn=dsn, + min_size=5, + max_size=10, + increment=5, + ) + yield + await select_ai.async_disconnect() + + + app = FastAPI(lifespan=lifespan) + + + @app.get("/chat") + async def chat(prompt: str): + profile = await select_ai.AsyncProfile( + profile_name="async_oci_ai_profile" + ) + return {"response": await profile.chat(prompt=prompt)} + +Start and stop the server the same way: + +.. code-block:: sh + + uvicorn app:app --host 0.0.0.0 --port 8000 + +Press ``Ctrl+C`` to stop it. + +Flask example +============= + +Flask applications normally use synchronous request handlers, so initialize a +synchronous Select AI pool when the application is created. + +.. code-block:: python + + import atexit + import os + + from flask import Flask, jsonify, request + + import select_ai + + + def create_app(): + app = Flask(__name__) + + select_ai.create_pool( + user=os.getenv("SELECT_AI_USER"), + password=os.getenv("SELECT_AI_PASSWORD"), + dsn=os.getenv("SELECT_AI_DB_CONNECT_STRING"), + min_size=int(os.getenv("SELECT_AI_POOL_MIN", "1")), + max_size=int(os.getenv("SELECT_AI_POOL_MAX", "4")), + increment=int(os.getenv("SELECT_AI_POOL_INCREMENT", "1")), + ) + + @app.get("/show_sql") + def show_sql(): + prompt = request.args["prompt"] + profile = select_ai.Profile(profile_name="oci_ai_profile") + return jsonify({"sql": profile.show_sql(prompt=prompt)}) + + @atexit.register + def close_select_ai_pool(): + if select_ai.is_connected(): + select_ai.disconnect() + + return app + +Django example +============== + +Django has its own database connection management, but ``select_ai`` uses the +Oracle Database connection pool created by this package. Create the Select AI +pool once per process, then call ``Profile`` APIs inside views. + +.. code-block:: python + + # myapp/apps.py + import os + + from django.apps import AppConfig + + import select_ai + + + class MyAppConfig(AppConfig): + name = "myapp" + + def ready(self): + if not select_ai.is_connected(): + select_ai.create_pool( + user=os.getenv("SELECT_AI_USER"), + password=os.getenv("SELECT_AI_PASSWORD"), + dsn=os.getenv("SELECT_AI_DB_CONNECT_STRING"), + min_size=int(os.getenv("SELECT_AI_POOL_MIN", "1")), + max_size=int(os.getenv("SELECT_AI_POOL_MAX", "4")), + increment=int(os.getenv("SELECT_AI_POOL_INCREMENT", "1")), + ) + +.. code-block:: python + + # myapp/views.py + from django.http import JsonResponse + + import select_ai + + + def show_sql(request): + profile = select_ai.Profile(profile_name="oci_ai_profile") + sql = profile.show_sql(prompt=request.GET["prompt"]) + return JsonResponse({"sql": sql}) + +When using Django's development autoreloader, startup hooks may run more than +once. The ``is_connected()`` check prevents this example from creating a second +pool in the same process. + +Pool sizing +=========== + +Use connection pooling for concurrent services such as API applications, +workloads with mixed fast and slow requests, and applications with tail-latency +requirements. Use standalone connections for simple scripts, command-line +tools, or low-concurrency batch jobs. + +Set pool sizing based on expected request concurrency and database capacity. +In multi-worker deployments, each worker process creates its own pool, so total +possible database connections are approximately: + +.. code-block:: text + + workers * SELECT_AI_POOL_MAX + +Choose pool sizes that leave capacity for other database clients and avoid +overwhelming small database deployments. + +For example, a service running four worker processes with +``SELECT_AI_POOL_MAX=10`` can open up to forty Select AI database connections. +If the database can only spare twenty connections for the application, use fewer +workers, reduce ``SELECT_AI_POOL_MAX``, or both. + +Pool wait behavior +================== + +``select_ai.create_pool()`` and ``select_ai.create_pool_async()`` pass pool +options through to ``python-oracledb``. Use ``wait_timeout`` and ``getmode`` to +control what happens when all pooled connections are busy. + +.. code-block:: python + + select_ai.create_pool( + user=user, + password=password, + dsn=dsn, + min_size=2, + max_size=8, + increment=2, + wait_timeout=10, + ) + +Choose a timeout that matches your API latency budget. For public HTTP APIs, +it is usually better to fail fast and return an application error than to let +requests pile up until every worker is blocked. + +Request handling +================ + +Validate prompts and profile names before calling Select AI methods. If clients +can choose a profile, check the requested profile against an application +allowlist instead of passing arbitrary user input directly into +``Profile(profile_name=...)``. + +For long-running prompts, set HTTP server timeouts and client timeouts +deliberately. Text generation and RAG calls can take longer than simple SQL +metadata operations, especially when external AI providers or object storage +are involved. + +For streaming responses, prefer async frameworks and async Select AI methods when +the rest of the application is already async. For ordinary JSON responses, +either synchronous or asynchronous routes are fine as long as the connection +pool matches the route style. diff --git a/docs/_static/documentation_options.js b/docs/_static/documentation_options.js index 0ec80b7..d21c3d3 100644 --- a/docs/_static/documentation_options.js +++ b/docs/_static/documentation_options.js @@ -1,5 +1,5 @@ const DOCUMENTATION_OPTIONS = { - VERSION: '1.3.0', + VERSION: '1.4.0rc1', LANGUAGE: 'en', COLLAPSE_INDEX: false, BUILDER: 'html', diff --git a/docs/_static/pydoctheme.css b/docs/_static/pydoctheme.css index 7167add..aa9622d 100644 --- a/docs/_static/pydoctheme.css +++ b/docs/_static/pydoctheme.css @@ -223,6 +223,9 @@ div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 { border: 0; padding: 0.3em 0; } +div.body dl.field-list > dt { + line-height: 1.6; +} div.body hr { border: 0; @@ -786,10 +789,12 @@ div.genindex-jumpbox a { --versionadded: var(--good-color); --versionchanged: var(--middle-color); --deprecated: var(--bad-color); + --soft-deprecated: rgb(175, 0, 255); --versionadded-border: var(--good-border); --versionchanged-border: var(--middle-border); --deprecated-border: var(--bad-border); + --soft-deprecated-border: rgb(175, 0, 255); } div.versionadded, @@ -814,6 +819,10 @@ div.versionremoved { border-left-color: var(--deprecated-border); } +div.soft-deprecated { + border-left-color: var(--soft-deprecated-border); +} + div.versionadded .versionmodified { color: var(--versionadded); } @@ -828,6 +837,10 @@ div.versionremoved .versionmodified { color: var(--deprecated); } +div.soft-deprecated .versionmodified { + color: var(--soft-deprecated); +} + /* Hide header when printing */ @media print { div.mobile-nav { diff --git a/docs/_static/pydoctheme_dark.css b/docs/_static/pydoctheme_dark.css index 909a296..df91a2a 100644 --- a/docs/_static/pydoctheme_dark.css +++ b/docs/_static/pydoctheme_dark.css @@ -181,6 +181,8 @@ img.invert-in-dark-mode { --versionadded: var(--good-color); --versionchanged: var(--middle-color); --deprecated: var(--bad-color); + --soft-deprecated: rgb(206, 100, 255); + --soft-deprecated-border: rgb(206, 100, 255); } .copybutton { diff --git a/docs/genindex.html b/docs/genindex.html index dc41ad6..df59397 100644 --- a/docs/genindex.html +++ b/docs/genindex.html @@ -4,14 +4,14 @@ - Index — Select AI for Python 1.3.0 documentation + Index — Select AI for Python 1.4.0rc1 documentation - + - + @@ -85,7 +85,7 @@

Navigation

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • @@ -130,6 +130,7 @@

    Index

    | F | G | H + | I | L | N | O @@ -423,6 +424,18 @@

    E

    +
  • export() (select_ai.agent.AsyncTeam method) + +
  • +
  • export_team() (select_ai.agent.AsyncTeam class method) + +
  • ExtractivenessLevel (class in select_ai.summary) @@ -522,6 +535,18 @@

    H

    +

    I

    + + +
    +

    L

    - - - - + + - + + +
    @@ -121,7 +126,7 @@

    Navigation

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • @@ -164,16 +169,26 @@

    select_ai documentationGetting Started

    @@ -200,50 +223,54 @@

    Privileges

    @@ -266,7 +298,13 @@

    Profile Attributes @@ -276,62 +314,61 @@

    Profile Attributes

    + +
    +

    Async Profile

    +
    + @@ -356,7 +393,7 @@

    ConversationConversation.set_attributes() -
  • 3.1. Create conversion
  • +
  • 3.1. Create conversation
  • 3.2. Chat session
  • 3.3. List conversations
  • 3.4. Delete conversation
  • @@ -383,16 +420,17 @@

    Conversation

    +
    +

    Async AI Agent

    +
    +
    +
    +
    +

    Command Line Interface

    + +
    +
    +

    Web Frameworks

    + +
    +
    +

    Concurrent Prompt Processing

    + @@ -615,11 +787,16 @@

    Table of Contents

  • Credential
  • Profile Attributes
  • Profile
  • +
  • Async Profile
  • Conversation
  • Vector Index
  • Synthetic Data
  • Summary
  • AI Agent
  • +
  • Async AI Agent
  • +
  • Command Line Interface
  • +
  • Web Frameworks
  • +
  • Concurrent Prompt Processing
  • @@ -666,7 +843,7 @@

    Navigation

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • diff --git a/docs/license.html b/docs/license.html index f0f6923..f297b9e 100644 --- a/docs/license.html +++ b/docs/license.html @@ -5,14 +5,14 @@ - <no title> — Select AI for Python 1.3.0 documentation + <no title> — Select AI for Python 1.4.0rc1 documentation - + - + @@ -93,7 +93,7 @@

    Navigation

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • @@ -202,7 +202,7 @@

    Navigation

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • diff --git a/docs/objects.inv b/docs/objects.inv index 46c5b65..fa15d2a 100644 Binary files a/docs/objects.inv and b/docs/objects.inv differ diff --git a/docs/search.html b/docs/search.html index 3a69be8..1143474 100644 --- a/docs/search.html +++ b/docs/search.html @@ -4,15 +4,15 @@ - Search — Select AI for Python 1.3.0 documentation + Search — Select AI for Python 1.4.0rc1 documentation - + - + @@ -75,7 +75,7 @@

    Navigation

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • @@ -149,7 +149,7 @@

    Navigation

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • diff --git a/docs/searchindex.js b/docs/searchindex.js index a48c517..e3e2339 100644 --- a/docs/searchindex.js +++ b/docs/searchindex.js @@ -1 +1 @@ -Search.setIndex({"alltitles":{"AI Agent":[[0,"ai-agent"]],"AI Provider and expected credential format":[[8,null]],"AI agent examples":[[3,"ai-agent-examples"]],"AWSProvider":[[14,"awsprovider"]],"Actions":[[0,"actions"]],"Agent":[[3,"id1"]],"AnthropicProvider":[[14,"anthropicprovider"]],"Async AI Agent":[[3,"async-ai-agent"]],"Async AI agent examples":[[4,"async-ai-agent-examples"]],"Async API":[[8,"async-api"]],"Async Profile":[[12,"async-profile"]],"Async Profile creation":[[5,"async-profile-creation"]],"Async RAG using vector index":[[17,"async-rag-using-vector-index"]],"Async chat":[[5,"async-chat"]],"Async chat session":[[7,"async-chat-session"]],"Async concurrent SQL":[[5,"async-concurrent-sql"]],"Async create vector index":[[17,"async-create-vector-index"]],"Async explain SQL":[[5,"async-explain-sql"]],"Async fetch vector index":[[17,"async-fetch-vector-index"]],"Async list conversations":[[7,"async-list-conversations"]],"Async list vector index":[[17,"async-list-vector-index"]],"Async pipeline":[[5,"async-pipeline"]],"Async run SQL":[[5,"async-run-sql"]],"Async show SQL":[[5,"async-show-sql"]],"Async update vector index attributes":[[17,"async-update-vector-index-attributes"]],"AsyncAgent":[[4,"asyncagent"]],"AsyncConversation API":[[7,"asyncconversation-api"]],"AsyncProfile API":[[5,null]],"AsyncTask":[[4,"asynctask"]],"AsyncTeam":[[4,"asyncteam"]],"AsyncTool":[[4,"asynctool"]],"AsyncVectorIndex API":[[17,"asyncvectorindex-api"]],"Asynchronous connection":[[6,"asynchronous-connection"]],"AzureProvider":[[14,"azureprovider"]],"Base Profile API":[[12,"base-profile-api"]],"Chat":[[12,"chat"]],"Chat session":[[7,"chat-session"]],"ChunkProcessingMethod":[[15,"chunkprocessingmethod"]],"CohereProvider":[[14,"cohereprovider"]],"Connecting to Oracle Database":[[6,null]],"Connection Pool":[[6,"connection-pool"]],"Conversation":[[0,"conversation"]],"Conversation API":[[7,"conversation-api"]],"Conversation Object model":[[7,null]],"ConversationAttributes":[[7,"conversationattributes"]],"Create Agent":[[3,"create-agent"],[4,"create-agent"]],"Create Profile":[[12,"create-profile"]],"Create Task":[[3,"create-task"],[4,"create-task"]],"Create Tool":[[3,"create-tool"],[4,"create-tool"]],"Create conversion":[[7,"create-conversion"]],"Create credential":[[8,"create-credential"]],"Create vector index":[[17,"create-vector-index"]],"Credential":[[0,"credential"]],"Delete conversation":[[7,"delete-conversation"]],"Delete vector index":[[17,"delete-vector-index"]],"Disable AI service provider":[[14,"disable-ai-service-provider"]],"Disable using Async API":[[14,"disable-using-async-api"]],"Disable using Sync API":[[14,"disable-using-sync-api"]],"Enable AI service provider":[[14,"enable-ai-service-provider"]],"Enable using Async API":[[14,"enable-using-async-api"]],"Enable using Sync API":[[14,"enable-using-sync-api"]],"ExtractivenessLevel":[[15,"extractivenesslevel"]],"Fetch vector index":[[17,"fetch-vector-index"]],"Getting Started":[[0,"getting-started"]],"GoogleProvider":[[14,"googleprovider"]],"Grant privilege":[[11,null]],"HuggingFaceProvider":[[14,"huggingfaceprovider"]],"Installation requirements":[[9,"installation-requirements"]],"Installing select_ai":[[9,null]],"Introduction to Select AI for Python":[[10,null]],"List Agents":[[4,"list-agents"]],"List Tasks":[[3,"list-tasks"],[4,"list-tasks"]],"List Teams":[[4,"list-teams"]],"List Tools":[[3,"list-tools"],[4,"list-tools"]],"List conversations":[[7,"list-conversations"]],"List profiles":[[12,"list-profiles"]],"List profiles asynchronously":[[5,"list-profiles-asynchronously"]],"List vector index":[[17,"list-vector-index"]],"Multi table Async API":[[16,"multi-table-async-api"]],"Multi table Sync API":[[16,"multi-table-sync-api"]],"Multi table synthetic data":[[16,"multi-table-synthetic-data"]],"Narrate":[[12,"narrate"]],"OCIGenAIProvider":[[14,"ocigenaiprovider"]],"OpenAIProvider":[[14,"openaiprovider"]],"OracleVectorIndexAttributes":[[17,"oraclevectorindexattributes"]],"Privileges":[[0,"privileges"]],"Profile":[[0,"profile"]],"Profile API":[[12,"profile-api"]],"Profile Attributes":[[0,"profile-attributes"]],"Profile Object Model":[[12,null]],"ProfileAttributes":[[13,null]],"Provider":[[0,"provider"],[14,null]],"RAG using vector index":[[17,"rag-using-vector-index"]],"Revoke privilege":[[11,"revoke-privilege"]],"Run SQL":[[12,"run-sql"]],"Run Team":[[3,"run-team"],[4,"run-team"]],"Select AI Actions":[[2,"id1"]],"Select AI Agent Tools":[[3,"id2"]],"Select AI Async Agent Tools":[[4,null]],"Show SQL":[[12,"show-sql"]],"Singe Table Async API":[[16,"singe-table-async-api"]],"Single Table Sync API":[[16,"single-table-sync-api"]],"Single table synthetic data":[[16,"single-table-synthetic-data"]],"Summarize":[[5,"summarize"],[12,"summarize"]],"Summary":[[0,"summary"]],"SummaryParams":[[15,null]],"SummaryStyle":[[15,"summarystyle"]],"Supported Actions":[[2,null]],"Supported Tools":[[3,"supported-tools"]],"Sync API":[[8,"sync-api"]],"Synchronous connection":[[6,"synchronous-connection"]],"Synthetic Data":[[0,"synthetic-data"]],"SyntheticDataAttributes":[[16,null]],"SyntheticDataParams":[[16,"syntheticdataparams"]],"Task":[[3,"task"]],"Team":[[3,"team"]],"Tool":[[3,null]],"Translate":[[5,"translate"],[12,"translate"]],"Update vector index attributes":[[17,"update-vector-index-attributes"]],"Vector Index":[[0,"vector-index"]],"VectorIndex API":[[17,"vectorindex-api"]],"VectorIndex Object Model":[[17,null]],"VectorIndexAttributes":[[17,"vectorindexattributes"]],"Web Search Agent using OpenAI\u2019s GPT model":[[3,"web-search-agent-using-openai-s-gpt-model"],[4,"web-search-agent-using-openai-s-gpt-model"]],"select_ai documentation":[[0,null]],"select_ai installation":[[9,"select-ai-installation"]]},"docnames":["index","license","user_guide/actions","user_guide/agent","user_guide/async_agent","user_guide/async_profile","user_guide/connection","user_guide/conversation","user_guide/credential","user_guide/installation","user_guide/introduction","user_guide/privileges","user_guide/profile","user_guide/profile_attributes","user_guide/provider","user_guide/summary","user_guide/synthetic_data","user_guide/vector_index"],"envversion":{"sphinx":65,"sphinx.domains.c":3,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":9,"sphinx.domains.index":1,"sphinx.domains.javascript":3,"sphinx.domains.math":2,"sphinx.domains.python":4,"sphinx.domains.rst":2,"sphinx.domains.std":2},"filenames":["index.rst","license.rst","user_guide/actions.rst","user_guide/agent.rst","user_guide/async_agent.rst","user_guide/async_profile.rst","user_guide/connection.rst","user_guide/conversation.rst","user_guide/credential.rst","user_guide/installation.rst","user_guide/introduction.rst","user_guide/privileges.rst","user_guide/profile.rst","user_guide/profile_attributes.rst","user_guide/provider.rst","user_guide/summary.rst","user_guide/synthetic_data.rst","user_guide/vector_index.rst"],"indexentries":{"add_negative_feedback() (select_ai.asyncprofile method)":[[5,"select_ai.AsyncProfile.add_negative_feedback",false]],"add_negative_feedback() (select_ai.profile method)":[[12,"select_ai.Profile.add_negative_feedback",false]],"add_positive_feedback() (select_ai.asyncprofile method)":[[5,"select_ai.AsyncProfile.add_positive_feedback",false]],"add_positive_feedback() (select_ai.profile method)":[[12,"select_ai.Profile.add_positive_feedback",false]],"agent (class in select_ai.agent)":[[3,"select_ai.agent.Agent",false]],"agentattributes (class in select_ai.agent)":[[3,"select_ai.agent.AgentAttributes",false]],"asyncagent (class in select_ai.agent)":[[4,"select_ai.agent.AsyncAgent",false]],"asyncprofile (class in select_ai)":[[5,"select_ai.AsyncProfile",false]],"asynctask (class in select_ai.agent)":[[4,"select_ai.agent.AsyncTask",false]],"asyncteam (class in select_ai.agent)":[[4,"select_ai.agent.AsyncTeam",false]],"asynctool (class in select_ai.agent)":[[4,"select_ai.agent.AsyncTool",false]],"baseprofile (class in select_ai)":[[12,"select_ai.BaseProfile",false]],"chat() (select_ai.asyncprofile method)":[[5,"select_ai.AsyncProfile.chat",false]],"chat() (select_ai.profile method)":[[12,"select_ai.Profile.chat",false]],"chat_session() (select_ai.asyncprofile method)":[[5,"select_ai.AsyncProfile.chat_session",false]],"chat_session() (select_ai.profile method)":[[12,"select_ai.Profile.chat_session",false]],"create() (select_ai.agent.agent method)":[[3,"select_ai.agent.Agent.create",false]],"create() (select_ai.agent.asyncagent method)":[[4,"select_ai.agent.AsyncAgent.create",false]],"create() (select_ai.agent.asynctask method)":[[4,"select_ai.agent.AsyncTask.create",false]],"create() (select_ai.agent.asyncteam method)":[[4,"select_ai.agent.AsyncTeam.create",false]],"create() (select_ai.agent.asynctool method)":[[4,"select_ai.agent.AsyncTool.create",false]],"create() (select_ai.agent.task method)":[[3,"select_ai.agent.Task.create",false]],"create() (select_ai.agent.team method)":[[3,"select_ai.agent.Team.create",false]],"create() (select_ai.asyncprofile method)":[[5,"select_ai.AsyncProfile.create",false]],"create() (select_ai.profile method)":[[12,"select_ai.Profile.create",false]],"create_built_in_tool() (select_ai.agent.asynctool class method)":[[4,"select_ai.agent.AsyncTool.create_built_in_tool",false]],"create_built_in_tool() (select_ai.agent.tool class method)":[[3,"select_ai.agent.Tool.create_built_in_tool",false]],"create_email_notification_tool() (select_ai.agent.asynctool class method)":[[4,"select_ai.agent.AsyncTool.create_email_notification_tool",false]],"create_email_notification_tool() (select_ai.agent.tool class method)":[[3,"select_ai.agent.Tool.create_email_notification_tool",false]],"create_pl_sql_tool() (select_ai.agent.asynctool class method)":[[4,"select_ai.agent.AsyncTool.create_pl_sql_tool",false]],"create_pl_sql_tool() (select_ai.agent.tool class method)":[[3,"select_ai.agent.Tool.create_pl_sql_tool",false]],"create_rag_tool() (select_ai.agent.asynctool class method)":[[4,"select_ai.agent.AsyncTool.create_rag_tool",false]],"create_rag_tool() (select_ai.agent.tool class method)":[[3,"select_ai.agent.Tool.create_rag_tool",false]],"create_slack_notification_tool() (select_ai.agent.asynctool class method)":[[4,"select_ai.agent.AsyncTool.create_slack_notification_tool",false]],"create_slack_notification_tool() (select_ai.agent.tool class method)":[[3,"select_ai.agent.Tool.create_slack_notification_tool",false]],"create_sql_tool() (select_ai.agent.asynctool class method)":[[4,"select_ai.agent.AsyncTool.create_sql_tool",false]],"create_sql_tool() (select_ai.agent.tool class method)":[[3,"select_ai.agent.Tool.create_sql_tool",false]],"create_websearch_tool() (select_ai.agent.asynctool class method)":[[4,"select_ai.agent.AsyncTool.create_websearch_tool",false]],"create_websearch_tool() (select_ai.agent.tool class method)":[[3,"select_ai.agent.Tool.create_websearch_tool",false]],"delete() (select_ai.agent.agent method)":[[3,"select_ai.agent.Agent.delete",false]],"delete() (select_ai.agent.asyncagent method)":[[4,"select_ai.agent.AsyncAgent.delete",false]],"delete() (select_ai.agent.asynctask method)":[[4,"select_ai.agent.AsyncTask.delete",false]],"delete() (select_ai.agent.asyncteam method)":[[4,"select_ai.agent.AsyncTeam.delete",false]],"delete() (select_ai.agent.asynctool method)":[[4,"select_ai.agent.AsyncTool.delete",false]],"delete() (select_ai.agent.task method)":[[3,"select_ai.agent.Task.delete",false]],"delete() (select_ai.agent.team method)":[[3,"select_ai.agent.Team.delete",false]],"delete() (select_ai.agent.tool method)":[[3,"select_ai.agent.Tool.delete",false]],"delete() (select_ai.asyncprofile method)":[[5,"select_ai.AsyncProfile.delete",false]],"delete() (select_ai.profile method)":[[12,"select_ai.Profile.delete",false]],"delete_agent() (select_ai.agent.agent class method)":[[3,"select_ai.agent.Agent.delete_agent",false]],"delete_agent() (select_ai.agent.asyncagent class method)":[[4,"select_ai.agent.AsyncAgent.delete_agent",false]],"delete_feedback() (select_ai.asyncprofile method)":[[5,"select_ai.AsyncProfile.delete_feedback",false]],"delete_feedback() (select_ai.profile method)":[[12,"select_ai.Profile.delete_feedback",false]],"delete_profile() (select_ai.asyncprofile class method)":[[5,"select_ai.AsyncProfile.delete_profile",false]],"delete_profile() (select_ai.profile class method)":[[12,"select_ai.Profile.delete_profile",false]],"delete_task() (select_ai.agent.asynctask class method)":[[4,"select_ai.agent.AsyncTask.delete_task",false]],"delete_task() (select_ai.agent.task class method)":[[3,"select_ai.agent.Task.delete_task",false]],"delete_team() (select_ai.agent.asyncteam class method)":[[4,"select_ai.agent.AsyncTeam.delete_team",false]],"delete_team() (select_ai.agent.team class method)":[[3,"select_ai.agent.Team.delete_team",false]],"delete_tool() (select_ai.agent.asynctool class method)":[[4,"select_ai.agent.AsyncTool.delete_tool",false]],"delete_tool() (select_ai.agent.tool class method)":[[3,"select_ai.agent.Tool.delete_tool",false]],"disable() (select_ai.agent.agent method)":[[3,"select_ai.agent.Agent.disable",false]],"disable() (select_ai.agent.asyncagent method)":[[4,"select_ai.agent.AsyncAgent.disable",false]],"disable() (select_ai.agent.asynctask method)":[[4,"select_ai.agent.AsyncTask.disable",false]],"disable() (select_ai.agent.asyncteam method)":[[4,"select_ai.agent.AsyncTeam.disable",false]],"disable() (select_ai.agent.asynctool method)":[[4,"select_ai.agent.AsyncTool.disable",false]],"disable() (select_ai.agent.task method)":[[3,"select_ai.agent.Task.disable",false]],"disable() (select_ai.agent.team method)":[[3,"select_ai.agent.Team.disable",false]],"disable() (select_ai.agent.tool method)":[[3,"select_ai.agent.Tool.disable",false]],"enable() (select_ai.agent.agent method)":[[3,"select_ai.agent.Agent.enable",false]],"enable() (select_ai.agent.asyncagent method)":[[4,"select_ai.agent.AsyncAgent.enable",false]],"enable() (select_ai.agent.asynctask method)":[[4,"select_ai.agent.AsyncTask.enable",false]],"enable() (select_ai.agent.asyncteam method)":[[4,"select_ai.agent.AsyncTeam.enable",false]],"enable() (select_ai.agent.asynctool method)":[[4,"select_ai.agent.AsyncTool.enable",false]],"enable() (select_ai.agent.task method)":[[3,"select_ai.agent.Task.enable",false]],"enable() (select_ai.agent.team method)":[[3,"select_ai.agent.Team.enable",false]],"enable() (select_ai.agent.tool method)":[[3,"select_ai.agent.Tool.enable",false]],"explain_sql() (select_ai.asyncprofile method)":[[5,"select_ai.AsyncProfile.explain_sql",false]],"explain_sql() (select_ai.profile method)":[[12,"select_ai.Profile.explain_sql",false]],"fetch() (select_ai.agent.agent class method)":[[3,"select_ai.agent.Agent.fetch",false]],"fetch() (select_ai.agent.asyncagent class method)":[[4,"select_ai.agent.AsyncAgent.fetch",false]],"fetch() (select_ai.agent.asynctask class method)":[[4,"select_ai.agent.AsyncTask.fetch",false]],"fetch() (select_ai.agent.asyncteam class method)":[[4,"select_ai.agent.AsyncTeam.fetch",false]],"fetch() (select_ai.agent.asynctool class method)":[[4,"select_ai.agent.AsyncTool.fetch",false]],"fetch() (select_ai.agent.task class method)":[[3,"select_ai.agent.Task.fetch",false]],"fetch() (select_ai.agent.team class method)":[[3,"select_ai.agent.Team.fetch",false]],"fetch() (select_ai.agent.tool class method)":[[3,"select_ai.agent.Tool.fetch",false]],"fetch() (select_ai.asyncprofile class method)":[[5,"select_ai.AsyncProfile.fetch",false]],"fetch() (select_ai.profile class method)":[[12,"select_ai.Profile.fetch",false]],"generate() (select_ai.asyncprofile method)":[[5,"select_ai.AsyncProfile.generate",false]],"generate() (select_ai.profile method)":[[12,"select_ai.Profile.generate",false]],"generate_synthetic_data() (select_ai.asyncprofile method)":[[5,"select_ai.AsyncProfile.generate_synthetic_data",false]],"generate_synthetic_data() (select_ai.profile method)":[[12,"select_ai.Profile.generate_synthetic_data",false]],"get_attributes() (select_ai.asyncprofile method)":[[5,"select_ai.AsyncProfile.get_attributes",false]],"get_attributes() (select_ai.profile method)":[[12,"select_ai.Profile.get_attributes",false]],"list() (select_ai.agent.agent class method)":[[3,"select_ai.agent.Agent.list",false]],"list() (select_ai.agent.asyncagent class method)":[[4,"select_ai.agent.AsyncAgent.list",false]],"list() (select_ai.agent.asynctask class method)":[[4,"select_ai.agent.AsyncTask.list",false]],"list() (select_ai.agent.asyncteam class method)":[[4,"select_ai.agent.AsyncTeam.list",false]],"list() (select_ai.agent.asynctool class method)":[[4,"select_ai.agent.AsyncTool.list",false]],"list() (select_ai.agent.task class method)":[[3,"select_ai.agent.Task.list",false]],"list() (select_ai.agent.team class method)":[[3,"select_ai.agent.Team.list",false]],"list() (select_ai.agent.tool class method)":[[3,"select_ai.agent.Tool.list",false]],"list() (select_ai.asyncprofile class method)":[[5,"select_ai.AsyncProfile.list",false]],"list() (select_ai.profile class method)":[[12,"select_ai.Profile.list",false]],"narrate() (select_ai.asyncprofile method)":[[5,"select_ai.AsyncProfile.narrate",false]],"narrate() (select_ai.profile method)":[[12,"select_ai.Profile.narrate",false]],"profile (class in select_ai)":[[12,"select_ai.Profile",false]],"run() (select_ai.agent.asyncteam method)":[[4,"select_ai.agent.AsyncTeam.run",false]],"run() (select_ai.agent.team method)":[[3,"select_ai.agent.Team.run",false]],"run_pipeline() (select_ai.asyncprofile method)":[[5,"select_ai.AsyncProfile.run_pipeline",false]],"run_sql() (select_ai.asyncprofile method)":[[5,"select_ai.AsyncProfile.run_sql",false]],"run_sql() (select_ai.profile method)":[[12,"select_ai.Profile.run_sql",false]],"set_attribute() (select_ai.agent.agent method)":[[3,"select_ai.agent.Agent.set_attribute",false]],"set_attribute() (select_ai.agent.asyncagent method)":[[4,"select_ai.agent.AsyncAgent.set_attribute",false]],"set_attribute() (select_ai.agent.asynctask method)":[[4,"select_ai.agent.AsyncTask.set_attribute",false]],"set_attribute() (select_ai.agent.asyncteam method)":[[4,"select_ai.agent.AsyncTeam.set_attribute",false]],"set_attribute() (select_ai.agent.asynctool method)":[[4,"select_ai.agent.AsyncTool.set_attribute",false]],"set_attribute() (select_ai.agent.task method)":[[3,"select_ai.agent.Task.set_attribute",false]],"set_attribute() (select_ai.agent.team method)":[[3,"select_ai.agent.Team.set_attribute",false]],"set_attribute() (select_ai.agent.tool method)":[[3,"select_ai.agent.Tool.set_attribute",false]],"set_attribute() (select_ai.asyncprofile method)":[[5,"select_ai.AsyncProfile.set_attribute",false]],"set_attribute() (select_ai.profile method)":[[12,"select_ai.Profile.set_attribute",false]],"set_attributes() (select_ai.agent.agent method)":[[3,"select_ai.agent.Agent.set_attributes",false]],"set_attributes() (select_ai.agent.asyncagent method)":[[4,"select_ai.agent.AsyncAgent.set_attributes",false]],"set_attributes() (select_ai.agent.asynctask method)":[[4,"select_ai.agent.AsyncTask.set_attributes",false]],"set_attributes() (select_ai.agent.asyncteam method)":[[4,"select_ai.agent.AsyncTeam.set_attributes",false]],"set_attributes() (select_ai.agent.asynctool method)":[[4,"select_ai.agent.AsyncTool.set_attributes",false]],"set_attributes() (select_ai.agent.task method)":[[3,"select_ai.agent.Task.set_attributes",false]],"set_attributes() (select_ai.agent.team method)":[[3,"select_ai.agent.Team.set_attributes",false]],"set_attributes() (select_ai.agent.tool method)":[[3,"select_ai.agent.Tool.set_attributes",false]],"set_attributes() (select_ai.asyncprofile method)":[[5,"select_ai.AsyncProfile.set_attributes",false]],"set_attributes() (select_ai.profile method)":[[12,"select_ai.Profile.set_attributes",false]],"show_prompt() (select_ai.asyncprofile method)":[[5,"select_ai.AsyncProfile.show_prompt",false]],"show_prompt() (select_ai.profile method)":[[12,"select_ai.Profile.show_prompt",false]],"show_sql() (select_ai.asyncprofile method)":[[5,"select_ai.AsyncProfile.show_sql",false]],"show_sql() (select_ai.profile method)":[[12,"select_ai.Profile.show_sql",false]],"summarize() (select_ai.asyncprofile method)":[[5,"select_ai.AsyncProfile.summarize",false]],"summarize() (select_ai.profile method)":[[12,"select_ai.Profile.summarize",false]],"task (class in select_ai.agent)":[[3,"select_ai.agent.Task",false]],"taskattributes (class in select_ai.agent)":[[3,"select_ai.agent.TaskAttributes",false]],"team (class in select_ai.agent)":[[3,"select_ai.agent.Team",false]],"teamattributes (class in select_ai.agent)":[[3,"select_ai.agent.TeamAttributes",false]],"tool (class in select_ai.agent)":[[3,"select_ai.agent.Tool",false]],"toolattributes (class in select_ai.agent)":[[3,"select_ai.agent.ToolAttributes",false]],"toolparams (class in select_ai.agent)":[[3,"select_ai.agent.ToolParams",false]],"translate() (select_ai.asyncprofile method)":[[5,"select_ai.AsyncProfile.translate",false]],"translate() (select_ai.profile method)":[[12,"select_ai.Profile.translate",false]]},"objects":{"select_ai":[[14,0,1,"","AWSProvider"],[14,0,1,"","AnthropicProvider"],[7,0,1,"","AsyncConversation"],[5,0,1,"","AsyncProfile"],[17,0,1,"","AsyncVectorIndex"],[14,0,1,"","AzureProvider"],[12,0,1,"","BaseProfile"],[14,0,1,"","CohereProvider"],[7,0,1,"","Conversation"],[7,0,1,"","ConversationAttributes"],[14,0,1,"","GoogleProvider"],[14,0,1,"","HuggingFaceProvider"],[14,0,1,"","OCIGenAIProvider"],[14,0,1,"","OpenAIProvider"],[17,0,1,"","OracleVectorIndexAttributes"],[12,0,1,"","Profile"],[13,0,1,"","ProfileAttributes"],[14,0,1,"","Provider"],[16,0,1,"","SyntheticDataAttributes"],[16,0,1,"","SyntheticDataParams"],[17,0,1,"","VectorIndex"],[17,0,1,"","VectorIndexAttributes"]],"select_ai.AsyncConversation":[[7,1,1,"","create"],[7,1,1,"","delete"],[7,1,1,"","fetch"],[7,1,1,"","get_attributes"],[7,1,1,"","list"],[7,1,1,"","set_attributes"]],"select_ai.AsyncProfile":[[5,1,1,"","add_negative_feedback"],[5,1,1,"","add_positive_feedback"],[5,1,1,"","chat"],[5,1,1,"","chat_session"],[5,1,1,"","create"],[5,1,1,"","delete"],[5,1,1,"","delete_feedback"],[5,1,1,"","delete_profile"],[5,1,1,"","explain_sql"],[5,1,1,"","fetch"],[5,1,1,"","generate"],[5,1,1,"","generate_synthetic_data"],[5,1,1,"","get_attributes"],[5,1,1,"","list"],[5,1,1,"","narrate"],[5,1,1,"","run_pipeline"],[5,1,1,"","run_sql"],[5,1,1,"","set_attribute"],[5,1,1,"","set_attributes"],[5,1,1,"","show_prompt"],[5,1,1,"","show_sql"],[5,1,1,"","summarize"],[5,1,1,"","translate"]],"select_ai.AsyncVectorIndex":[[17,1,1,"","create"],[17,1,1,"","delete"],[17,1,1,"","delete_index"],[17,1,1,"","disable"],[17,1,1,"","enable"],[17,1,1,"","fetch"],[17,1,1,"","get_attributes"],[17,1,1,"","get_next_refresh_timestamp"],[17,1,1,"","get_profile"],[17,1,1,"","list"],[17,1,1,"","set_attribute"],[17,1,1,"","set_attributes"]],"select_ai.Conversation":[[7,1,1,"","create"],[7,1,1,"","delete"],[7,1,1,"","fetch"],[7,1,1,"","get_attributes"],[7,1,1,"","list"],[7,1,1,"","set_attributes"]],"select_ai.Profile":[[12,1,1,"","add_negative_feedback"],[12,1,1,"","add_positive_feedback"],[12,1,1,"","chat"],[12,1,1,"","chat_session"],[12,1,1,"","create"],[12,1,1,"","delete"],[12,1,1,"","delete_feedback"],[12,1,1,"","delete_profile"],[12,1,1,"","explain_sql"],[12,1,1,"","fetch"],[12,1,1,"","generate"],[12,1,1,"","generate_synthetic_data"],[12,1,1,"","get_attributes"],[12,1,1,"","list"],[12,1,1,"","narrate"],[12,1,1,"","run_sql"],[12,1,1,"","set_attribute"],[12,1,1,"","set_attributes"],[12,1,1,"","show_prompt"],[12,1,1,"","show_sql"],[12,1,1,"","summarize"],[12,1,1,"","translate"]],"select_ai.VectorIndex":[[17,1,1,"","create"],[17,1,1,"","delete"],[17,1,1,"","delete_index"],[17,1,1,"","disable"],[17,1,1,"","enable"],[17,1,1,"","fetch"],[17,1,1,"","get_attributes"],[17,1,1,"","get_next_refresh_timestamp"],[17,1,1,"","get_profile"],[17,1,1,"","list"],[17,1,1,"","set_attribute"],[17,1,1,"","set_attributes"]],"select_ai.agent":[[3,0,1,"","Agent"],[3,0,1,"","AgentAttributes"],[4,0,1,"","AsyncAgent"],[4,0,1,"","AsyncTask"],[4,0,1,"","AsyncTeam"],[4,0,1,"","AsyncTool"],[3,0,1,"","Task"],[3,0,1,"","TaskAttributes"],[3,0,1,"","Team"],[3,0,1,"","TeamAttributes"],[3,0,1,"","Tool"],[3,0,1,"","ToolAttributes"],[3,0,1,"","ToolParams"]],"select_ai.agent.Agent":[[3,1,1,"","create"],[3,1,1,"","delete"],[3,1,1,"","delete_agent"],[3,1,1,"","disable"],[3,1,1,"","enable"],[3,1,1,"","fetch"],[3,1,1,"","list"],[3,1,1,"","set_attribute"],[3,1,1,"","set_attributes"]],"select_ai.agent.AsyncAgent":[[4,1,1,"","create"],[4,1,1,"","delete"],[4,1,1,"","delete_agent"],[4,1,1,"","disable"],[4,1,1,"","enable"],[4,1,1,"","fetch"],[4,1,1,"","list"],[4,1,1,"","set_attribute"],[4,1,1,"","set_attributes"]],"select_ai.agent.AsyncTask":[[4,1,1,"","create"],[4,1,1,"","delete"],[4,1,1,"","delete_task"],[4,1,1,"","disable"],[4,1,1,"","enable"],[4,1,1,"","fetch"],[4,1,1,"","list"],[4,1,1,"","set_attribute"],[4,1,1,"","set_attributes"]],"select_ai.agent.AsyncTeam":[[4,1,1,"","create"],[4,1,1,"","delete"],[4,1,1,"","delete_team"],[4,1,1,"","disable"],[4,1,1,"","enable"],[4,1,1,"","fetch"],[4,1,1,"","list"],[4,1,1,"","run"],[4,1,1,"","set_attribute"],[4,1,1,"","set_attributes"]],"select_ai.agent.AsyncTool":[[4,1,1,"","create"],[4,1,1,"","create_built_in_tool"],[4,1,1,"","create_email_notification_tool"],[4,1,1,"","create_pl_sql_tool"],[4,1,1,"","create_rag_tool"],[4,1,1,"","create_slack_notification_tool"],[4,1,1,"","create_sql_tool"],[4,1,1,"","create_websearch_tool"],[4,1,1,"","delete"],[4,1,1,"","delete_tool"],[4,1,1,"","disable"],[4,1,1,"","enable"],[4,1,1,"","fetch"],[4,1,1,"","list"],[4,1,1,"","set_attribute"],[4,1,1,"","set_attributes"]],"select_ai.agent.Task":[[3,1,1,"","create"],[3,1,1,"","delete"],[3,1,1,"","delete_task"],[3,1,1,"","disable"],[3,1,1,"","enable"],[3,1,1,"","fetch"],[3,1,1,"","list"],[3,1,1,"","set_attribute"],[3,1,1,"","set_attributes"]],"select_ai.agent.Team":[[3,1,1,"","create"],[3,1,1,"","delete"],[3,1,1,"","delete_team"],[3,1,1,"","disable"],[3,1,1,"","enable"],[3,1,1,"","fetch"],[3,1,1,"","list"],[3,1,1,"","run"],[3,1,1,"","set_attribute"],[3,1,1,"","set_attributes"]],"select_ai.agent.Tool":[[3,1,1,"","create_built_in_tool"],[3,1,1,"","create_email_notification_tool"],[3,1,1,"","create_pl_sql_tool"],[3,1,1,"","create_rag_tool"],[3,1,1,"","create_slack_notification_tool"],[3,1,1,"","create_sql_tool"],[3,1,1,"","create_websearch_tool"],[3,1,1,"","delete"],[3,1,1,"","delete_tool"],[3,1,1,"","disable"],[3,1,1,"","enable"],[3,1,1,"","fetch"],[3,1,1,"","list"],[3,1,1,"","set_attribute"],[3,1,1,"","set_attributes"]],"select_ai.summary":[[15,0,1,"","ChunkProcessingMethod"],[15,0,1,"","ExtractivenessLevel"],[15,0,1,"","Style"],[15,0,1,"","SummaryParams"]]},"objnames":{"0":["py","class","Python class"],"1":["py","method","Python method"]},"objtypes":{"0":"py:class","1":"py:method"},"terms":{"":[0,1,5,7,9,12,14,16,17],"0":[1,5,7,12,17],"01":[3,4],"02":[3,4],"03":[3,4],"04":[3,4],"05":[3,4],"06":[3,4],"07":[3,4],"07b9":[3,4],"08":[3,4],"09":[3,4],"1":[1,3,4,5,7,12,17],"10":[3,4,6,7,9,10,16],"100":[3,4,16],"1024":[5,12,13,17],"11":[9,10],"11c8":7,"12":[9,10],"128":17,"128e":[3,4],"13":[9,10,16],"14":9,"1450":17,"151b000ad3b4":7,"17b":[3,4],"2":[3,4,5,17],"20000":5,"2019":[3,4,16],"2025":1,"25e23a25":[3,4],"3":[3,4,5,9,10,17],"300":16,"37ddc22e":7,"37df777f":7,"380a1910":7,"3ab2ed3":7,"3d49":7,"4":[3,4,5,17],"40":16,"400":[5,12],"40e7":[3,4],"463a":[3,4],"4ed7":[3,4],"5":[3,4,5,6,16,17],"503":[5,12],"5275a80":7,"55":[5,12],"5bf2":7,"6":[3,4],"7":[3,4,7],"7e52":7,"8":[3,4],"80":9,"8000":7,"9":[3,4,9,10],"987c":[3,4],"A":[1,3,4,5,12,17],"AND":1,"AS":[1,5,12],"BE":1,"BUT":1,"By":7,"FOR":1,"For":[3,5,6,9,12,16,17],"IN":1,"If":[3,4,7,9],"In":[3,4,8,17],"It":[0,5,10,12,15],"NO":1,"NOT":1,"No":[3,4],"OF":1,"OR":1,"THE":1,"TO":1,"The":[1,3,4,5,7,8,10,12,13,14,15,16,17],"There":12,"These":[3,4,14,17],"To":[5,6,9,14,17],"WITH":1,"_":1,"_required_field":[3,4],"a290":7,"a489":[3,4],"abil":7,"about":[3,4,5,12,17],"abov":1,"abstract":12,"access":[2,3,4,5,12,13,14,17],"accomplish":[3,4],"accuraci":2,"acl":14,"acquir":[5,12],"act":[2,3,4],"action":[1,3,4,5,12],"activ":17,"actor":[3,4,16],"actual":[5,12],"ad":17,"add":[3,14],"add_negative_feedback":[0,5,12],"add_positive_feedback":[0,5,12],"addit":[3,4,6],"addition":[5,12],"adjac":17,"admin":11,"admin_us":[11,14],"administr":5,"advanc":[3,4],"adventur":[3,4],"affili":1,"after":[5,12],"agent_attribut":[3,4],"agent_nam":[3,4],"agent_name_pattern":[3,4],"agentattribut":[0,3,4],"agentnotfounderror":[3,4],"agenttasknotfounderror":[3,4],"agentteamnotfounderror":[3,4],"agenttoolnotfounderror":[3,4],"agreement":1,"ai":[1,5,7,11,12,13,17],"alcohol":[5,12],"algorithm":[3,4],"alia":5,"all":[1,3,4,5,7,11,12,13,17],"allow":[3,4,5,14],"along":[6,17],"alreadi":9,"also":[3,4,5,12,14,16,17],"amazon":12,"amount":[5,12,17],"an":[1,2,3,4,5,6,7,12,13,14,17],"analyst":[3,4],"analyt":[3,4,5,12],"analyz":[3,4,5],"analyze_movie_task":[3,4],"ancient":[5,12],"ani":[1,3,4,9,14],"anim":[3,4],"annot":[5,12,13,17],"anomali":[3,4],"anoth":2,"answer":[3,4,5],"anthrop":[8,14],"anthropicprovid":0,"api":[0,3,9,10,13],"applic":[3,4,5,6],"appreci":7,"approxim":15,"ar":[3,4,5,7,9,12,13,14,15,16,17],"area":[5,12],"arg":[5,12],"argument":[3,4],"aris":1,"arrai":[3,13],"artifici":[3,4,5],"as_complet":5,"ashburn":17,"ask":3,"assign":[3,16],"associ":[1,3,4,5,17],"astrobiologi":[5,12],"astronom":[5,12],"astronomi":[5,12],"async":[0,6,9],"async_connect":[4,5,6,7,8,14,16,17],"async_convers":7,"async_create_credenti":[4,8],"async_grant_http_access":14,"async_oci_ai_profil":[5,7,12,16],"async_oci_vector_ai_profil":[12,17],"async_profil":[5,7,16,17],"async_revoke_http_access":14,"async_sess":7,"async_vector_index":17,"asyncag":[0,3],"asyncconvers":[0,5],"asyncgener":[4,5,7,17],"asynchron":[0,4,10,12],"asyncio":[4,5,7,8,14,16,17],"asyncprofil":[0,4,7,12,16,17],"asynctask":[0,3],"asyncteam":[0,3],"asynctool":[0,3],"asyncvectorindex":0,"attach":3,"attribut":[3,4,5,7,12,13,14,16],"attribute_nam":[3,4,5,12,17],"attribute_valu":[3,4,5,12,17],"augment":[10,17],"authent":[5,8,12],"author":1,"autom":[3,4,5,13],"automat":[3,9],"automl":[3,4],"autonom":[3,5],"avail":[9,15],"aw":[12,14],"await":[4,5,6,7,8,14,16,17],"awar":[5,7,12],"aws_apiformat":14,"awsprovid":0,"azur":[12,14],"azure_deployment_nam":14,"azure_embedding_deployment_nam":14,"azure_resource_nam":14,"azureprovid":0,"b":[1,17],"b2":[5,12],"back":12,"base":[0,3,4,5,6,10,14,17],"baseprofil":[0,12,17],"be11":[3,4],"be1a000a15b6":7,"becom":[5,12],"beer":[5,12],"befor":[5,11],"begin":13,"behavior":[2,3,13,17],"behind":9,"being":[5,12,14],"below":[1,6,16,17],"benefit":[3,4,6],"better":9,"between":[0,7,17],"biograph":[3,4],"biographi":[3,4],"block":[12,14,17],"blog":6,"bool":[3,4,5,7,12,13,16,17],"both":[1,10,14,17],"branch":[5,12],"breakdown":5,"brew":[5,12],"bridg":0,"bucket":17,"build":[3,4,5,7,17],"built":[3,4,12],"burn":[5,12],"busi":[3,4,5],"c":[1,5],"c2e3ff20":[3,4],"calcul":[5,17],"call":[3,14],"callabl":3,"can":[2,3,4,5,6,7,9,12,14,15,17],"cancri":[5,12],"cannot":17,"capabl":[0,3,4],"case":[5,14],"case_sensitive_valu":[5,12,13,17],"cc72740c75a5":[3,4],"celesti":[5,12],"certain":3,"chain":3,"challeng":7,"channel":[3,4],"charact":17,"charg":1,"chat":[0,2],"chat_sess":[0,5,7,12],"chat_task":5,"chatgpt":[3,4],"check":[6,16,17],"chemistri":[5,12],"chicago":[3,4,5,12,17],"choic":17,"choos":[3,15],"chunk":[15,17],"chunk_overlap":17,"chunk_processing_method":15,"chunk_siz":17,"chunkprocessingmethod":0,"civil":[5,12],"claim":1,"clarif":3,"clarifi":2,"class":[3,4,5,7,12,13,14,15,16,17],"classif":[3,4],"classmethod":[3,4,5,7,12,17],"clear":[3,4],"climat":7,"close":15,"cloud":[3,4,5,12,14],"clue":[5,12],"cluster":[3,4,14],"coher":[14,17],"cohereprovid":0,"collect":[1,5,17],"column":[3,5,12,13],"com":[3,4,9,14,17],"combin":7,"comedi":[3,4],"comment":[3,5,12,13,16,17],"compar":17,"compart":14,"compet":12,"complet":[1,16],"complianc":[3,4],"compliant":[3,4],"compon":5,"compos":3,"composit":[3,5,12],"comprehens":[7,12],"comput":[5,12],"concept":14,"concis":[3,4],"concret":14,"concurr":[0,10,12,17],"conda":17,"condit":1,"config":8,"configur":[3,13,17],"connect":[0,1,3,4,7,8,9,11,12,14,16,17],"consid":17,"constantli":[5,12],"constraint":[5,12,13,17],"consum":16,"contain":[3,4,5,12,15,17],"content":[2,3,4,5,12,17],"context":[3,5,7,12],"contextu":7,"continu":[3,4,5],"continue_on_error":5,"contract":1,"contribut":1,"control":[15,16],"convers":[2,3,4,5,12,13,17],"conversation_attribut":7,"conversation_id":[3,4,5,7,12],"conversation_length":7,"conversationattribut":0,"convert":[14,17],"cool":[5,12],"coordin":3,"copi":1,"copyright":1,"corpor":[5,12],"correct":5,"correspond":[5,8,12],"cosin":17,"could":[3,4,5,12],"count":[5,12,16],"cover":[1,13],"creat":[0,1,5,6,9,11,13,14],"create_built_in_tool":[3,4],"create_credenti":[3,8],"create_email_notification_tool":[3,4],"create_http_tool":[3,4],"create_pl_sql_tool":[3,4],"create_pool":6,"create_pool_async":6,"create_rag_tool":[3,4],"create_slack_notification_tool":[3,4],"create_sql_tool":[3,4],"create_tool":3,"create_websearch_tool":[3,4],"creation":[0,3,4,7,12,17],"credenti":[3,4,5,12,13,17],"credential_nam":[3,4,5,8,12,13,17],"cultur":7,"current":[3,4,17],"cust_email":5,"cust_first_nam":5,"cust_id":5,"cust_last_nam":5,"custom":[3,4,5,15,17],"customer_count":5,"d4328a7b2210":[3,4],"d81a000a3fda":7,"d81a000a53b":7,"d81a000a85f":7,"d917b055":[3,4],"da17":7,"dai":7,"damag":1,"dank":[5,12],"data":[1,2,3,4,5,10,12,14,17],"data_guard":3,"databas":[0,3,4,5,7,8,9,11,12,14,16,17],"databaseerror":[5,12,17],"datafram":[5,12],"date":[3,4,7,16],"datetim":[7,17],"db_admin":11,"db_admin_password":11,"db_connect_str":11,"dba":5,"dbms_cloud":11,"dbms_cloud_ai":[0,10,11],"dbms_cloud_ai_ag":[3,11],"dbms_cloud_pipelin":11,"de":[5,12],"deal":1,"dedic":14,"deep":2,"def":[4,5,7,8,14,16,17],"default":[2,3,4,5,8,12,13,16,17],"default_config":8,"defin":[1,3,5,12,13,16,17],"degre":[13,15],"delet":[0,3,4,5,12],"delete_ag":[0,3,4],"delete_feedback":[0,5,12],"delete_index":[0,17],"delete_profil":[0,5,12],"delete_task":[0,3,4],"delete_team":[0,3,4],"delete_tool":[3,4],"denot":13,"depend":[3,5,9,14],"deploi":[3,4,5,14],"deploy":[3,4],"deriv":1,"describ":[3,4,5,12],"descript":[2,3,4,5,7,12,17],"design":[3,5],"despit":[5,12],"detail":[2,11,12,16],"detect":[3,4,5,12],"determin":15,"develop":[3,4,5,7,12],"df":[5,12],"dict":[5,12],"dictionari":3,"differ":[2,3],"dir_containing_tnsnam":11,"directli":[3,4],"director":[3,4,16],"disabl":[0,3,4,16,17],"discoveri":[5,7,12],"displai":[1,2],"distanc":17,"distribut":1,"do":[3,4],"document":[1,11,17],"documentari":[3,4],"doe":[5,12,17],"doesn":5,"dotenv":11,"doubl":5,"drama":[3,4],"drive":5,"driver":6,"drop":7,"dsn":[3,4,5,6,7,8,9,11,12,14,16,17],"dtype":12,"due":[5,12],"dure":3,"dwcsdev":17,"dynam":[5,12],"e":[3,4,5,6,12,16,17],"e063":7,"e8a1":[3,4],"each":[1,3,17],"earli":[5,12],"earliest":13,"easier":5,"ecosystem":0,"effici":5,"either":[1,3,12,17],"elabor":7,"element":[5,12,17],"elig":13,"elimin":[3,4,5],"els":[5,12],"email":[3,4,5],"emb":17,"embed":[14,17],"embedding_model":[5,12,14,17],"empti":12,"en":[5,12],"enabl":[0,2,3,4,5,7,13,15,16,17],"enable_custom_source_uri":[13,17],"enable_human_tool":[3,4],"enable_sourc":[5,12,13,17],"enable_source_offset":[5,12,13,17],"enclos":5,"end":[1,5,12],"endpoint":[3,4,14,17],"enforce_object_list":[5,12,13,17],"english":17,"enhanc":[3,4],"enough":[5,12],"ensur":[3,4,5],"enter":9,"enum":2,"enumer":5,"env":11,"environ":[3,4,11,17],"epic":[3,4],"error":[3,4,5,7,12,17],"essenti":7,"even":[5,12],"event":[1,5,9,12],"evolut":[5,12],"evolv":[5,12],"exampl":[0,5,7,8,9,16,17],"exce":15,"exchang":7,"exclude_nul":[5,12],"execut":[2,3,5,6,11],"exist":[3,4,5,12,17],"exoplanet":[5,12],"expans":[5,12],"expect":[5,12,14,15],"expertis":2,"explain":[0,2,12],"explain_sql":[0,5,12],"explainsql":[2,5],"explan":5,"explicitli":5,"explor":2,"export":[1,11],"express":[1,3,4,5,12,17],"extern":3,"extract":15,"extractiveness_level":15,"extractivenesslevel":0,"extraterrestri":[5,12],"f":5,"f084":7,"f3da":7,"f56d":[3,4],"f7a1":7,"f7e5e445d286":[3,4],"fals":[3,4,5,7,12,16,17],"famili":[3,4],"fantasi":[3,4],"fastapi":6,"faster":16,"fccenv":17,"featur":[3,4,10],"februari":[3,4],"feedback":[2,5,12],"feedback_cont":[5,12],"fetch":[0,3,4,5,7,12],"fetched_profil":[5,12],"fewer":5,"fi":[3,4],"field":[3,5,12],"file":[1,5,8,9,11,12],"filenam":17,"film":[3,4],"find":7,"fingerprint":8,"first":[5,12],"fit":1,"flexibl":[3,4],"float":[5,12,13,17],"focu":5,"focus":[3,4,5,12],"follow":[1,2,3,4,8,11,15,17],"forc":[3,4,5,7,12,17],"forego":1,"foreign":13,"form":[5,12],"format":[5,12,13,14,15],"forth":1,"found":[3,4,5,12],"fp":8,"fp8":[3,4],"framework":[3,4],"free":1,"freeli":1,"from":[1,2,3,4,5,7,8,9,11,12,13,15,16,17],"from_fil":8,"fulfil":3,"full":[5,12],"fulli":17,"function":[3,4,5,12,17],"g":[5,12,16,17],"ga":[5,12],"gain":7,"galaxi":[5,12],"gamma":[5,12],"gap":0,"gcp":12,"gen":[8,14],"gener":[0,2,3,4,5,10,12,13,14,15,16,17],"generate_synthetic_data":[0,5,12,16],"genr":[3,4],"get":[5,7,12,17],"get_attribut":[0,5,7,12,17],"get_next_refresh_timestamp":[0,17],"get_profil":[0,17],"getenv":[3,4,5,7,8,11,12,14,16,17],"give":[5,12],"googl":[12,14],"googleprovid":0,"govern":[3,4],"gpt":0,"grant":[0,1],"grant_http_access":14,"grant_privileg":11,"graph":17,"graphenv":17,"gravit":[5,12],"group":3,"guid":[3,5,12,16],"ha":[5,12],"halo":[5,12],"hardwar":1,"have":[1,5,7],"help":[3,4,7,10,17],"here":[3,4,5,7],"herebi":1,"hereund":1,"hf":8,"hf_xxx":8,"high":[3,4,5,12,15,16],"higher":[5,9,16],"highlight":[3,4,14],"histor":[3,4],"histori":[5,7,12,13],"holder":1,"horror":[3,4],"host":[3,4,14],"hot":[5,12],"how":[3,4,5,12,15,17],"http":[3,4,5,9,12,14,17],"https_proxi":6,"https_proxy_port":6,"huggingfac":[8,14],"huggingfaceprovid":0,"human":[3,4],"hyperparamet":[3,4],"i":[0,1,2,3,4,5,6,7,9,10,12,13,15,16,17],"ibm":12,"ic":[5,12],"id":[3,4,5,7],"identifi":[3,4,5,12],"ignor":[5,12,17],"ii":1,"impact":7,"implement":14,"impli":1,"import":[1,3,4,5,6,7,8,9,11,12,14,16,17],"improv":[2,3,4],"includ":[1,3,4,5,7,12,13],"include_data":17,"incorpor":13,"increment":6,"index":[3,4,12,13],"index_nam":17,"index_name_pattern":17,"indic":[13,14,17],"inform":[3,4,16,17],"infrar":[5,12],"infrastructur":[3,4,5,12],"inherit":[3,4],"inlin":[5,12],"input":[3,4,15,17],"insid":[3,4],"insight":[5,7,12],"inspir":[5,12],"instal":0,"instanti":12,"instruct":[2,3,4],"int":[5,7,12,13,15,16,17],"integr":[0,3,4,5,13],"intellectu":7,"intellig":[3,4,5],"intend":3,"interact":[5,7,12],"interfac":[4,5],"interpret":14,"interv":17,"introduc":9,"introduct":0,"invalid":5,"invok":[3,4,10,14],"item":[3,4,17],"iter":[3,4,5,7,12,17],"iterative_refin":15,"its":[1,3,4,5,7,12],"januari":[3,4],"job":17,"json":[13,17],"keep":[3,4],"kei":[3,4,7,8,13,15],"kept":5,"key_cont":8,"key_fil":8,"keyword":[2,4,5,6],"kind":1,"knowledg":7,"known":14,"kwarg":[5,12],"languag":[2,3,4,5,7,12,13,14,17],"larg":[2,5,12],"larger":[1,5],"last":5,"layer":[3,4],"learn":[3,4,5,7],"led":[5,12],"less":13,"let":[3,4,17],"level":[5,17],"leverag":[3,4,5],"li":7,"liabil":1,"liabl":1,"licens":1,"licensor":1,"life":[5,12],"like":[3,4,6],"limit":[1,15],"link":[3,4,17],"list":[0,1,2,13,15,16],"llama":[3,4,14],"llama_4_maverick":[3,4],"llm":[2,3,4,5,7,12,13,14,15,16],"llm_chat_tool":[3,4],"load":17,"local":[5,12],"locat":17,"location_uri":[5,12],"long":[5,12],"loop":9,"low":[15,16],"lower":13,"lrgrwrk":1,"m":[6,9],"machin":[3,4,5],"made":[1,7],"main":[3,4,5,7,8,14,16,17],"maintain":[3,4],"major":12,"make":[1,2,5,12],"manag":[5,9,13,15,17],"mani":[5,12],"manifest":17,"manipul":5,"manner":[5,7],"manual":[5,7],"map":[3,4,5,12,13,16],"map_reduc":15,"mapped_sql":[5,12],"match":[3,4,5,12,17],"match_limit":17,"mathemat":[5,12],"maverick":[3,4],"max_siz":6,"max_token":[5,12,13,17],"max_word":15,"maximum":[15,17],"mean":13,"meant":3,"meanwhil":[5,12],"medium":[15,16],"merchant":1,"merg":12,"messag":9,"meta":[3,4],"metadata":[12,13],"method":[3,4,5,6,11,12,14,15,17],"microsoft":12,"milki":[5,12],"min_siz":6,"min_word":15,"minimum":[1,15,17],"minut":17,"misconcept":7,"mission":[3,4],"mistak":7,"ml":[3,4,5],"mlenv":17,"model":[0,5,14,15],"modul":[0,10],"more":[3,4,5,7,12,15,16],"most":13,"move":[3,4],"movement":[3,4],"movi":[3,4,16],"movie_agent_team":[3,4],"movie_analyst":[3,4],"movie_sql_tool":[3,4],"much":[5,12],"multi":[0,3],"multipl":[3,4,5,12,16,17],"multit":16,"music":[3,4],"must":[1,3,13,15],"my":[3,4,5,12,17],"my_oci_ai_profile_kei":[3,4,5,8,12,17],"myrenv":17,"mysteri":[3,4,5,12],"n":17,"nad":5,"name":[3,4,5,12,13,14,16,17],"narrat":[0,2,5,17],"natur":[2,3,4,5,7,12,13,14,17],"need":[3,4,5,9],"neg":[5,12,13],"network":[5,12],"new":[3,4,5,7,12,17],"next":[5,17],"night":[3,4,5,12],"non":[12,13,17],"none":[3,4,5,7,12,13,14,15,16,17],"noninfring":1,"note":5,"notic":1,"notif":[3,4],"notification_typ":[3,4],"notificationtyp":3,"null":12,"number":[5,7,12,13,15,16,17],"number_of_promot":5,"numer":[5,12],"o":[3,4,5,7,8,11,12,14,16,17],"object":[0,3,4,5,8,13,14,16],"object_list":[3,4,5,12,13,16,17],"object_list_mod":[5,12,13,17],"object_nam":16,"object_storage_credential_nam":17,"objectstor":17,"objectstorag":17,"observ":[5,12],"obtain":1,"occur":[7,17],"oci":[3,4,5,8,12,14,17],"oci_ai_profil":[3,4,5,7,12,16],"oci_apiformat":[3,4,5,12,14,17],"oci_compartment_id":[5,12,14,17],"oci_endpoint_id":[5,12,14,17],"oci_runtimetyp":[5,12,14,17],"oci_vector_ai_profil":[5,12,17],"ocid":14,"ocigenaiprovid":[0,3,4,5,12,17],"offer":[1,3,4,5,12,14],"older":[5,12],"omf":5,"oml":5,"oml4pi":5,"one":[1,2,3,4,5,14,15],"onli":[3,13],"open":[3,4,8],"open_ai_api_kei":[3,4],"open_ai_credential_nam":[3,4],"open_ai_profile_nam":[3,4],"openai":[0,8,14],"openai_cr":[3,4],"openai_profil":[3,4],"openaiprovid":[0,3,4],"operation":[3,4],"optic":[5,12],"option":[3,4,9,15,16],"ora":[5,11],"oracl":[0,1,3,4,5,8,10,11,12,14,17],"oraclecloud":17,"oracledb":[5,6,9,12,17],"oraclevectorindexattribut":0,"orchestr":3,"order":3,"org":[5,12],"organ":[3,4],"origin":[5,12,15],"ot":4,"other":[1,10,11,12],"otherwis":1,"our":[5,12],"out":1,"outlin":3,"output":[2,3,4,5,7,8,11,12,14,16,17],"outsid":[3,4],"over":[3,7],"overal":[5,12],"overlap":17,"own":[1,16],"owner":[3,4,5,12,13,16],"owner_nam":16,"p":[5,12],"packag":[0,3,9,11],"page":[3,4],"pair":[3,4],"panda":[5,9,12],"paragraph":15,"parallel":16,"param":[3,4,5,12,16],"paramet":[3,4,5,6,7,12,13,14,15,16,17],"parti":10,"particular":1,"pass":[3,4,6,17],"password":[3,4,5,6,7,8,9,11,12,14,16,17],"past":7,"patent":1,"path":[5,11,12],"pattern":[3,4,5,12,17],"paus":[3,4],"pdb3":17,"per":13,"perform":[1,2,3,4,5,12,17],"permiss":1,"permit":14,"persist":3,"person":1,"pformat":[3,4,5,12],"phenomena":[5,12],"physic":[5,12],"piec":1,"pint":[5,12],"pip":9,"pipelin":[0,12],"pipeline_nam":17,"pitfal":7,"pl":[0,3,4,6,16],"placehold":[3,4],"platform":12,"point":15,"pool":0,"popul":[16,17],"portion":1,"posit":[5,12],"possibl":16,"potenti":2,"power":5,"pprint":[3,4,5,12],"prebuilt":[3,4],"predict":[3,4],"present":15,"pressur":[5,12],"prevent":[5,12],"previou":[3,4],"previous":17,"primari":13,"primarili":[3,4],"print":[3,4,5,7,8,9,11,12,14,17],"prior":3,"prioriti":16,"privaci":[3,4],"private_kei":8,"procedur":[3,4,17],"process":[3,4,14,15],"product":[3,4,5],"profil":[3,4,7,8,13,16,17],"profile_attribut":[3,4,5,12,17],"profile_nam":[3,4,5,7,12,16,17],"profile_name_pattern":[5,12],"profileattribut":[0,3,4,5,12,17],"profileemptyattributeserror":12,"profileexistserror":12,"profilenotfounderror":[5,12,17],"program":[5,10],"promo_id":[5,12],"promot":[3,4,5,12],"promotion_count":5,"prompt":[2,3,4,5,7,9,12,13,14,16,17],"prompt_spec":[5,12],"prompt_specif":5,"properti":3,"provid":[1,2,3,4,5,7,10,12,13,17],"provider_endpoint":[5,12,14,17],"provider_nam":[5,12,14,17],"providerattribut":[5,12],"proxi":[3,4,7,9,12,17],"purpos":[1,3],"py":9,"pypi":9,"python":[0,1,3,4,5,6,9,12],"python3":9,"queri":[2,3,4,5,7,13,17],"question":[3,4,5],"quot":5,"r":[3,4,17],"radio":[5,12],"rag":[0,3,4,10],"rai":[5,12],"rais":[3,4,5,12,17],"raise_error_if_exist":12,"raise_error_on_empty_attribut":12,"random":13,"rang":[3,4,5,12],"read":[5,8,11],"reason":[3,4,7],"receiv":14,"recipi":[3,4],"record":16,"record_count":16,"refer":[1,5,14],"referenc":16,"referenti":13,"refresh":17,"refresh_r":17,"regard":12,"regexp_lik":[3,4,5,12,17],"region":[3,4,5,12,14,17],"regist":[3,4],"regress":[3,4],"regular":[3,4,5,12,17],"relat":[3,4],"releas":[3,4,16],"relev":[7,11,13],"remain":[5,12],"remov":[7,14,17],"repair":5,"rephras":15,"replac":[3,4,5,8,12,17],"replet":7,"repositori":9,"repres":[7,12],"request":[3,4,5,12,16,17],"requir":[0,3,4,12,17],"research":[3,4,5,7,12],"resid":[3,4,17],"resourc":[14,16],"respond":[3,4],"respons":[3,4,5,7,12,14],"restrict":[1,13],"result":[2,5,12,17],"resum":[3,4],"retention_dai":7,"retriev":[5,10,17],"return":[3,4,5,7,12,13,17],"revok":0,"revoke_http_access":14,"revoke_privileg":11,"rich":0,"right":1,"robust":[3,4],"role":[3,4],"romanc":[3,4],"round":5,"roundtrip":5,"row":[5,16],"run":[0,7,8,9,11,14,16,17],"run_pipelin":[5,12],"run_sql":[0,5,12],"runsql":[2,12],"runtim":14,"sagittariu":[5,12],"sale":1,"same":3,"sampl":[11,16],"sample_row":16,"save":[5,12],"scalabl":[3,4,5],"scale":[3,4],"schedul":17,"schema":[5,12,16],"sci":[3,4],"scienc":[5,7,12],"scientif":7,"scientist":[3,4,7],"script":[5,11],"seamlessli":[3,4],"search":[0,5,12,17],"second":[5,12],"secur":[3,4,5,8],"see":14,"seed":[5,12,13,17],"seek":[5,12],"select":[0,1,5,7,11,12,14,16,17],"select_ai":[2,3,4,5,6,7,8,10,11,12,13,14,15,16,17],"select_ai_admin_password":[11,14],"select_ai_admin_us":[11,14],"select_ai_agent_nam":[3,4],"select_ai_connection_test":9,"select_ai_db_connect_str":[3,4,5,7,8,11,12,14,16,17],"select_ai_db_password":11,"select_ai_db_us":[11,14],"select_ai_password":[3,4,5,7,8,11,12,16,17],"select_ai_task_nam":[3,4],"select_ai_team_nam":[3,4],"select_ai_tool_nam":[3,4],"select_ai_us":[3,4,5,7,8,11,12,14,16,17],"self":5,"sell":1,"semant":17,"send":[3,5,13,16],"sender":[3,4],"sensit":5,"sent":[2,3,4,5,12,13,14,16],"separ":17,"sequenc":13,"sequenti":[3,4],"seri":[3,4,7],"serv":[3,4],"server":[3,4],"servic":[0,5,6,8,12],"session":[0,3,4,5,12],"set":[1,3,4,5,12],"set_attribut":[0,3,4,5,7,12,17],"sever":[5,7,10],"sh":[5,12],"shall":1,"shape":7,"should":[3,4,5,6,11,16],"show":[0,2,3,4,6,8,16],"show_prompt":[0,5,12],"show_sql":[0,5,12],"shown":[6,9],"showprompt":2,"showsql":[2,5],"signific":7,"similar":[3,17],"similarity_threshold":17,"similarli":11,"simul":5,"sinc":[5,12],"sing":0,"singl":[0,3,4,5,12,17],"size":17,"sk":8,"sky":[5,12],"slack":[3,4],"slack_channel":[3,4],"smtp":[3,4],"smtp_host":[3,4],"so":[3,5,12],"social":7,"societi":7,"softwar":1,"sold":1,"solid":[5,12],"solver":[3,4],"some":[5,7,12],"soon":5,"sourc":[5,11,12,17],"source_languag":[5,12],"special":[3,4],"specif":[3,4,12,14,17],"specifi":[3,4,5,12,13,14,15,17],"speed":[3,4],"split":[5,12,15],"sport":[3,4],"sql":[0,2,3,4,6,10,13,16],"sql_id":[5,12],"sql_task":5,"sql_tool":[3,4],"sqltoolparam":[3,4],"stabil":9,"stand":[5,12],"star":[5,12],"start":[3,4,5,12],"state":[3,4],"statement":[2,3,4,12],"statist":16,"step":[3,4],"stop":13,"stop_token":[5,12,13,17],"storag":[5,12,17],"store":[3,4,5,7,8,12,17],"stori":[3,4],"str":[3,4,5,7,12,13,14,16,17],"strategi":3,"stream":[5,12,13,17],"string":[5,13],"structur":9,"studi":[5,7,12],"style":[0,10,15],"subject":[1,3,4],"sublicens":1,"subprogram":6,"substanti":1,"summar":[0,2],"summari":[2,3,4,5,12,15],"summary_styl":15,"summaryparam":[0,5,12],"summarystyl":0,"sun":[5,12],"support":[0,4,5,10,13,14,17],"sync":[0,6],"synchron":[0,5,10,12],"synthet":[5,10,12],"synthetic_data_attribut":[5,12,16],"synthetic_data_param":16,"syntheticdataattribut":[0,5,12],"syntheticdataparam":0,"system":[7,17],"t":5,"tabl":[0,3,5,8,12,13,17],"table_statist":16,"target":[5,12],"target_languag":[5,12],"task":[0,5,16],"task_nam":[3,4],"task_name_pattern":[3,4],"taskattribut":[0,3,4],"team":0,"team_nam":[3,4],"team_name_pattern":[3,4],"teamattribut":[0,3,4],"technic":2,"technologi":[3,4,5,12],"temperatur":[5,12,13,17],"tenanc":8,"tenancy_ocid":8,"tenant1":17,"term":1,"termin":13,"test":17,"test_vector_index":17,"text":[2,3,4,5,10,12,13,15,17],"than":[5,12],"thank":[5,12],"them":[3,5,12,17],"theoret":[5,12],"thi":[1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17],"thin":[3,6],"thing":5,"third":10,"thriller":[3,4],"through":[3,7,9],"time":[3,4,7],"timedelta":7,"timestamp":17,"titl":[3,4,7],"tl":6,"tns_admin":11,"togeth":[3,4],"token":[13,15],"tool":0,"tool_input":[3,4],"tool_nam":[3,4],"tool_name_pattern":[3,4],"tool_param":[3,4],"tool_typ":[3,4],"toolattribut":[0,3,4],"toolparam":[0,3,4],"tooltyp":[3,4],"topic":[3,4,7],"tort":1,"total":5,"touch":[5,12],"train":[3,4],"transform":14,"translat":[0,2,3,4,13],"trillion":[5,12],"trip":5,"true":[3,4,5,7,8,12,13,16,17],"tune":[3,4,13],"tupl":[5,12],"two":17,"txt":1,"type":[3,4,5,14,17],"typic":[5,7],"u":[3,4,5,7,12,17],"ultraviolet":[5,12],"under":[1,14],"underli":[5,12],"understand":[5,7,12,17],"union":[5,12,17],"uniqu":[3,5,12],"unit":17,"univers":[1,5,12],"unless":[5,7],"unmodifi":1,"up":[3,4],"updat":[0,5,7,12],"updated_attribut":17,"upgrad":9,"upl":1,"uri":[5,12],"url":[3,4,5,12,14],"us":[0,1,2,5,6,7,8,9,10,11,12,13,15,16],"usag":[5,7],"user":[2,3,4,5,6,7,8,9,11,12,14,16,17],"user_ocid":8,"user_prompt":16,"user_queri":[3,4],"usernam":[3,4,8],"utc":17,"util":[3,4],"uuid":[3,4],"uuid4":[3,4],"v":[5,12],"v3":17,"valid":13,"validate_config":8,"valu":[3,4,5,7,12,13,14,15,16,17],"valuabl":7,"vari":14,"variabl":[3,4,11],"varieti":[3,4],"variou":[3,4,5,12],"vecpipelin":17,"vector":[3,4,13],"vector_db_credential_nam":17,"vector_db_endpoint":17,"vector_db_provid":17,"vector_dimens":17,"vector_distance_metr":17,"vector_index":17,"vector_index_attribut":17,"vector_index_nam":[5,12,13,17],"vector_table_nam":17,"vectordbprovid":17,"vectordistancemetr":17,"vectorindex":[0,3,4,7],"vectorindexattribut":0,"vectorindexnotfounderror":17,"version":[1,9,10],"versu":15,"via":[5,12],"view":[5,12],"wai":[5,12],"wait":[3,4,5,17],"wait_for_complet":17,"waiting_for_human":[3,4],"wallet":6,"wallet_loc":6,"wallet_password":6,"want":[5,12],"war":[3,4],"warranti":1,"water":[5,12],"wave":[5,12],"we":[3,4,5,8],"web":[0,12],"web_search_ag":[3,4],"web_search_task":[3,4],"web_search_team":[3,4],"web_search_tool":[3,4],"websearch":[3,4],"websit":[3,4],"were":7,"western":[3,4],"what":[3,4,5,7,12],"when":[2,3,9,14,15,17],"where":[3,4,5,12],"whether":[1,3,4,13,17],"which":[0,1,3,4,6,7,14,15,17],"while":[5,12],"who":16,"whose":3,"why":7,"wide":[3,4,12],"wiki":[5,12],"wikipedia":[5,12],"wire":3,"within":[3,4,5,17],"without":[1,2,3,4,5,12],"word":15,"work":[1,3,4],"workflow":[0,3,4,5],"workload":[3,4],"world":[3,4],"write":5,"www":[3,4],"x":[5,12],"xxx":8,"you":[3,4,5,6,9,10,12,14,15,17],"your":[2,3,4,8,14,17],"your_db_dsn":[6,9],"your_db_password":[6,9],"your_db_us":[6,9],"\u00aa":1,"\u00b2":1,"\u00b3":1,"\u00b5":1,"\u00b9":1,"\u00ba":1,"\u00bc":1,"\u00bd":1,"\u00be":1,"\u03c9":1,"\u215b":1,"\u215c":1,"\u215d":1,"\u215e":1},"titles":["select_ai documentation","<no title>","1. Supported Actions","1. Tool","1. AsyncTool","1. AsyncProfile API","3. Connecting to Oracle Database","1. Conversation Object model","1. Create credential","2. Installing select_ai","1. Introduction to Select AI for Python","1. Grant privilege","1. Profile Object Model","1. ProfileAttributes","1. Provider","1. SummaryParams","1. SyntheticDataAttributes","1. VectorIndex Object Model"],"titleterms":{"":[3,4],"action":[0,2],"agent":[0,3,4],"ai":[0,2,3,4,8,10,14],"anthropicprovid":14,"api":[5,7,8,12,14,16,17],"async":[3,4,5,7,8,12,14,16,17],"asyncag":4,"asyncconvers":7,"asynchron":[5,6],"asyncprofil":5,"asynctask":4,"asyncteam":4,"asynctool":4,"asyncvectorindex":17,"attribut":[0,17],"awsprovid":14,"azureprovid":14,"base":12,"chat":[5,7,12],"chunkprocessingmethod":15,"cohereprovid":14,"concurr":5,"connect":6,"convers":[0,7],"conversationattribut":7,"creat":[3,4,7,8,12,17],"creation":5,"credenti":[0,8],"data":[0,16],"databas":6,"delet":[7,17],"disabl":14,"document":0,"enabl":14,"exampl":[3,4],"expect":8,"explain":5,"extractivenesslevel":15,"fetch":17,"format":8,"get":0,"googleprovid":14,"gpt":[3,4],"grant":11,"huggingfaceprovid":14,"index":[0,17],"instal":9,"introduct":10,"list":[3,4,5,7,12,17],"model":[3,4,7,12,17],"multi":16,"narrat":12,"object":[7,12,17],"ocigenaiprovid":14,"openai":[3,4],"openaiprovid":14,"oracl":6,"oraclevectorindexattribut":17,"pipelin":5,"pool":6,"privileg":[0,11],"profil":[0,5,12],"profileattribut":13,"provid":[0,8,14],"python":10,"rag":17,"requir":9,"revok":11,"run":[3,4,5,12],"search":[3,4],"select":[2,3,4,10],"select_ai":[0,9],"servic":14,"session":7,"show":[5,12],"sing":16,"singl":16,"sql":[5,12],"start":0,"summar":[5,12],"summari":0,"summaryparam":15,"summarystyl":15,"support":[2,3],"sync":[8,14,16],"synchron":6,"synthet":[0,16],"syntheticdataattribut":16,"syntheticdataparam":16,"tabl":16,"task":[3,4],"team":[3,4],"tool":[3,4],"translat":[5,12],"updat":17,"us":[3,4,14,17],"vector":[0,17],"vectorindex":17,"vectorindexattribut":17,"web":[3,4]}}) +Search.setIndex({"alltitles":{"AI Agent":[[0,"ai-agent"]],"AI agent examples":[[3,"ai-agent-examples"]],"AI provider and expected credential format":[[10,null]],"AWSProvider":[[16,"awsprovider"]],"Action methods":[[2,"action-methods"]],"Action to method mapping":[[2,"id2"]],"Actions":[[0,"actions"]],"Agent":[[3,"id1"]],"AnthropicProvider":[[16,"anthropicprovider"]],"Async AI Agent":[[0,"async-ai-agent"]],"Async AI agent examples":[[4,"async-ai-agent-examples"]],"Async API":[[10,"async-api"],[10,"id2"]],"Async Profile":[[0,"async-profile"]],"Async Profile creation":[[5,"async-profile-creation"]],"Async RAG using vector index":[[19,"async-rag-using-vector-index"]],"Async chat":[[5,"async-chat"]],"Async chat session":[[9,"async-chat-session"]],"Async concurrent SQL":[[5,"async-concurrent-sql"]],"Async create vector index":[[19,"async-create-vector-index"]],"Async explain SQL":[[5,"async-explain-sql"]],"Async fetch vector index":[[19,"async-fetch-vector-index"]],"Async list conversations":[[9,"async-list-conversations"]],"Async list vector index":[[19,"async-list-vector-index"]],"Async pipeline":[[5,"async-pipeline"]],"Async profile actions":[[5,"async-profile-actions"]],"Async profile lifecycle":[[5,null]],"Async run SQL":[[5,"async-run-sql"]],"Async show SQL":[[5,"async-show-sql"]],"Async show prompt":[[5,"async-show-prompt"]],"Async streaming chat":[[5,"async-streaming-chat"]],"Async summary":[[17,"async-summary"]],"Async update vector index attributes":[[19,"async-update-vector-index-attributes"]],"AsyncAgent":[[4,"asyncagent"]],"AsyncConversation API":[[9,"asyncconversation-api"]],"AsyncProfile API":[[5,"asyncprofile-api"]],"AsyncTask":[[4,"asynctask"]],"AsyncTeam":[[4,"asyncteam"]],"AsyncTool":[[4,"asynctool"]],"AsyncVectorIndex API":[[19,"asyncvectorindex-api"]],"Asynchronous connection":[[8,"asynchronous-connection"]],"Attribute groups":[[15,"attribute-groups"]],"AzureProvider":[[16,"azureprovider"]],"Base Profile API":[[14,"base-profile-api"]],"CLI command summary":[[6,"id3"]],"Chat":[[14,"chat"]],"Chat REPL commands":[[6,"id2"]],"Chat session":[[9,"chat-session"]],"Choosing an action":[[2,"choosing-an-action"]],"ChunkProcessingMethod":[[17,"chunkprocessingmethod"]],"CohereProvider":[[16,"cohereprovider"]],"Command Line Interface":[[0,"command-line-interface"]],"Command line interface":[[6,null]],"Command summary":[[6,"command-summary"]],"Common async profile actions":[[5,"id1"]],"Common profile actions":[[14,"id1"]],"Common required attributes":[[15,"common-required-attributes"]],"Concurrent Prompt Processing":[[0,"concurrent-prompt-processing"]],"Concurrent prompt processing":[[7,null]],"Connecting to Oracle Database":[[8,null]],"Connection Pool":[[8,"connection-pool"]],"Connection health":[[8,"connection-health"]],"Connection options":[[6,"connection-options"],[6,"id1"]],"Connection smoke test":[[11,"connection-smoke-test"]],"Content from a URI":[[17,"content-from-a-uri"]],"Content from object storage":[[17,"content-from-object-storage"]],"Conversation":[[0,"conversation"]],"Conversation API":[[9,"conversation-api"]],"Conversation Object model":[[9,null]],"ConversationAttributes":[[9,"conversationattributes"]],"Core concepts":[[12,"core-concepts"]],"Create Agent":[[3,"create-agent"],[4,"create-agent"]],"Create Profile":[[14,"create-profile"]],"Create Task":[[3,"create-task"],[4,"create-task"]],"Create Tool":[[3,"create-tool"],[4,"create-tool"]],"Create conversation":[[9,"create-conversation"]],"Create credential":[[10,"create-credential"]],"Create vector index":[[19,"create-vector-index"]],"Credential":[[0,"credential"]],"Delete Async Profile":[[5,"delete-async-profile"]],"Delete Profile":[[14,"delete-profile"]],"Delete conversation":[[9,"delete-conversation"]],"Delete credential":[[10,"delete-credential"]],"Delete vector index":[[19,"delete-vector-index"]],"Disable AI service provider":[[16,"disable-ai-service-provider"]],"Disable using Async API":[[16,"disable-using-async-api"]],"Disable using Sync API":[[16,"disable-using-sync-api"]],"Django example":[[20,"django-example"]],"Enable AI service provider":[[16,"enable-ai-service-provider"]],"Enable using Async API":[[16,"enable-using-async-api"]],"Enable using Sync API":[[16,"enable-using-sync-api"]],"Environment variables":[[7,"environment-variables"]],"Examples":[[2,"examples"],[16,"examples"]],"Explain SQL":[[14,"explain-sql"]],"Export and Import Team":[[3,"export-and-import-team"],[4,"export-and-import-team"]],"ExtractivenessLevel":[[17,"extractivenesslevel"]],"FastAPI asynchronous endpoints":[[20,"fastapi-asynchronous-endpoints"]],"FastAPI synchronous endpoints":[[20,"fastapi-synchronous-endpoints"]],"Fetch vector index":[[19,"fetch-vector-index"]],"Flask example":[[20,"flask-example"]],"Framework patterns":[[20,"framework-patterns"]],"Generation controls":[[15,"generation-controls"]],"Generation modes":[[18,null]],"Generation parameters":[[18,"generation-parameters"]],"Getting Started":[[0,"getting-started"]],"GoogleProvider":[[16,"googleprovider"]],"Grant network access":[[13,"grant-network-access"]],"Grant privilege":[[13,null]],"HuggingFaceProvider":[[16,"huggingfaceprovider"]],"Inline content":[[17,null]],"Install dependencies":[[20,"install-dependencies"]],"Install documentation dependencies":[[11,"install-documentation-dependencies"]],"Installation requirements":[[11,"installation-requirements"]],"Installing select_ai":[[11,null]],"Interactive chat":[[6,"interactive-chat"]],"Introduction to Select AI for Python":[[12,null]],"Lifecycle helpers":[[3,"lifecycle-helpers"],[4,"lifecycle-helpers"]],"List Agents":[[4,"list-agents"]],"List Tasks":[[3,"list-tasks"],[4,"list-tasks"]],"List Teams":[[4,"list-teams"]],"List Tools":[[3,"list-tools"],[4,"list-tools"]],"List conversations":[[9,"list-conversations"]],"List profiles":[[14,"list-profiles"]],"List profiles asynchronously":[[5,"list-profiles-asynchronously"]],"List vector index":[[19,"list-vector-index"]],"Multi table Async API":[[18,"multi-table-async-api"]],"Multi table Sync API":[[18,"multi-table-sync-api"]],"Multi table synthetic data":[[18,"multi-table-synthetic-data"]],"Narrate":[[14,"narrate"]],"OCIGenAIProvider":[[16,"ocigenaiprovider"]],"Object list examples":[[15,"object-list-examples"]],"OpenAIProvider":[[16,"openaiprovider"]],"OracleVectorIndexAttributes":[[19,"oraclevectorindexattributes"]],"Pool sizing":[[7,"pool-sizing"],[20,"pool-sizing"]],"Pool wait behavior":[[20,"pool-wait-behavior"]],"Privileges":[[0,"privileges"]],"Profile":[[0,"profile"]],"Profile API":[[14,"profile-api"]],"Profile Attributes":[[0,"profile-attributes"]],"Profile Object Model":[[14,"profile-object-model"]],"Profile actions":[[14,"profile-actions"]],"Profile attribute groups":[[15,"id1"]],"Profile commands":[[6,"profile-commands"]],"Profile lifecycle":[[14,null]],"ProfileAttributes":[[15,null]],"Provider":[[0,"provider"],[16,null],[16,"id2"]],"Provider classes":[[16,"id3"]],"RAG using vector index":[[19,"rag-using-vector-index"]],"Recipe summary":[[7,"recipe-summary"]],"Request handling":[[20,"request-handling"]],"Reuse Async Profile":[[5,"reuse-async-profile"]],"Reuse Profile":[[14,"reuse-profile"]],"Revoke network access":[[13,"revoke-network-access"]],"Revoke privilege":[[13,"revoke-privilege"]],"Run SQL":[[14,"run-sql"]],"Run Team":[[3,"run-team"],[4,"run-team"]],"SQL commands":[[6,"sql-commands"]],"Select AI Actions":[[2,"id1"]],"Select AI Agent Tools":[[3,"id2"]],"Select AI Async Agent Tools":[[4,"id2"]],"Show Prompt":[[14,"show-prompt"]],"Show SQL":[[14,"show-sql"]],"Single Table Async API":[[18,"single-table-async-api"]],"Single Table Sync API":[[18,"single-table-sync-api"]],"Single table synthetic data":[[18,"single-table-synthetic-data"]],"Streaming":[[2,"streaming"]],"Streaming chat":[[14,"streaming-chat"]],"Summarize":[[5,"summarize"],[14,"summarize"]],"Summary":[[0,"summary"]],"Summary parameters":[[17,"summary-parameters"]],"SummaryParams":[[17,"summaryparams"]],"SummaryStyle":[[17,"summarystyle"]],"Supported Actions":[[2,null]],"Supported Python versions":[[12,"supported-python-versions"]],"Supported Tools":[[3,"supported-tools"]],"Sync API":[[10,"sync-api"],[10,"id1"]],"Sync and async APIs":[[18,"sync-and-async-apis"]],"Sync and async agent APIs":[[4,null]],"Synchronous and asynchronous APIs":[[12,"synchronous-and-asynchronous-apis"]],"Synchronous connection":[[8,"synchronous-connection"]],"Synthetic Data":[[0,"synthetic-data"]],"SyntheticDataAttributes":[[18,"syntheticdataattributes"]],"SyntheticDataParams":[[18,"syntheticdataparams"]],"Task":[[3,"task"]],"Team":[[3,"team"]],"Tool":[[3,null]],"Tool selection":[[3,"tool-selection"]],"Translate":[[5,"translate"],[14,"translate"]],"Update Async Profile":[[5,"update-async-profile"]],"Update Profile":[[14,"update-profile"]],"Update vector index attributes":[[19,"update-vector-index-attributes"]],"Using select_ai with Python web frameworks":[[20,null]],"Validation":[[17,"validation"]],"Vector Index":[[0,"vector-index"],[19,null]],"VectorIndex API":[[19,"vectorindex-api"]],"VectorIndex Object Model":[[19,"vectorindex-object-model"]],"VectorIndexAttributes":[[19,"vectorindexattributes"]],"Wallet connections":[[8,"wallet-connections"]],"Web Frameworks":[[0,"web-frameworks"]],"Web Search Agent using OpenAI\u2019s GPT model":[[3,"web-search-agent-using-openai-s-gpt-model"],[4,"web-search-agent-using-openai-s-gpt-model"]],"What you can build":[[12,"what-you-can-build"]],"When to use each tool":[[3,"id3"]],"async_as_completed.py":[[7,"async-as-completed-py"]],"async_gather.py":[[7,"async-gather-py"]],"async_pipeline.py":[[7,"async-pipeline-py"]],"async_queue_workers.py":[[7,"async-queue-workers-py"]],"select_ai documentation":[[0,null]],"select_ai installation":[[11,"select-ai-installation"]],"sync_ordered_results.py":[[7,"sync-ordered-results-py"]],"sync_queue_workers.py":[[7,"sync-queue-workers-py"]],"sync_thread_pool.py":[[7,"sync-thread-pool-py"]]},"docnames":["index","license","user_guide/actions","user_guide/agent","user_guide/async_agent","user_guide/async_profile","user_guide/cli","user_guide/concurrent_prompt_processing","user_guide/connection","user_guide/conversation","user_guide/credential","user_guide/installation","user_guide/introduction","user_guide/privileges","user_guide/profile","user_guide/profile_attributes","user_guide/provider","user_guide/summary","user_guide/synthetic_data","user_guide/vector_index","user_guide/web_frameworks"],"envversion":{"sphinx":65,"sphinx.domains.c":3,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":9,"sphinx.domains.index":1,"sphinx.domains.javascript":3,"sphinx.domains.math":2,"sphinx.domains.python":4,"sphinx.domains.rst":2,"sphinx.domains.std":2},"filenames":["index.rst","license.rst","user_guide/actions.rst","user_guide/agent.rst","user_guide/async_agent.rst","user_guide/async_profile.rst","user_guide/cli.rst","user_guide/concurrent_prompt_processing.rst","user_guide/connection.rst","user_guide/conversation.rst","user_guide/credential.rst","user_guide/installation.rst","user_guide/introduction.rst","user_guide/privileges.rst","user_guide/profile.rst","user_guide/profile_attributes.rst","user_guide/provider.rst","user_guide/summary.rst","user_guide/synthetic_data.rst","user_guide/vector_index.rst","user_guide/web_frameworks.rst"],"indexentries":{},"objects":{"select_ai":[[16,0,1,"","AWSProvider"],[16,0,1,"","AnthropicProvider"],[9,0,1,"","AsyncConversation"],[5,0,1,"","AsyncProfile"],[19,0,1,"","AsyncVectorIndex"],[16,0,1,"","AzureProvider"],[14,0,1,"","BaseProfile"],[16,0,1,"","CohereProvider"],[9,0,1,"","Conversation"],[9,0,1,"","ConversationAttributes"],[16,0,1,"","GoogleProvider"],[16,0,1,"","HuggingFaceProvider"],[16,0,1,"","OCIGenAIProvider"],[16,0,1,"","OpenAIProvider"],[19,0,1,"","OracleVectorIndexAttributes"],[14,0,1,"","Profile"],[15,0,1,"","ProfileAttributes"],[16,0,1,"","Provider"],[18,0,1,"","SyntheticDataAttributes"],[18,0,1,"","SyntheticDataParams"],[19,0,1,"","VectorIndex"],[19,0,1,"","VectorIndexAttributes"]],"select_ai.AsyncConversation":[[9,1,1,"","create"],[9,1,1,"","delete"],[9,1,1,"","fetch"],[9,1,1,"","get_attributes"],[9,1,1,"","list"],[9,1,1,"","set_attributes"]],"select_ai.AsyncProfile":[[5,1,1,"","add_negative_feedback"],[5,1,1,"","add_positive_feedback"],[5,1,1,"","chat"],[5,1,1,"","chat_session"],[5,1,1,"","create"],[5,1,1,"","delete"],[5,1,1,"","delete_feedback"],[5,1,1,"","delete_profile"],[5,1,1,"","explain_sql"],[5,1,1,"","fetch"],[5,1,1,"","generate"],[5,1,1,"","generate_synthetic_data"],[5,1,1,"","get_attributes"],[5,1,1,"","list"],[5,1,1,"","narrate"],[5,1,1,"","run_pipeline"],[5,1,1,"","run_sql"],[5,1,1,"","set_attribute"],[5,1,1,"","set_attributes"],[5,1,1,"","show_prompt"],[5,1,1,"","show_sql"],[5,1,1,"","summarize"],[5,1,1,"","translate"]],"select_ai.AsyncVectorIndex":[[19,1,1,"","create"],[19,1,1,"","delete"],[19,1,1,"","delete_index"],[19,1,1,"","disable"],[19,1,1,"","enable"],[19,1,1,"","fetch"],[19,1,1,"","get_attributes"],[19,1,1,"","get_next_refresh_timestamp"],[19,1,1,"","get_profile"],[19,1,1,"","list"],[19,1,1,"","set_attribute"],[19,1,1,"","set_attributes"]],"select_ai.Conversation":[[9,1,1,"","create"],[9,1,1,"","delete"],[9,1,1,"","fetch"],[9,1,1,"","get_attributes"],[9,1,1,"","list"],[9,1,1,"","set_attributes"]],"select_ai.Profile":[[14,1,1,"","add_negative_feedback"],[14,1,1,"","add_positive_feedback"],[14,1,1,"","chat"],[14,1,1,"","chat_session"],[14,1,1,"","create"],[14,1,1,"","delete"],[14,1,1,"","delete_feedback"],[14,1,1,"","delete_profile"],[14,1,1,"","explain_sql"],[14,1,1,"","fetch"],[14,1,1,"","generate"],[14,1,1,"","generate_synthetic_data"],[14,1,1,"","get_attributes"],[14,1,1,"","list"],[14,1,1,"","narrate"],[14,1,1,"","run_sql"],[14,1,1,"","set_attribute"],[14,1,1,"","set_attributes"],[14,1,1,"","show_prompt"],[14,1,1,"","show_sql"],[14,1,1,"","summarize"],[14,1,1,"","translate"]],"select_ai.VectorIndex":[[19,1,1,"","create"],[19,1,1,"","delete"],[19,1,1,"","delete_index"],[19,1,1,"","disable"],[19,1,1,"","enable"],[19,1,1,"","fetch"],[19,1,1,"","get_attributes"],[19,1,1,"","get_next_refresh_timestamp"],[19,1,1,"","get_profile"],[19,1,1,"","list"],[19,1,1,"","set_attribute"],[19,1,1,"","set_attributes"]],"select_ai.agent":[[3,0,1,"","Agent"],[3,0,1,"","AgentAttributes"],[4,0,1,"","AsyncAgent"],[4,0,1,"","AsyncTask"],[4,0,1,"","AsyncTeam"],[4,0,1,"","AsyncTool"],[3,0,1,"","Task"],[3,0,1,"","TaskAttributes"],[3,0,1,"","Team"],[3,0,1,"","TeamAttributes"],[3,0,1,"","Tool"],[3,0,1,"","ToolAttributes"],[3,0,1,"","ToolParams"]],"select_ai.agent.Agent":[[3,1,1,"","create"],[3,1,1,"","delete"],[3,1,1,"","delete_agent"],[3,1,1,"","disable"],[3,1,1,"","enable"],[3,1,1,"","fetch"],[3,1,1,"","list"],[3,1,1,"","set_attribute"],[3,1,1,"","set_attributes"]],"select_ai.agent.AsyncAgent":[[4,1,1,"","create"],[4,1,1,"","delete"],[4,1,1,"","delete_agent"],[4,1,1,"","disable"],[4,1,1,"","enable"],[4,1,1,"","fetch"],[4,1,1,"","list"],[4,1,1,"","set_attribute"],[4,1,1,"","set_attributes"]],"select_ai.agent.AsyncTask":[[4,1,1,"","create"],[4,1,1,"","delete"],[4,1,1,"","delete_task"],[4,1,1,"","disable"],[4,1,1,"","enable"],[4,1,1,"","fetch"],[4,1,1,"","list"],[4,1,1,"","set_attribute"],[4,1,1,"","set_attributes"]],"select_ai.agent.AsyncTeam":[[4,1,1,"","create"],[4,1,1,"","delete"],[4,1,1,"","delete_team"],[4,1,1,"","disable"],[4,1,1,"","enable"],[4,1,1,"","export"],[4,1,1,"","export_team"],[4,1,1,"","fetch"],[4,1,1,"","import_team"],[4,1,1,"","list"],[4,1,1,"","run"],[4,1,1,"","set_attribute"],[4,1,1,"","set_attributes"]],"select_ai.agent.AsyncTool":[[4,1,1,"","create"],[4,1,1,"","create_built_in_tool"],[4,1,1,"","create_email_notification_tool"],[4,1,1,"","create_pl_sql_tool"],[4,1,1,"","create_rag_tool"],[4,1,1,"","create_slack_notification_tool"],[4,1,1,"","create_sql_tool"],[4,1,1,"","create_websearch_tool"],[4,1,1,"","delete"],[4,1,1,"","delete_tool"],[4,1,1,"","disable"],[4,1,1,"","enable"],[4,1,1,"","fetch"],[4,1,1,"","list"],[4,1,1,"","set_attribute"],[4,1,1,"","set_attributes"]],"select_ai.agent.Task":[[3,1,1,"","create"],[3,1,1,"","delete"],[3,1,1,"","delete_task"],[3,1,1,"","disable"],[3,1,1,"","enable"],[3,1,1,"","fetch"],[3,1,1,"","list"],[3,1,1,"","set_attribute"],[3,1,1,"","set_attributes"]],"select_ai.agent.Team":[[3,1,1,"","create"],[3,1,1,"","delete"],[3,1,1,"","delete_team"],[3,1,1,"","disable"],[3,1,1,"","enable"],[3,1,1,"","export"],[3,1,1,"","export_team"],[3,1,1,"","fetch"],[3,1,1,"","import_team"],[3,1,1,"","list"],[3,1,1,"","run"],[3,1,1,"","set_attribute"],[3,1,1,"","set_attributes"]],"select_ai.agent.Tool":[[3,1,1,"","create_built_in_tool"],[3,1,1,"","create_email_notification_tool"],[3,1,1,"","create_pl_sql_tool"],[3,1,1,"","create_rag_tool"],[3,1,1,"","create_slack_notification_tool"],[3,1,1,"","create_sql_tool"],[3,1,1,"","create_websearch_tool"],[3,1,1,"","delete"],[3,1,1,"","delete_tool"],[3,1,1,"","disable"],[3,1,1,"","enable"],[3,1,1,"","fetch"],[3,1,1,"","list"],[3,1,1,"","set_attribute"],[3,1,1,"","set_attributes"]],"select_ai.summary":[[17,0,1,"","ChunkProcessingMethod"],[17,0,1,"","ExtractivenessLevel"],[17,0,1,"","Style"],[17,0,1,"","SummaryParams"]]},"objnames":{"0":["py","class","Python class"],"1":["py","method","Python method"]},"objtypes":{"0":"py:class","1":"py:method"},"terms":{"":[0,1,5,9,10,11,12,14,16,18,19,20],"0":[1,5,9,14,15,16,19,20],"01":[3,4],"02":[3,4],"03":[3,4],"04":[3,4],"05":[3,4],"06":[3,4],"07":[3,4],"07b9":[3,4],"08":[3,4],"09":[3,4],"1":[1,3,4,5,7,9,14,15,16,17,19,20],"10":[3,4,8,9,18,20],"100":[3,4,18],"1024":[5,14,15,19],"11":[11,12],"11c8":9,"12":[11,12],"128":19,"128e":[3,4],"13":[11,12,18],"14":[9,11,12],"1440":19,"1450":19,"150":17,"151b000ad3b4":9,"17b":[3,4],"2":[3,4,5,19,20],"20":9,"20000":5,"2019":[3,4,18],"20240620":16,"2025":1,"2048":[5,14],"20i":20,"20oci":20,"25e23a25":[3,4],"3":[3,4,5,11,12,16,19],"300":18,"37ddc22e":9,"37df777f":9,"380a1910":9,"3ab2ed3":9,"3d49":9,"3f":20,"4":[3,4,5,7,16,19,20],"40":18,"400":[5,14],"4096":[2,5,14],"40e7":[3,4],"463a":[3,4],"4ed7":[3,4],"4o":16,"5":[3,4,5,7,8,16,18,19,20],"50":17,"503":[5,14],"5275a80":9,"55":[5,14],"587":13,"5bf2":9,"6":[3,4],"7":[3,4,9],"7e52":9,"8":[3,4,20],"80":11,"8000":[9,20],"8192":[5,14],"9":[3,4],"987c":[3,4],"A":[1,3,4,5,6,9,10,11,14,15,16,19,20],"AND":1,"AS":[1,5,14],"BE":1,"BUT":1,"By":[9,19],"FOR":1,"For":[3,5,7,8,9,11,12,13,14,15,16,18,19,20],"IN":1,"If":[3,4,6,9,10,11,19,20],"In":[3,4,7,8,10,19,20],"It":[0,5,6,7,9,12,14,17,18,19],"NO":1,"NOT":1,"No":[3,4],"OF":1,"OR":1,"On":[3,4,11],"One":8,"THE":1,"TO":1,"The":[1,2,3,4,5,6,7,8,9,10,12,13,14,15,16,17,18,19,20],"Then":[8,11],"There":[13,14],"These":[3,4,11,13,16,19],"To":[5,8,11,16,19],"WITH":1,"_":[1,7],"__name__":20,"_required_field":[3,4],"a290":9,"a489":[3,4],"abc":[3,4],"abil":9,"about":[3,4,5,6,9,12,14,19],"abov":1,"abstract":14,"accept":[3,4,6,10,13],"access":[0,3,4,5,10,11,14,15,16,17,19],"accomplish":[3,4],"accuraci":2,"acl":[12,13,16,19],"acquir":[5,8,14,20],"across":[9,19],"act":[2,3,4],"action":[1,3,4,7,12,19],"activ":[8,9,11,19],"actor":[3,4,18],"actual":[5,14],"ad":[6,19],"add":[3,13,16,20],"add_negative_feedback":[5,14],"add_positive_feedback":[5,14],"addit":[3,4,6,7,8,15,18],"addition":[5,14],"adjac":19,"admin":13,"admin_us":[13,16],"administr":[5,8,13],"advanc":[3,4],"adventur":[3,4],"affili":1,"after":[5,6,8,9,11,14,19,20],"after_serv":20,"after_server_stop":20,"again":[10,14],"against":[6,20],"agent":[8,10,12,16],"agent_attribut":[3,4],"agent_nam":[3,4],"agent_name_pattern":[3,4],"agentattribut":[0,3,4],"agentnotfounderror":[3,4],"agenttasknotfounderror":[3,4],"agentteamnotfounderror":[3,4],"agenttoolnotfounderror":[3,4],"agreement":1,"ai":[1,5,6,7,8,9,11,13,14,15,17,18,19,20],"alcohol":[5,14],"algorithm":[3,4],"alia":5,"all":[1,3,4,5,6,7,9,13,14,15,19,20],"allow":[3,4,5,13,16],"allowlist":20,"along":[8,19],"alreadi":[4,5,6,10,11,14,19,20],"also":[3,4,5,10,14,16,19,20],"amazon":14,"amazonaw":16,"amount":[5,14,19],"an":[0,1,3,4,5,6,7,8,9,10,11,13,14,15,16,17,19,20],"analysi":9,"analyst":[3,4],"analyt":[3,4,5,14],"analyz":[3,4,5],"analyze_movie_task":[3,4],"ancient":[5,14],"ani":[1,3,4,11,16],"anim":[3,4],"annot":[5,14,15,19],"anomali":[3,4],"anoth":[2,3,4,5,9,14,19],"answer":[2,3,4,5,6,7,9,12,14,19],"ant":10,"anthrop":[10,16],"anthropic_cr":10,"anthropicprovid":0,"api":[0,3,7,8,13,15,17,20],"app":20,"appconfig":20,"append_host_ac":13,"appli":20,"applic":[2,3,4,5,7,8,9,12,13,16,18,19,20],"appreci":9,"approach":20,"approxim":[7,17,20],"ar":[3,4,5,6,7,9,10,11,13,14,15,16,17,18,19,20],"arbitrari":20,"area":[5,14],"arg":[5,7,14,20],"argument":[3,4,8,13],"aris":1,"arrai":[3,15],"arriv":7,"articl":6,"artifici":[3,4,5],"as_complet":[5,7],"asgi":20,"ashburn":[17,19],"ask":[3,6,9,12],"assign":[3,15,18],"associ":[1,3,4,5,19],"astrobiologi":[5,14],"astronom":[5,14],"astronomi":[5,14,17],"async":[7,8,12,13,20],"async_as_complet":0,"async_connect":[4,5,8,9,10,13,16,18,19],"async_convers":9,"async_create_credenti":[4,10],"async_delete_credenti":10,"async_disconnect":[7,8,20],"async_gath":0,"async_grant_http_access":16,"async_grant_network_access":13,"async_is_connect":8,"async_oci_ai_profil":[5,7,9,14,17,18,20],"async_oci_vector_ai_profil":[14,19],"async_pipelin":0,"async_profil":[5,9,17,18,19],"async_queue_work":0,"async_revoke_http_access":16,"async_revoke_network_access":13,"async_sess":9,"async_vector_index":19,"asyncag":0,"asynccontextmanag":20,"asyncconvers":[0,5],"asyncgener":[4,5,9,19],"asynchron":[0,4,7,18],"asyncio":[4,5,7,9,10,12,13,16,18,19],"asyncprofil":[0,2,4,7,9,14,15,17,18,19,20],"asynctask":0,"asyncteam":0,"asynctool":0,"asyncvectorindex":0,"atexit":20,"attach":3,"attribut":[2,3,4,5,9,14,16,18],"attribute_nam":[3,4,5,14,19],"attribute_valu":[3,4,5,14,19],"audienc":[3,4],"augment":[12,15,19],"authent":[5,10,14,15,16,17],"author":1,"autom":[3,4,5,15],"automat":[3,9,11],"automl":[3,4],"autonom":[3,5],"autoreload":20,"avail":[3,6,7,8,11,17],"avoid":[8,20],"aw":[10,14,16],"await":[4,5,7,8,9,10,13,16,17,18,19,20],"awar":[5,6,9,12,14,15],"aws_access_key_id":10,"aws_apiformat":16,"aws_bedrock_cr":10,"aws_secret_access_kei":10,"awsprovid":0,"azur":[10,14,15,16],"azure_deployment_nam":16,"azure_embedding_deployment_nam":16,"azure_openai_api_kei":10,"azure_openai_cr":10,"azure_resource_nam":16,"azureprovid":0,"b":[1,6,17,19],"b2":[5,14],"back":[4,12,14],"background":[7,20],"base":[0,3,4,5,6,8,12,16,19,20],"baseprofil":[0,14,19],"batch":[7,20],"be11":[3,4],"be1a000a15b6":9,"becaus":[2,3,4,5,9],"becom":[5,14],"bedrock":[10,16],"been":[5,14],"beer":[5,14],"befor":[2,5,7,10,13,14,18,19,20],"before_serv":20,"before_server_start":20,"begin":15,"behav":15,"behavior":[0,2,3,9,15,16,19],"behind":11,"being":[5,14,16,19],"below":[1,8,18,19,20],"benefit":[3,4,8],"better":20,"between":[0,9,19],"bin":11,"biograph":[3,4],"biographi":[3,4],"block":[12,14,19,20],"blog":[8,20],"bool":[3,4,5,9,14,15,18,19],"both":[1,3,4,7,9,12,16,17,19,20],"bound":20,"boundari":[3,19],"branch":[5,14],"breakdown":5,"brew":[5,14],"bridg":[0,12],"bucket":[6,17,19],"budget":20,"build":[0,3,4,5,9,11,16,19],"built":[3,4,14],"burn":[5,14],"busi":[3,4,5,17,20],"byte":[5,14],"c":[1,5,20],"c2e3ff20":[3,4],"calcul":[5,19],"call":[3,5,7,8,9,10,12,13,16,17,19,20],"callabl":3,"caller":[5,14],"can":[0,2,3,4,5,6,7,8,9,11,13,14,15,16,17,19,20],"cancri":[5,14],"cannot":19,"capabl":[0,3,4,12],"capac":[7,8,20],"care":[18,20],"carefulli":[3,4],"case":[3,4,5,15,16],"case_sensitive_valu":[5,14,15,19],"cc72740c75a5":[3,4],"celesti":[5,14],"certain":3,"chain":3,"challeng":9,"chang":[5,14,19],"channel":[3,4],"charact":[5,6,14,19],"charg":1,"chat":[0,2,12,15,20],"chat_sess":[5,6,9,14],"chat_task":5,"chatgpt":[3,4],"check":[6,8,19,20],"chemistri":[5,14],"chicago":[3,4,5,14,15,16,19],"choic":19,"choos":[0,3,7,12,17,20],"chunk":[2,5,6,14,17,19],"chunk_overlap":19,"chunk_processing_method":17,"chunk_siz":[2,5,14,19],"chunkprocessingmethod":0,"churn":20,"civil":[5,14],"claim":1,"clarif":3,"clarifi":2,"class":[3,4,5,9,14,15,17,18,19,20],"classif":[3,4],"classmethod":[3,4,5,9,14,19],"claud":16,"cleanup":[3,4,5,10,14,20],"clear":[3,4,6],"cli":11,"client":[7,20],"climat":9,"clob":[5,6,14],"close":[7,8,12,17,20],"close_select_ai_pool":20,"cloud":[3,4,5,14,16],"clue":[5,14],"cluster":[3,4,16],"co":16,"code":[6,8,20],"coher":[10,16,19],"cohere_api_kei":10,"cohere_cr":10,"cohereprovid":0,"collect":[1,3,4,5,19],"column":[3,5,14,15],"com":[3,4,6,11,13,16,17,19],"combin":[9,12],"come":19,"comedi":[3,4],"comfort":6,"command":[7,11,12,16,19,20],"comment":[2,3,5,10,14,15,18,19],"common":[0,19],"compar":19,"compart":16,"compat":16,"compet":14,"complet":[1,7,18,19],"complianc":[3,4],"compliant":[3,4],"compon":[3,4,5],"component_typ":[3,4],"compos":3,"composit":[3,4,5,14],"comprehens":[9,14],"comput":[5,14],"concept":[0,16],"conceptu":19,"concis":[3,4],"concret":[16,20],"concurr":[8,12,19,20],"conda":19,"condit":1,"config":10,"config_dir":8,"configur":[3,6,8,15,18,19,20],"conflict":[3,4],"connect":[0,1,3,4,5,7,9,10,12,13,14,16,18,19,20],"consid":19,"constantli":[5,14],"constrain":15,"constraint":[2,5,14,15,19],"construct":19,"consum":[5,7,14,18],"contain":[3,4,5,14,17,19],"content":[0,2,3,4,5,6,9,12,14,19],"context":[3,5,6,9,12,14,15,19,20],"contextlib":20,"contextu":9,"continu":[3,4,5],"continue_on_error":[5,7],"contract":1,"contribut":1,"control":[0,5,6,7,9,14,17,18,19,20],"conveni":2,"convers":[2,3,4,5,6,12,14,15,19],"conversation_attribut":9,"conversation_id":[3,4,5,9,14],"conversation_length":9,"conversationattribut":0,"convert":[16,19],"cool":[5,14],"coordin":3,"copi":[1,18],"copyright":1,"core":0,"corpor":[5,14],"correct":5,"correctli":6,"correspond":[5,10,14],"cosin":19,"could":[3,4,5,14],"count":[5,6,7,14,18],"countri":16,"cover":[1,15],"creat":[0,1,5,7,8,11,12,13,15,16,20],"create_app":20,"create_built_in_tool":[0,3,4],"create_credenti":[3,10,16],"create_email_notification_tool":[0,3,4],"create_http_tool":[],"create_pl_sql_tool":[0,3,4],"create_pool":[7,8,9,20],"create_pool_async":[4,5,7,8,9,20],"create_rag_tool":[0,3,4],"create_slack_notification_tool":[0,3,4],"create_sql_tool":[0,3,4],"create_task":7,"create_tool":3,"create_websearch_tool":[0,3,4],"creation":[0,3,4,8,9,19],"credenti":[3,4,5,6,8,12,14,15,16,17,18,19,20],"credential_nam":[3,4,5,10,14,15,16,17,19],"ctrl":20,"cultur":9,"curat":6,"curl":20,"current":[3,8,9,19],"cust_email":5,"cust_first_nam":5,"cust_id":5,"cust_last_nam":5,"custom":[3,4,5,7,15,16,17,19],"customer_count":5,"d4328a7b2210":[3,4],"d81a000a3fda":9,"d81a000a53b":9,"d81a000a85f":9,"d917b055":[3,4],"da17":9,"dai":9,"damag":1,"dank":[5,14],"data":[1,2,3,4,5,12,14,16,19],"data_guard":[],"databas":[0,3,4,5,6,7,9,10,11,12,13,14,15,16,17,18,19,20],"databaseerror":[5,14,19],"datafram":[2,5,14],"date":[3,4,9,18],"datetim":[9,19],"db_admin":13,"db_admin_password":13,"db_connect_str":[6,7,8,11,13,20],"db_password":[6,8],"db_user":[6,8],"dba":5,"dbms_cloud":[10,13],"dbms_cloud_ai":[0,7,12,13],"dbms_cloud_ai_ag":[3,13],"dbms_cloud_pipelin":13,"dbms_network_acl_admin":13,"de":[5,14],"deal":1,"decid":[3,19],"dedic":[16,18],"deep":[],"def":[4,5,7,9,10,13,16,18,19,20],"default":[2,3,4,5,6,9,10,14,15,16,18,19],"default_config":10,"defin":[1,3,5,12,14,15,18,19],"definit":[3,4],"degre":[15,17],"delet":[0,3,4],"delete_ag":[0,3,4],"delete_credenti":10,"delete_feedback":[5,14],"delete_index":[0,19],"delete_profil":[5,14],"delete_task":[0,3,4],"delete_team":[0,3,4],"delete_tool":[0,3,4],"deliber":20,"demo":18,"denot":15,"depend":[0,3,5,15,16,19],"deploi":[3,4,5,16],"deploy":[3,4,7,8,15,16,20],"deriv":1,"describ":[3,4,5,12,14,15,16],"descript":[2,3,4,5,6,9,14,19],"design":[3,5],"despit":[5,14],"detail":[3,4,6,10,13,14,16,18,20],"detect":[3,4,5,14],"determin":17,"develop":[3,4,5,6,9,14,18,20],"df":[2,5,14],"dict":[3,4,5,14],"dictionari":3,"differ":[2,3,4,7],"dir_containing_tnsnam":13,"directli":[3,4,9,16,20],"director":[3,4,18],"disabl":[0,3,4,18,19],"disconnect":[7,8,20],"discoveri":[5,9,14],"displai":[1,2],"distanc":19,"distribut":1,"django":0,"do":[3,4,6,12,16,20],"doc":[11,19],"document":[1,12,13,17,19],"documentari":[3,4],"doe":[3,4,5,6,9,10,14,16,19],"doesn":5,"domain":3,"dot":19,"dotenv":13,"doubl":5,"down":20,"drama":[3,4],"drive":5,"driver":8,"drop":[3,4,9,10,19],"dsn":[3,4,5,6,7,8,9,10,11,13,14,16,18,19,20],"dtype":14,"due":[5,14],"dump":[3,4],"dure":[3,4,6,12,19,20],"dwcsdev":19,"dynam":[2,5,14],"e":[3,4,5,8,14,18,19],"e063":9,"e8a1":[3,4],"each":[1,6,7,8,19,20],"earli":[5,14],"earlier":19,"earliest":15,"easier":[5,14],"east":16,"ecosystem":[0,12],"effici":5,"either":[1,3,4,13,14,19,20],"elabor":9,"element":[5,14,19],"elig":15,"elimin":[3,4,5],"els":[5,14],"email":[3,4,5],"emb":19,"embed":[16,19],"embedding_model":[5,14,16,19],"empti":14,"en":[5,14,17],"enabl":[0,2,3,4,5,9,15,17,18,19],"enable_custom_source_uri":[15,19],"enable_human_tool":[3,4],"enable_sourc":[5,14,15,19],"enable_source_offset":[5,14,15,19],"enclos":5,"end":[1,2,5,9,14],"endpoint":[0,3,4,5,10,11,12,13,14,15,16,19],"enforce_object_list":[5,14,15,19],"english":[6,19],"enhanc":[3,4],"enough":[3,5,14],"ensur":[3,4,5],"enter":[],"entri":[3,13,16],"enum":2,"enumer":[5,7],"env":13,"environ":[0,3,4,6,8,11,13,19,20],"epic":[3,4],"error":[3,4,5,9,10,14,17,19,20],"especi":[9,20],"essenti":9,"euclidean":19,"eval":6,"evalu":[6,19],"even":[3,4,5,10,14],"event":[1,5,14],"everi":[8,9,10,15,20],"evolut":[5,14],"evolv":[5,6,14],"exact":19,"exactli":[17,18],"exampl":[0,5,6,8,9,10,11,13,14,18,19],"exce":17,"exchang":9,"exclude_nul":[5,14],"execut":[2,3,5,6,8,13,14,19],"executor":7,"exhaust":20,"exist":[3,4,5,6,9,10,14,18,19],"exit":[6,9],"exoplanet":[5,14],"expans":[5,14],"expect":[3,5,14,16,17,20],"experi":18,"expertis":[],"explain":[0,2,6,7,9],"explain_sql":[2,5,14],"explainsql":[2,5,7],"explan":[5,12,14],"explicit":2,"explicitli":5,"explor":[2,6],"export":[0,1,6,7,8,11,13,20],"export_import_movie_analyst":[3,4],"export_import_movie_task":[3,4],"export_import_movie_team":[3,4],"export_team":[0,3,4],"exported_spec":[3,4],"express":[1,3,4,5,6,14,19],"extern":[3,4,10,13,20],"extra":[6,11],"extract":17,"extractiveness_level":17,"extractivenesslevel":0,"extraterrestri":[5,14],"f":[5,7],"f084":9,"f3da":9,"f56d":[3,4],"f7a1":9,"f7e5e445d286":[3,4],"factori":[],"fail":20,"fals":[3,4,5,9,14,18,19],"famili":[3,4],"fantasi":[3,4],"fast":[6,16,20],"fastapi":[0,8],"faster":18,"fccenv":19,"featur":[3,4,12],"februari":[3,4],"feedback":[2,5,14],"feedback_cont":[5,14],"fetch":[0,3,4,5,9,14],"fetched_profil":[5,14],"fewer":[5,20],"fi":[3,4],"field":[3,5,10,14],"file":[1,5,6,10,11,13,14,17,19,20],"filenam":19,"film":[3,4],"filter":6,"final":7,"find":9,"fine":20,"fingerprint":10,"finish":7,"first":[5,14],"fit":1,"flask":0,"flexibl":[3,4],"float":[5,14,15,19],"focu":[5,17],"focus":[3,4,5,14],"follow":[1,2,3,4,5,9,10,13,14,17,19],"forc":[3,4,5,9,10,14,19],"forego":1,"foreign":15,"form":[5,14],"format":[5,14,15,16,17],"forth":1,"forti":20,"forward":[5,7,14],"found":[3,4,5,14],"four":20,"fp":10,"fp8":[3,4],"frame":12,"framework":[3,4,12],"free":1,"freeli":1,"fresh":6,"from":[0,1,2,3,4,5,7,8,9,10,11,13,14,15,16,18,19,20],"from_fil":10,"front":7,"fulfil":3,"full":[5,14],"fulli":[6,19],"function":[3,4,5,14,19],"further":9,"futur":7,"g":[5,14,18],"ga":[5,14],"gain":9,"galaxi":[5,14],"gamma":[5,14],"gap":0,"gatewai":20,"gather":7,"gcp":14,"gen":[5,10,14,16],"gener":[0,2,3,4,5,6,12,14,16,17,19,20],"generate_synthetic_data":[5,14,18],"generativelanguag":16,"genr":[3,4,6],"german":6,"get":[5,7,9,14,19,20],"get_attribut":[0,5,9,14,19],"get_next_refresh_timestamp":[0,19],"get_profil":[0,19],"getenv":[3,4,5,7,8,9,10,11,13,14,16,18,19,20],"getmod":20,"give":[5,12,14],"given":[3,4],"good":20,"googl":[10,14,16],"google_api_kei":10,"google_cr":10,"googleapi":16,"googleprovid":0,"govern":[3,4],"gpt":[0,16],"grant":[0,1,3,12,15],"grant_http_access":16,"grant_network_access":13,"grant_privileg":13,"graph":19,"graphenv":19,"gravit":[5,14],"grok":16,"ground":19,"group":[0,3,6],"grow":8,"guid":[3,5,6,14,17,18,19],"guidanc":4,"gunicorn":20,"ha":[5,9,10,13,14,18,19,20],"halo":[5,14],"ham":19,"handl":[0,7,8],"handler":20,"happen":20,"hard":20,"hardwar":1,"have":[1,5,9,16],"health":0,"heavi":19,"help":[3,4,6,9,12,15,19],"helper":[0,13,16,19],"here":[3,4,5,9,12],"herebi":1,"hereund":1,"hf":10,"hf_xxx":10,"high":[3,4,5,14,17,18],"higher":[5,12,18],"highlight":[3,4,16],"histor":[3,4],"histori":[5,9,12,14,15],"holder":1,"hook":20,"horror":[3,4],"host":[3,4,13,16,20],"hot":[5,14],"how":[2,3,4,5,6,7,14,15,16,17,18,19],"http":[3,4,5,6,11,13,14,16,17,19,20],"https_proxi":8,"https_proxy_port":8,"huggingfac":[10,16],"huggingface_cr":10,"huggingfaceprovid":0,"human":[3,4,9],"hyperparamet":[3,4],"i":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],"ibm":14,"ic":[5,14],"id":[3,4,5,9],"identifi":[3,4,5,9,14,18],"ignor":[5,9,14,19],"ii":1,"impact":9,"implement":16,"impli":1,"implic":17,"import":[0,1,5,7,8,9,10,11,13,14,16,18,19,20],"import_team":[0,3,4],"imported_analyze_movie_task":[3,4],"imported_movie_agent_team":[3,4],"imported_movie_analyst":[3,4],"improv":[2,3,4],"includ":[1,3,4,5,9,10,13,14,15,18,19],"include_data":19,"incorpor":15,"increas":20,"increment":[7,8,20],"indent":[3,4],"independ":7,"index":[3,4,6,7,8,10,11,12,14,15,16],"index_nam":19,"index_name_pattern":19,"indic":[15,16,19],"infer":16,"inform":[3,4,18,19],"infrar":[5,14],"infrastructur":[3,4,5,14],"inherit":[3,4],"initi":[5,19,20],"inlin":[0,2,3,4,5,6,14],"input":[3,4,7,17,19,20],"insert":[3,4,18],"insid":[3,4,6,19,20],"insight":[5,9,14],"inspect":[2,5,6,14,19],"inspir":[5,14],"instal":[0,6],"instanc":5,"instanti":[5,14,16],"instead":[2,3,4,6,16,20],"instruct":[2,3,4],"int":[5,7,9,14,15,17,18,19,20],"integr":[0,3,4,5,15],"intellectu":9,"intellig":[3,4,5],"intend":[3,6,13],"intention":[7,19],"interact":[0,5,9,12,14],"interfac":[4,5,11,12,14,20],"interpret":[16,20],"interv":19,"introduc":[],"introduct":0,"invalid":5,"invok":[3,4,12,16],"involv":20,"is_connect":[8,20],"isol":11,"item":[3,4,7,19],"iter":[3,4,5,9,14,19],"iterative_refin":17,"its":[1,3,4,5,7,8,9,11,14,19,20],"itself":5,"januari":[3,4],"job":[19,20],"join":7,"json":[3,4,15,19,20],"jsonifi":20,"jsonrespons":20,"keep":[3,4,6,7,8,9,12,19],"kei":[3,4,9,10,15,17],"kept":5,"key_cont":10,"key_fil":10,"keyword":[2,4,5,8,19],"kind":1,"knowledg":9,"known":[7,16],"kwarg":[5,14],"l2_squar":19,"languag":[2,3,4,5,6,9,12,14,15,16,19],"larg":[5,14],"larger":[1,5,19],"last":5,"latenc":20,"later":[5,10,14],"layer":[3,4],"learn":[3,4,5,9],"leav":[7,19,20],"led":[5,14],"len":7,"length":[6,9,17],"less":15,"let":[3,4,5,14,19,20],"level":[5,12,19],"leverag":[3,4,5],"li":9,"liabil":1,"liabl":1,"librari":[8,10,13,16],"licens":1,"licensor":1,"life":[5,14],"lifecycl":[0,9,19,20],"lifespan":20,"lightweight":20,"like":[3,4,8],"limit":[1,3,4,17,20],"line":[7,11,12,19,20],"link":[3,4,19],"list":[0,1,2,6,7,13,17,18],"listen":[],"live":20,"llama":[3,4,16],"llama_4_maverick":[3,4],"llm":[2,3,4,5,9,14,15,16,17,18],"llm_chat_tool":[3,4],"llm_config":[3,4],"load":[3,4,8,19,20],"local":[5,8,11,14,20],"localhost":20,"locat":[3,4,6,17,19],"location_uri":[5,14,17],"log":19,"logic":4,"long":[5,7,8,12,14,17,20],"longer":[5,9,10,14,19,20],"loop":6,"low":[17,18,20],"lower":15,"lower_port":13,"lrgrwrk":1,"m":[8,11,20],"machin":[3,4,5],"made":[1,7,9],"mai":[3,4,7,20],"mail":13,"main":[3,4,5,7,9,10,13,16,17,18,19],"maintain":[3,4],"major":14,"make":[1,5,10,13,14,18,19],"makefil":11,"manag":[5,9,13,15,17,19,20],"manhattan":19,"mani":[2,5,6,7,12,14,16,18],"manifest":19,"manipul":5,"manner":[5,9],"manual":[5,9,19],"map":[3,4,5,7,14,15,18],"map_reduc":17,"mapped_sql":[5,14],"match":[3,4,5,7,14,19,20],"match_limit":19,"materi":12,"mathemat":[5,14],"maverick":[3,4],"max_siz":[7,8,20],"max_token":[5,14,15,19],"max_word":17,"max_work":7,"maximum":[7,17,19],"mean":[15,19],"meant":3,"meanwhil":[5,14],"measur":20,"medium":[17,18],"memori":[5,14],"merchant":1,"merg":[5,14],"messag":[],"meta":[3,4],"metadata":[9,14,15,18,19,20],"method":[0,3,4,5,8,9,13,14,16,17,19,20],"metric":19,"microsoft":14,"milki":[5,14],"min_siz":[7,8,20],"min_word":17,"minimum":[1,17,19],"minut":19,"mirror":[4,9,19],"misconcept":9,"miss":[9,19],"mission":[3,4],"mistak":9,"mix":20,"ml":[3,4,5],"mlenv":19,"mode":0,"model":[0,5,12,15,16,17,18],"modul":[0,7,12],"more":[3,4,5,9,13,14,15,17,18,19,20],"most":[2,3,4,8,12,15,16],"move":[3,4],"movement":[3,4],"movi":[3,4,6,18],"movie_agent_team":[3,4],"movie_analyst":[3,4],"movie_sql_tool":[3,4],"mtl":20,"much":[5,14,15],"multi":[0,3,7,8,12,20],"multipl":[3,4,5,7,8,9,14,18,19],"multit":[],"music":[3,4],"must":[1,3,4,7,10,15,17,18,19],"my":[3,4,5,14,16,19],"my_oci_ai_profile_kei":[3,4,5,10,14,15,19],"myapp":20,"myappconfig":20,"myrenv":19,"mysteri":[3,4,5,14],"n":[6,17,19],"nad":5,"name":[3,4,5,6,7,10,13,14,15,16,18,19,20],"namespac":[6,17],"narr":12,"narrat":[0,2,5,6,9,12,19],"natur":[2,3,4,5,6,9,12,14,15,16,19],"need":[2,3,4,5,6,7,9,10,11,12,13,14,15,16,18,19],"neg":[5,14,15],"neither":17,"network":[0,3,4,5,10,11,12,14,16,19],"new":[3,4,5,8,9,14,19],"next":[5,6,7,19],"night":[3,4,5,14],"non":[5,6,14,15,16,19],"none":[3,4,5,7,9,14,15,16,17,18,19],"noninfring":1,"normal":20,"note":[5,6],"notebook":[8,12,19],"notic":1,"notif":[3,4],"notification_typ":[3,4],"notificationtyp":3,"nprompt":7,"null":[5,14],"number":[5,6,9,14,15,17,18,19],"number_of_promot":5,"numer":[5,14],"o":[3,4,5,6,7,8,9,10,11,13,14,16,17,18,19,20],"object":[0,2,3,4,5,6,8,10,12,16,18,20],"object_list":[3,4,5,14,15,16,18,19],"object_list_mod":[5,14,15,19],"object_nam":18,"object_storage_credential_nam":[3,4,19],"object_store_cr":[6,17],"object_store_credenti":19,"objectstor":19,"objectstorag":[6,17,19],"observ":[5,14],"obtain":1,"occur":[9,19],"oci":[2,3,4,5,6,10,14,15,16,19],"oci_ai_profil":[2,3,4,5,6,7,9,14,17,18,20],"oci_apiformat":[3,4,5,14,15,16,19],"oci_compartment_id":[5,14,16,19],"oci_endpoint_id":[5,14,16,19],"oci_genai_cr":10,"oci_runtimetyp":[5,14,16,19],"oci_vector_ai_profil":[5,14,19],"ocid":16,"ocigenaiprovid":[0,3,4,5,14,15,19],"off":[8,9],"offer":[1,3,4,5,14,16],"older":[5,14],"omf":5,"omit":[3,4,9,19],"oml":5,"oml4pi":5,"onc":[12,20],"one":[1,2,3,4,5,6,7,8,9,13,14,16,17,18,19,20],"onli":[3,5,6,14,15,19,20],"open":[3,4,8,10,20],"open_ai_api_kei":[3,4],"open_ai_credential_nam":[3,4],"open_ai_profile_nam":[3,4],"openai":[0,10,16],"openai_cr":[3,4,10],"openai_profil":[3,4],"openaiprovid":[0,3,4,15],"oper":[3,4,6,8,13,20],"operation":[3,4],"optic":[5,14],"option":[0,3,4,7,9,11,12,15,16,17,18,20],"ora":[5,13],"oracl":[0,1,3,4,5,10,11,12,13,14,16,19,20],"oraclecloud":[17,19],"oracledb":[5,8,11,14,19,20],"oraclevectorindexattribut":0,"orchestr":3,"order":[3,7],"ordereddict":[3,4],"ordinari":20,"org":[5,14,17],"organ":[3,4],"origin":[5,14,17,19],"ot":4,"other":[1,3,4,7,12,14,19,20],"otherwis":[1,3,4],"our":[5,14],"out":1,"outbound":13,"outlin":3,"output":[2,3,4,5,6,9,10,13,14,16,17,18,19],"outsid":[3,4],"over":[3,5,7,9,12,14,19],"overal":[5,14],"overlap":19,"overrid":6,"overwhelm":20,"own":[1,7,8,10,18,20],"owner":[3,4,5,14,15,16,18],"owner_nam":18,"p":[5,14],"packag":[0,3,6,10,11,12,13,20],"page":[3,4],"pair":[3,7],"panda":[2,5,11,12,14],"paragraph":17,"parallel":18,"param":[3,4,5,14,17,18],"paramet":[0,3,4,5,8,9,14,15,16,19,20],"part":7,"parti":12,"particular":1,"pass":[3,4,5,6,8,9,10,14,15,17,19,20],"password":[3,4,5,6,7,8,9,10,11,13,14,16,18,19,20],"past":9,"patent":1,"path":[5,8,13,14],"pattern":[0,3,4,5,6,7,12,14,19],"paus":[3,4,19],"pdb3":19,"per":[5,6,8,14,15,17,20],"perform":[1,2,3,4,5,14,18,19],"period":9,"permiss":[1,13],"permit":16,"persist":3,"person":1,"pformat":[3,4,5,14],"phenomena":[5,14],"physic":[5,14],"piec":1,"pile":20,"pint":[5,14],"pip":[6,11,20],"pipelin":[0,7,19],"pipeline_nam":19,"pitfal":9,"pl":[0,3,4,8,13,18],"place":20,"placehold":[3,4],"plan":[3,11],"platform":[14,20],"plu":16,"point":17,"pool":[0,5,12,19],"pool_incr":[7,20],"pool_max":[7,20],"pool_min":[7,20],"pop":20,"popul":[18,19],"port":[13,16,20],"portabl":[3,4],"portion":1,"posit":[5,14],"possibl":[7,18,20],"potenti":2,"power":5,"powershel":11,"pprint":[3,4,5,14],"prebuilt":[3,4],"predict":[3,4,15],"prefer":[9,19,20],"prepar":13,"present":17,"preserv":19,"press":20,"pressur":[5,14],"prevent":[5,14,20],"preview":12,"previou":[3,4,9],"previous":19,"primari":15,"primarili":[3,4],"print":[2,3,4,5,6,7,9,10,11,13,14,16,17,19],"prior":[3,9],"prioriti":18,"privaci":[3,4],"private_kei":10,"private_key_cont":10,"privileg":[3,5,10,11,12,14,16,18,19],"procedur":[3,4,19],"process":[3,4,8,12,16,17,19,20],"processor":7,"produc":7,"product":[3,4,5,7,15,16,18,19,20],"profil":[2,3,4,7,8,9,10,12,16,17,18,19,20],"profile_attribut":[3,4,5,14,19],"profile_nam":[2,3,4,5,7,9,14,16,17,18,19,20],"profile_name_pattern":[5,14],"profileattribut":[0,3,4,5,14,16,19],"profileemptyattributeserror":14,"profileexistserror":14,"profilenotfounderror":[5,14,19],"program":[5,12],"progress":[5,14],"project":11,"promo_id":[5,14],"promot":[2,3,4,5,7,14],"promotion_count":5,"prompt":[2,3,4,6,8,9,12,15,16,17,18,19,20],"prompt_spec":[5,14],"prompt_specif":[5,7],"properti":3,"protocol":13,"prototyp":18,"provid":[1,2,3,4,5,6,7,8,9,11,12,13,14,15,17,18,19,20],"provider_endpoint":[5,14,16,19],"provider_nam":[5,14,16,19],"providerattribut":[5,14],"proxi":[3,4,5,9,11,14,19,20],"ps1":11,"public":[3,4,19,20],"purpos":[1,3,6,12,15],"put":7,"py":[0,11,20],"pypi":11,"python":[0,1,3,4,5,6,7,8,11,14,19],"python3":11,"quart":20,"quarterli":9,"queri":[2,3,4,5,9,15,19],"question":[3,4,5,9,12],"queu":7,"queue":7,"quick":6,"quickli":8,"quit":6,"quot":5,"r":[3,4,11,16,19],"radio":[5,14],"rag":[0,3,4,6,12,20],"rai":[5,14],"rais":[3,4,5,10,14,17,19],"raise_error_if_exist":14,"raise_error_on_empty_attribut":14,"random":15,"rang":[3,4,5,7,13,14],"rate":19,"rather":19,"reach":13,"read":[3,4,5,6,8,9,10,13,14,19],"readabl":9,"readi":[7,20],"reason":[3,4,9,16],"receiv":[7,16],"recip":0,"recipi":[3,4],"recommend":11,"record":[18,19],"record_count":18,"recreat":[3,4,5,10,14,19],"reduc":[5,14,20],"refer":[1,5,9,10,16],"referenc":[2,3,4,5,14,18],"referenti":15,"refresh":19,"refresh_r":19,"regard":14,"regexp_lik":[3,4,5,14,19],"region":[3,4,5,12,14,15,16,19],"regist":[3,4,12,20],"regress":[3,4],"regular":[3,4,5,6,14,19],"relat":[3,4,19],"releas":[3,4,6,8,18,20],"relev":[9,15,19],"remain":[5,9,14],"remov":[5,9,13,14,16,19],"remove_host_ac":13,"repair":5,"rephras":17,"repl":[],"replac":[3,4,5,10,14,16,19],"replai":9,"replet":9,"report":[15,19],"repositori":11,"repres":[9,14,18,19],"request":[0,3,4,5,8,14,18,19],"requir":[0,3,4,5,6,10,12,13,14,17,19,20],"research":[3,4,5,9,14],"resid":[3,4,19],"resourc":[16,18],"respond":[3,4],"respons":[3,4,5,6,9,14,15,16,19,20],"rest":20,"restrict":[1,15],"result":[2,3,4,5,6,7,12,14,19],"resum":[3,4,19],"retain":[6,9],"retent":9,"retention_dai":9,"retriev":[5,12,15,19],"return":[2,3,4,5,6,7,9,12,14,15,19,20],"reus":[0,3,4],"reusabl":12,"revok":0,"revoke_http_access":16,"revoke_network_access":13,"revoke_privileg":13,"rich":0,"right":[1,3],"robust":[3,4],"role":[3,4],"romanc":[3,4],"round":[5,7],"roundtrip":5,"rout":20,"row":[5,18],"run":[0,6,7,8,9,10,11,12,13,16,18,19,20],"run_pipelin":[5,7],"run_sql":[2,5,14],"runsql":[2,7,14],"runtim":[2,16],"sagittariu":[5,14],"sale":[1,7,9,15,16],"same":[3,4,5,6,7,8,9,10,12,13,14,20],"sampl":[3,4,7,8,13,18],"sample_row":18,"sanic":20,"save":[5,6,14],"scalabl":[3,4,5],"scale":[3,4],"schedul":19,"schema":[3,4,5,10,13,14,15,18],"sci":[3,4],"scienc":[5,9,14],"scientif":9,"scientist":[3,4,9],"scope":[5,12,14],"score":19,"script":[5,7,8,11,12,13,19,20],"seamlessli":[3,4],"search":[0,5,14,19],"second":[5,9,14,20],"secret":[10,12,20],"secur":[3,4,5,10,12],"see":[3,5,11,12,14,16,18,19,20],"seed":[5,14,15,19],"seek":[5,14],"select":[0,1,5,6,8,9,10,11,13,14,15,16,17,18,19,20],"select_ai":[2,3,4,5,6,7,8,9,10,12,13,14,15,16,17,18,19],"select_ai_admin_password":[13,16],"select_ai_admin_us":[13,16],"select_ai_agent_nam":[3,4],"select_ai_connection_test":11,"select_ai_db_connect_str":[3,4,5,6,7,8,9,10,11,13,14,16,18,19,20],"select_ai_db_password":[7,11,13,20],"select_ai_db_us":[7,11,13,16,20],"select_ai_max_work":7,"select_ai_password":[3,4,5,6,7,8,9,10,11,13,14,18,19,20],"select_ai_pool_incr":[7,20],"select_ai_pool_max":[7,20],"select_ai_pool_min":[7,20],"select_ai_profile_nam":[3,4,7],"select_ai_task_nam":[3,4],"select_ai_team_nam":[3,4],"select_ai_tool_nam":[3,4],"select_ai_us":[3,4,5,6,7,8,9,10,11,13,14,16,18,19,20],"select_ai_wallet_loc":6,"select_ai_wallet_password":6,"select_ai_worker_count":7,"self":[5,20],"sell":1,"semant":19,"send":[3,5,7,14,15,18],"sender":[3,4],"sensit":[5,15],"sent":[2,3,4,5,7,14,15,16,18],"separ":[7,13,16,19],"sequenc":15,"sequenti":[3,4],"seri":[3,4,9],"serializ":[3,4],"serv":[3,4],"server":[3,4,13,20],"servic":[0,3,4,5,7,8,10,12,14,20],"session":[0,3,4,5,6,12,14],"set":[1,3,4,5,6,9,11,14,15,17,18,19,20],"set_attribut":[0,3,4,5,9,14,19],"setup":[3,13],"sever":[5,9,12,14,19],"sh":[5,14,15,16,18],"shall":1,"shape":9,"share":[3,4,6,18,20],"shell":6,"short":8,"shot":6,"should":[2,3,4,5,7,8,9,10,12,13,14,15,16,17,18,19,20],"show":[0,2,3,4,6,8,9,10,12,18],"show_prompt":[2,5,14],"show_sql":[2,5,7,9,14,16,20],"shown":8,"showprompt":2,"showsql":[2,5,7],"shut":20,"shutdown":[12,20],"side":18,"signific":9,"similar":[3,19],"similarity_threshold":19,"similarli":13,"simpl":[6,12,20],"simul":5,"sinc":[5,14],"sing":[],"singl":[0,3,4,5,7,13,14,19,20],"size":[0,6,8,19],"sk":10,"sky":[5,14],"slack":[3,4],"slack_channel":[],"slow":20,"small":20,"smoke":0,"smtp":[3,4,13],"smtp_host":[3,4],"so":[3,5,6,8,9,11,14,20],"social":9,"societi":9,"softwar":1,"sold":1,"solid":[5,14],"solver":[3,4],"some":[5,9,14],"sonnet":16,"soon":[5,7],"sourc":[3,4,5,6,11,12,13,14,15,17,19,20],"source_languag":[5,14],"source_team":[3,4],"spare":20,"special":[3,4],"specif":[3,4,6,12,13,14,15,16,19],"specifi":[3,4,5,13,14,15,16,17,19],"speed":[3,4],"sphinx":11,"split":[5,14,17,19],"sport":[3,4],"sql":[0,2,3,4,7,8,12,13,15,16,18,20],"sql_id":[5,14],"sql_task":5,"sql_tool":[3,4],"sqltoolparam":[3,4],"stabil":[],"stand":[5,14],"standalon":[8,12,20],"star":[5,14],"starlett":20,"start":[3,4,5,6,7,12,14,19,20],"startup":[12,20],"state":[3,4],"statement":[2,3,4,14],"statist":18,"step":[3,4,12,13,19],"still":19,"stop":[15,20],"stop_token":[5,14,15,19],"storag":[0,3,4,5,6,12,14,19,20],"store":[3,4,5,9,10,12,14,16,19,20],"stori":[3,4],"str":[2,3,4,5,7,9,14,15,16,18,19,20],"strategi":3,"stream":[0,6,15,19,20],"string":[3,4,5,15],"structur":[3,4],"studi":[5,9,14],"style":[0,5,12,17,20],"subcommand":6,"subject":[1,3,4],"sublicens":1,"submit":7,"subprogram":8,"substanti":1,"succe":[3,4,5,10,11,14,19],"summar":[0,2,6,12,17],"summari":[2,3,4,5,12,14],"summarize_movie_task":3,"summary_styl":17,"summaryparam":[0,5,14],"summarystyl":0,"sun":[5,14],"suppli":[3,17],"support":[0,4,5,6,7,14,15,16,17,18,19],"sure":[5,10,14,18,19],"sync":[0,7,8],"sync_ordered_result":0,"sync_queue_work":0,"sync_thread_pool":0,"synchron":[0,4,5,7,9,14,18,19],"synthet":[5,12,14],"synthetic_data_attribut":[5,14,18],"synthetic_data_param":18,"syntheticdataattribut":[0,5,14],"syntheticdataparam":0,"system":[9,11,19],"t":5,"tabl":[0,2,3,5,6,10,12,14,15,19],"table_statist":18,"tabular":2,"tail":20,"take":20,"taken":19,"target":[3,4,5,6,7,10,11,13,14,17,18],"target_languag":[5,14],"task":[0,5,7,8,12,18],"task_attribut":[3,4],"task_don":7,"task_nam":[3,4],"task_name_pattern":[3,4],"taskattribut":[0,3,4],"team":[0,12],"team_nam":[3,4],"team_name_pattern":[3,4],"teamattribut":[0,3,4],"teardown_appcontext":20,"technic":[],"technologi":[3,4,5,14],"temperatur":[5,14,15,19],"temporari":9,"tenanc":10,"tenancy_ocid":10,"tenant1":19,"term":1,"termin":[6,15,20],"test":[0,6,18,19],"test_vector_index":19,"text":[2,3,4,5,6,12,14,15,16,17,19,20],"than":[5,14,19,20],"thank":[5,6,14],"thei":7,"them":[3,5,6,10,14,20],"theoret":[5,14],"thi":[1,2,3,4,5,7,8,9,10,11,13,14,15,16,17,18,19,20],"thin":[3,8],"thing":5,"third":12,"those":8,"thread":[7,20],"threadpoolexecutor":7,"thriller":[3,4],"through":[3,6,9,11,20],"time":[3,4,6,7,9],"timedelta":9,"timeout":20,"timestamp":19,"titl":[3,4,9],"tl":8,"tns_admin":[13,20],"togeth":[3,4,19],"token":[15,17],"tool":[0,6,7,10,12,16,19,20],"tool_input":[3,4],"tool_nam":[3,4],"tool_name_pattern":[3,4],"tool_param":[3,4],"tool_typ":[3,4],"toolattribut":[0,3,4],"toolparam":[0,3,4],"tooltyp":[3,4],"top":7,"topic":[3,4,9],"tort":1,"total":[5,7,8,20],"touch":[5,14],"train":[3,4],"transcript":9,"transform":16,"translat":[0,2,3,4,6,12,15],"trillion":[5,14],"trip":[5,7],"true":[2,3,4,5,7,9,10,14,15,16,18,19],"trust":12,"try":[6,7],"tune":[2,3,4,5,14,15],"tupl":[5,14],"twenti":20,"two":[13,19],"txt":[1,6,11,17],"type":[2,3,4,5,6,16,19],"typic":[5,9,19],"u":[3,4,5,9,14,15,16,17,19],"ultraviolet":[5,14],"under":[1,3,4,6,16,20],"underli":[5,14,19],"understand":[5,9,14,19],"union":[5,14,19],"uniqu":[3,5,14],"unit":19,"univers":[1,5,14],"unless":[5,7,9,19,20],"unmodifi":1,"unset":19,"until":[9,20],"up":[3,4,7,9,20],"upcom":6,"updat":[0,9,15],"updated_attribut":19,"upgrad":11,"upl":1,"upper_port":13,"uri":[0,2,3,4,5,6,14,19],"url":[3,4,5,14,16,17],"us":[0,1,2,5,6,7,8,9,10,11,12,13,14,15,17,18],"usag":[5,9],"user":[2,3,4,5,6,7,8,9,10,11,13,14,16,18,19,20],"user_ocid":10,"user_prompt":18,"user_queri":[3,4],"usernam":[3,4,10,16],"usual":[3,5,9,14,19,20],"utc":19,"util":[3,4],"uuid":[3,4],"uuid4":[3,4],"uvicorn":20,"v":[5,14],"v1":16,"v3":19,"valid":[0,6,15,20],"validate_config":10,"valu":[3,4,5,6,8,9,10,14,15,16,17,18,19,20],"valuabl":9,"vari":16,"variabl":[0,3,4,6,8,11,13,20],"varieti":[3,4],"variou":[3,4,5,14],"vecpipelin":19,"vector":[3,4,6,8,10,12,15,16],"vector_db_credential_nam":19,"vector_db_endpoint":19,"vector_db_provid":19,"vector_dimens":19,"vector_distance_metr":19,"vector_index":19,"vector_index_attribut":19,"vector_index_nam":[5,14,15,19],"vector_table_nam":19,"vectordbprovid":19,"vectordistancemetr":19,"vectorindex":[0,3,4],"vectorindexattribut":0,"vectorindexnotfounderror":19,"venv":11,"verifi":11,"version":[0,1,11],"versu":17,"via":[5,14],"view":[5,6,14,15,20],"virtual":11,"visibl":[5,6,9,14,19],"wa":19,"wai":[5,14,20],"wait":[0,3,4,5,6,7,19],"wait_for_complet":19,"wait_timeout":20,"waiting_for_human":[3,4],"wallet":[0,6,20],"wallet_loc":8,"wallet_password":8,"want":[2,3,4,5,6,10,11,14,19],"war":[3,4],"warranti":1,"water":[5,14],"wave":[5,14],"we":[3,4,5,10],"web":[8,12,14],"web_search_ag":[3,4],"web_search_task":[3,4],"web_search_team":[3,4],"web_search_tool":[3,4],"websearch":[3,4],"websit":[3,4],"were":[9,13],"western":[3,4],"what":[0,2,3,4,5,6,9,14,15,17,20],"when":[2,4,5,6,7,9,10,13,14,15,16,17,18,19,20],"where":[3,4,5,7,9,11,14,19,20],"whether":[1,3,4,6,8,15,19],"which":[0,1,3,4,5,8,9,14,15,16,17,19],"while":[5,7,9,10,14,16,19],"while_serv":20,"who":[6,13,18],"whose":3,"why":9,"wide":[3,4,14,20],"wiki":[5,14,17],"wikipedia":[5,14,17],"window":11,"wire":3,"within":[3,4,5,19],"without":[1,2,3,4,5,6,7,8,9,10,14,19],"word":17,"work":[1,3,4,6,7,8,12,18,20],"worker":[7,8,20],"worker_count":7,"worker_exit":20,"workflow":[0,3,4,5,6,9,12,15],"workload":[3,4,7,12,13,20],"world":[3,4],"wrap":13,"write":[3,4,5,6,18],"written":[3,4],"wsgi":20,"www":[3,4],"x":[5,14,16],"xai":16,"xai_api_kei":16,"xai_credenti":16,"xai_profil":16,"xxx":10,"yield":20,"you":[0,2,3,4,5,6,8,9,10,11,14,15,16,17,19,20],"your":[3,4,7,10,11,16,19,20],"your_db_dsn":8,"your_db_password":8,"your_db_us":8,"zip":7,"\u00aa":1,"\u00b2":1,"\u00b3":1,"\u00b5":1,"\u00b9":1,"\u00ba":1,"\u00bc":1,"\u00bd":1,"\u00be":1,"\u03c9":1,"\u215b":1,"\u215c":1,"\u215d":1,"\u215e":1},"titles":["select_ai documentation","<no title>","1. Supported Actions","1. Tool","1. AsyncTool","1. Async profile lifecycle","1. Command line interface","1. Concurrent prompt processing","3. Connecting to Oracle Database","1. Conversation Object model","1. Create credential","2. Installing select_ai","1. Introduction to Select AI for Python","1. Grant privilege","1. Profile lifecycle","1. ProfileAttributes","1. Provider","1. Inline content","1. Generation modes","1. Vector Index","1. Using select_ai with Python web frameworks"],"titleterms":{"":[3,4],"access":13,"action":[0,2,5,14],"agent":[0,3,4],"ai":[0,2,3,4,10,12,16],"an":2,"anthropicprovid":16,"api":[4,5,9,10,12,14,16,18,19],"async":[0,4,5,9,10,16,17,18,19],"async_as_complet":7,"async_gath":7,"async_pipelin":7,"async_queue_work":7,"asyncag":4,"asyncconvers":9,"asynchron":[5,8,12,20],"asyncprofil":5,"asynctask":4,"asyncteam":4,"asynctool":4,"asyncvectorindex":19,"attribut":[0,15,19],"awsprovid":16,"azureprovid":16,"base":14,"behavior":20,"build":12,"can":12,"chat":[5,6,9,14],"choos":2,"chunkprocessingmethod":17,"class":16,"cli":6,"cohereprovid":16,"command":[0,6],"common":[5,14,15],"complet":[],"concept":12,"concurr":[0,5,7],"connect":[6,8,11],"content":17,"control":15,"convers":[0,9],"conversationattribut":9,"core":12,"creat":[3,4,9,10,14,19],"creation":5,"credenti":[0,10],"data":[0,18],"databas":8,"delet":[5,9,10,14,19],"depend":[11,20],"disabl":16,"django":20,"document":[0,11],"each":3,"enabl":16,"endpoint":20,"environ":7,"exampl":[2,3,4,15,16,20],"expect":10,"explain":[5,14],"export":[3,4],"extractivenesslevel":17,"fastapi":20,"fetch":19,"flask":20,"format":10,"framework":[0,20],"from":17,"gener":[15,18],"get":0,"googleprovid":16,"gpt":[3,4],"grant":13,"group":15,"handl":20,"health":8,"helper":[3,4],"huggingfaceprovid":16,"import":[3,4],"index":[0,19],"inlin":17,"input":[],"instal":[11,20],"interact":6,"interfac":[0,6],"introduct":12,"lifecycl":[3,4,5,14],"line":[0,6],"list":[3,4,5,9,14,15,19],"map":2,"method":2,"mode":18,"model":[3,4,9,14,19],"multi":18,"narrat":14,"network":13,"object":[9,14,15,17,19],"ocigenaiprovid":16,"openai":[3,4],"openaiprovid":16,"option":6,"oracl":8,"oraclevectorindexattribut":19,"order":[],"paramet":[17,18],"pattern":20,"pipelin":5,"pool":[7,8,20],"privileg":[0,13],"process":[0,7],"profil":[0,5,6,14,15],"profileattribut":15,"prompt":[0,5,7,14],"provid":[0,10,16],"py":7,"python":[12,20],"queue":[],"rag":19,"recip":7,"repl":6,"request":20,"requir":[11,15],"reus":[5,14],"revok":13,"run":[3,4,5,14],"search":[3,4],"select":[2,3,4,12],"select_ai":[0,11,20],"servic":16,"session":9,"show":[5,14],"sing":[],"singl":18,"size":[7,20],"smoke":11,"sql":[5,6,14],"start":0,"storag":17,"stream":[2,5,14],"summar":[5,14],"summari":[0,6,7,17],"summaryparam":17,"summarystyl":17,"support":[2,3,12],"sync":[4,10,16,18],"sync_ordered_result":7,"sync_queue_work":7,"sync_thread_pool":7,"synchron":[8,12,20],"synthet":[0,18],"syntheticdataattribut":18,"syntheticdataparam":18,"tabl":18,"task":[3,4],"team":[3,4],"test":11,"tool":[3,4],"translat":[5,14],"updat":[5,14,19],"uri":17,"us":[3,4,16,19,20],"valid":17,"variabl":7,"vector":[0,19],"vectorindex":19,"vectorindexattribut":19,"version":12,"wait":20,"wallet":8,"web":[0,3,4,20],"what":12,"when":3,"worker":[],"you":12}}) diff --git a/docs/user_guide/actions.html b/docs/user_guide/actions.html index 711668d..e440f87 100644 --- a/docs/user_guide/actions.html +++ b/docs/user_guide/actions.html @@ -5,14 +5,14 @@ - 1. Supported Actions — Select AI for Python 1.3.0 documentation + 1. Supported Actions — Select AI for Python 1.4.0rc1 documentation - + - + @@ -60,6 +60,19 @@ +

    Previous topic

    Navigation

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • @@ -144,10 +157,16 @@

    Navigation

    -

    An action in Select AI is a keyword that instructs Select AI to perform different behavior when acting on the prompt.

    +

    An action in Select AI is a keyword that instructs Select AI to perform +different behavior when acting on the prompt.

    +

    Most applications use the convenience methods on Profile or +AsyncProfile, such as show_sql(), run_sql(), narrate(), and +chat(). Use generate(..., action=...) when you want to choose the +action dynamically at runtime.

    +

    The default action for generate() is select_ai.Action.RUNSQL.

    1. Supported Actions

    -

    Following list of actions can be performed using select_ai

    +

    The following actions can be performed using select_ai:

    @@ -156,7 +175,7 @@

    1. Supported Actions

    - + @@ -164,23 +183,25 @@

    1. Supported Actions

    - + - + - + - + - + @@ -188,18 +209,123 @@

    1. Supported Actions

    - + - + - +
    Select AI Actions

    Actions

    Action

    Enum

    Description

    chat

    select_ai.Action.CHAT

    Enables general conversations with the LLM, potentially for clarifying prompts, exploring data, or generating content.

    Enables general conversations with the LLM, potentially for clarifying +prompts, exploring data, or generating content.

    explainsql

    select_ai.Action.EXPLAINSQL

    Explain the generated SQL query

    Explains the generated SQL query.

    narrate

    select_ai.Action.NARRATE

    Explains the output of the query in natural language, making the results accessible to users without deep technical expertise.

    Executes generated SQL and explains the output in natural language.

    runsql

    select_ai.Action.RUNSQL

    Executes a SQL query generated from a natural language prompt. This is the default action.

    Executes SQL generated from a natural language prompt. This is the +default action for generate().

    showprompt

    select_ai.Action.SHOWPROMPT

    Show the details of the prompt sent to LLM

    Shows the prompt sent to the LLM.

    showsql

    select_ai.Action.SHOWSQL

    summarize

    select_ai.Action.SUMMARIZE

    Generate summary of your large texts

    Generates a summary of inline content or content referenced by a URI.

    feedback

    select_ai.Action.FEEDBACK

    Provide feedback to improve accuracy of the generated SQL

    Provides feedback to improve the accuracy of generated SQL.

    translate

    select_ai.Action.TRANSLATE

    Translate text from one language to another

    Translates text from one language to another.

    +
    +

    1.1. Action methods

    + + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Action to method mapping

    Action

    Convenience method

    Return type

    RUNSQL

    profile.run_sql(prompt)

    pandas.DataFrame

    SHOWSQL

    profile.show_sql(prompt)

    str

    EXPLAINSQL

    profile.explain_sql(prompt)

    str

    NARRATE

    profile.narrate(prompt)

    str

    CHAT

    profile.chat(prompt)

    str

    SHOWPROMPT

    profile.show_prompt(prompt)

    str

    SUMMARIZE

    profile.summarize(...)

    str

    TRANSLATE

    profile.translate(...)

    str

    +
    +
    +

    1.2. Choosing an action

    +

    Use show_sql before run_sql when you want to inspect generated SQL +before executing it. Use run_sql when the application should return a +tabular result. Use narrate when users need a natural language answer +instead of a table. Use explain_sql and show_prompt when tuning profile +attributes, object lists, comments, constraints, or feedback.

    +
    +
    +

    1.3. Examples

    +

    Use a convenience method:

    +
    profile = select_ai.Profile(profile_name="oci_ai_profile")
    +sql = profile.show_sql(prompt="How many promotions?")
    +
    +
    +

    Use generate with an explicit action:

    +
    profile = select_ai.Profile(profile_name="oci_ai_profile")
    +
    +sql = profile.generate(
    +    prompt="How many promotions?",
    +    action=select_ai.Action.SHOWSQL,
    +)
    +
    +df = profile.generate(
    +    prompt="How many promotions?",
    +    action=select_ai.Action.RUNSQL,
    +)
    +
    +
    +

    Use an action selected at runtime:

    +
    action = select_ai.Action("showsql")
    +result = profile.generate(
    +    prompt="How many promotions?",
    +    action=action,
    +)
    +
    +
    +
    +
    +

    1.4. Streaming

    +

    Streaming is supported for text-returning generation actions: +CHAT, NARRATE, EXPLAINSQL, SHOWSQL, and SHOWPROMPT. +Streaming is not supported for RUNSQL because it returns a +pandas.DataFrame.

    +
    for chunk in profile.generate(
    +    prompt="What is OCI?",
    +    action=select_ai.Action.CHAT,
    +    stream=True,
    +    chunk_size=4096,
    +):
    +    print(chunk, end="")
    +
    +
    +
    @@ -209,6 +335,19 @@

    1. Supported Actions

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • diff --git a/docs/user_guide/agent.html b/docs/user_guide/agent.html index 2db8dcc..539e709 100644 --- a/docs/user_guide/agent.html +++ b/docs/user_guide/agent.html @@ -5,21 +5,21 @@ - 1. Tool — Select AI for Python 1.3.0 documentation + 1. Tool — Select AI for Python 1.4.0rc1 documentation - + - + - + @@ -64,7 +64,8 @@

    Table of Contents

    Previous topic

    1. SummaryParams

    + title="previous chapter">1. Inline content

    Next topic

    @@ -193,7 +198,7 @@

    Navigation

    next |
  • - previous |
  • Python logo
  • Python »
  • @@ -203,7 +208,7 @@

    Navigation

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • @@ -238,20 +243,41 @@

    Navigation

    select_ai.agent adds a thin Python layer over Oracle Autonomous Database’s DBMS_CLOUD_AI_AGENT package so you can define tools, compose tasks, wire up -agents and run teams from Python using the existing select_ai connection objects

    +agents and run teams from Python using the existing Select AI connection +objects.

    • Keep agent state and orchestration in the database

    • Register callable tools (PL/SQL procedure or functions, SQL, external HTTP endpoints, Slack or Email notifications) and attach them to tasks

    • Group agents into teams and invoke them with a single API call

    +

    Agent workflows build on the same setup used by profiles: connect to Oracle +Database, create or reuse a Select AI profile, create credentials for any +external service used by tools, and grant network access for external +endpoints. See Connection, Profile, +Credential, and Privileges.

    +

    The usual agent workflow is:

    +
      +
    • Create tools that an agent can use.

    • +
    • Create tasks that describe the work and list the tools available for that +task.

    • +
    • Create an agent with a role and an LLM profile.

    • +
    • Create a team that pairs agents with tasks.

    • +
    • Run the team with a user prompt.

    • +
    +

    Tools, tasks, agents, and teams are database objects. Use replace=True when +you want to recreate an existing object with the same name, and force=True +when cleanup should succeed even if the object does not exist.

    -

    Tool

    +

    1. Tool

    A callable which Select AI agent can invoke to accomplish a certain task. Users can either register built-in tools or create a custom tool using a PL/SQL stored procedure.

    +

    Use focused tools with clear instructions. The task and agent prompts decide +when tools are used, so tool names, descriptions, and instructions should be +specific enough for the model to choose the right tool.

    -

    Supported Tools

    +

    1.1. Supported Tools

    Following class methods of select_ai.agent.Tool class can be used to create tools. Invoking them will create a proxy object in the Python layer and persist the tool in the Database using @@ -281,16 +307,7 @@

    Supported Tools

    HTTP

    select_ai.agent.Tool.create_http_tool

      -
    • tool_name

    • -
    • credential_name

    • -
    • endpoint

    • -
    -

    SQL

    SQL

    select_ai.agent.Tool.create_sql_tool

    • tool_name

    • @@ -298,16 +315,16 @@

      Supported Tools

    SLACK

    SLACK

    select_ai.agent.Tool.create_slack_notification_tool

    • tool_name

    • credential_name

    • -
    • slack_channel

    • +
    • channel

    WEBSEARCH

    WEBSEARCH

    select_ai.agent.Tool.create_websearch_tool

    • tool_name

    • @@ -315,7 +332,7 @@

      Supported Tools

    PL/SQL custom tool

    PL/SQL custom tool

    select_ai.agent.Tool.create_pl_sql_tool

    • tool_name

    • @@ -323,7 +340,7 @@

      Supported Tools

    RAG

    RAG

    select_ai.agent.Tool.create_rag_tool

    • tool_name

    • @@ -333,6 +350,43 @@

      Supported Tools +

      1.2. Tool selection

      + + ++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
      When to use each tool

      Tool type

      Use case

      SQL

      Ask questions over database objects using a Select AI profile.

      RAG

      Answer questions using content indexed by a vector index profile.

      WEBSEARCH

      Search public web content using a web search credential.

      SLACK

      Send a Slack notification from an agent workflow.

      EMAIL

      Send an email notification from an agent workflow.

      PL/SQL custom tool

      Call a database procedure or function for application-specific work.

      +

      Notification and web search tools require credentials and network access for +the external service. SQL and RAG tools require existing Select AI profiles.

      class select_ai.agent.ToolAttributes(instruction: str | None = None, function: str | None = None, tool_params: ToolParams | None = None, tool_inputs: List[Mapping] | None = None, tool_type: ToolType | None = None)
      @@ -347,19 +401,9 @@

      Supported Toolsselect_ai.agent.ToolParams) – Tool parameters for built-in tools

      -
    • tool_inputs (List[Mapping]) –

      Describes input arguments. -Similar to column comments in a table. For example: -“tool_inputs”: [

      -
      -
      -
      {

      “name”: “data_guard”, -“description”: “Only supported values are “Enabled” and “Disabled””

      -
      -
      -

      }

      -
      -

      ]

      -

    • +
    • tool_inputs (List[Mapping]) – Describes input arguments. +Similar to column comments in a table. Each mapping can include keys such +as name and description.

    @@ -632,7 +676,7 @@

    Supported Tools -

    Create Tool

    +

    1.3. Create Tool

    The following example shows creation of an AI agent tool to perform natural language translation to SQL using an OCI AI profile

    import os
    @@ -691,7 +735,7 @@ 

    Create Toolprofile_name='oci_ai_profile', recipient=None, sender=None, - slack_channel=None, + channel=None, smtp_host=None), tool_inputs=None, tool_type=<ToolType.SQL: 'SQL'>) @@ -699,7 +743,7 @@

    Create Tool -

    List Tools

    +

    1.4. List Tools

    import os
     
     import select_ai
    @@ -724,7 +768,7 @@ 

    List Tools -

    Task

    +

    2. Task

    Each task is identified by a task_name and includes a set of attributes that guide the agent’s behavior during execution. Key attributes include the instruction, which describes the task’s purpose and @@ -884,9 +928,12 @@

    Task
    -

    Create Task

    +

    2.1. Create Task

    In the following task, we use the MOVIE_SQL_TOOL created in the previous step

    +

    The instruction is the main task prompt. Use placeholders such as +{query} when the user prompt should be inserted into the task. The +tools list limits which tools the agent can use for the task.

    import os
     from pprint import pformat
     
    @@ -928,7 +975,7 @@ 

    Create Task -

    List Tasks

    +

    2.2. List Tasks

    import os
     
     import select_ai
    @@ -952,11 +999,14 @@ 

    List Tasks -

    Agent

    +

    3. Agent

    A Select AI Agent is defined using agent_name, its attributes and an optional description. The attributes must include key agent properties such as profile_name which specifies the LLM profile used for prompt generation and role, which outlines the agent’s intended role and behavioral context.

    +

    The agent profile supplies the model used for planning and reasoning. The role +should describe the agent’s domain, boundaries, and expected behavior. Keep the +role specific to the tasks assigned to the agent.

    class select_ai.agent.AgentAttributes(profile_name: str, role: str, enable_human_tool: bool | None = True)
    @@ -1096,7 +1146,7 @@

    Agent

    -

    Create Agent

    +

    3.1. Create Agent

    import os
     
     import select_ai
    @@ -1134,7 +1184,7 @@ 

    Create Agent -

    Team

    +

    4. Team

    AI Agent Team coordinates the execution of multiple agents working together to fulfill a user request. Each team is uniquely identified by a team_name and configured through a set of attributes that define its composition and @@ -1142,6 +1192,19 @@

    Teamprocess attribute defines how tasks should be executed.

    +

    Currently, process="sequential" is used to execute task assignments in +order. Reuse the same agent in multiple team entries when the agent should +perform multiple tasks.

    +

    For example:

    +
    attributes = TeamAttributes(
    +    agents=[
    +        {"name": "MOVIE_ANALYST", "task": "ANALYZE_MOVIE_TASK"},
    +        {"name": "MOVIE_ANALYST", "task": "SUMMARIZE_MOVIE_TASK"},
    +    ],
    +    process="sequential",
    +)
    +
    +
    class select_ai.agent.TeamAttributes(agents: List[Mapping], process: str = 'sequential')
    @@ -1227,6 +1290,67 @@

    Team

    Enable the AI agent team

    +
    +
    +export(object_storage_credential_name: str | None = None, location: str | None = None, params: str | Mapping | None = None) str | None
    +

    Export this AI agent team specification.

    +

    If object storage details are provided, the specification is written to +the given location and None is returned. Otherwise, the specification is +returned as a string.

    +
    +
    Parameters:
    +
      +
    • object_storage_credential_name (str) – Optional credential name +used to write the exported specification to object storage. Must be +specified together with location.

    • +
    • location (str) – Optional object storage URI where the exported +specification should be written. Must be specified together with +object_storage_credential_name.

    • +
    • params (str or Mapping) – Optional export parameters. May be a JSON string or a +Python mapping.

    • +
    +
    +
    Returns:
    +

    Exported team specification as a JSON string when exporting +inline, or None when exporting to object storage.

    +
    +
    Return type:
    +

    str or None

    +
    +
    +
    + +
    +
    +classmethod export_team(team_name: str, object_storage_credential_name: str | None = None, location: str | None = None, params: str | Mapping | None = None) str | None
    +

    Export an AI agent team specification.

    +

    If object storage details are provided, the specification is written to +the given location and None is returned. Otherwise, the specification is +returned as a string.

    +
    +
    Parameters:
    +
      +
    • team_name (str) – Name of the AI agent team to export.

    • +
    • object_storage_credential_name (str) – Optional credential name +used to write the exported specification to object storage. Must be +specified together with location.

    • +
    • location (str) – Optional object storage URI where the exported +specification should be written. Must be specified together with +object_storage_credential_name.

    • +
    • params (str or Mapping) – Optional export parameters. May be a JSON string or a +Python mapping.

    • +
    +
    +
    Returns:
    +

    Exported team specification as a JSON string when exporting +inline, or None when exporting to object storage.

    +
    +
    Return type:
    +

    str or None

    +
    +
    +
    +
    classmethod fetch(team_name: str) Team
    @@ -1245,6 +1369,36 @@

    Team

    +
    +
    +classmethod import_team(profile_name: str, team_name: str | None = None, specification: str | Mapping | None = None, object_storage_credential_name: str | None = None, location: str | None = None, force: bool | None = False, params: str | Mapping | None = None) None
    +

    Import an AI agent team specification and create the associated team, +agents, tasks, and tools in the database.

    +
    +
    Parameters:
    +
      +
    • profile_name (str) – Name of the Select AI profile to use for the +imported team and agents in the target database.

    • +
    • team_name (str) – Optional name for the imported team. If omitted, +the team name from the specification is used.

    • +
    • specification (str or Mapping) – Team specification to import. May be a JSON +string or a Python mapping. Omit this when importing from object +storage.

    • +
    • object_storage_credential_name (str) – Optional credential name +used to read the specification from object storage. Must be specified +together with location.

    • +
    • location (str) – Optional object storage URI of the specification +to import. Must be specified together with +object_storage_credential_name.

    • +
    • force (bool) – Whether to replace conflicting database objects +during import. Default value is False.

    • +
    • params (str or Mapping) – Optional import parameters. May be a JSON string or a +Python mapping.

    • +
    +
    +
    +
    +
    classmethod list(team_name_pattern: str | None = '.*') Iterator[Team]
    @@ -1276,16 +1430,11 @@

    Team -
  • params (Mapping[str, str]) –

    Optional parameters for the task. -Currently, the following parameters are supported:

    -
      -
    • conversation_id: Identifies the conversation session associated

    • -
    -

    with the agent team

    -
      -
    • variables: key-value pairs that provide additional input to the agent team.

    • -
    -

  • +
  • params (Mapping[str, str]) – Optional parameters for the task. +Supported keys include conversation_id, which identifies the +conversation session associated with the agent team, and +variables, which provides additional key-value input to the agent +team.

  • @@ -1307,7 +1456,20 @@

    Team
    -

    Run Team

    +

    4.1. Run Team

    +

    Team.run(...) starts the team workflow. The prompt argument is passed to +the task and can be referenced by task instructions using {query}. +params can include conversation_id to associate multiple runs with the +same conversation and variables to pass additional key-value inputs.

    +
    result = team.run(
    +    prompt="Could you list the movies in the database?",
    +    params={
    +        "conversation_id": conversation_id,
    +        "variables": {"audience": "analyst"},
    +    },
    +)
    +
    +
    import os
     import uuid
     
    @@ -1365,11 +1527,148 @@ 

    Run Team

    +
    +

    4.2. Export and Import Team

    +

    Select AI agent teams can be exported into a portable specification and +imported into the same database, a different database, or another Select AI +service. The specification describes the team composition and the associated +agent, task, and tool definitions that are needed to recreate the team.

    +

    Team.export_team() returns the specification as a JSON string by default. +Team.import_team() accepts either that JSON string or a Python mapping +containing the same team definition structure. In most cases, pass a dict, +for example the result of json.loads(exported_spec). Other +JSON-serializable collections.abc.Mapping +objects, such as OrderedDict, can also be used. On import, +profile_name identifies the Select AI profile to use in the target +database. team_name can be provided to create the imported team under a new +name; this is useful when importing into the same database as the source team.

    +

    If imported object names conflict with existing agents, tasks, tools, or teams, +set force=True to let the database replace the conflicting objects. Use this +carefully when importing into a shared schema because conflicting components can +be dropped and recreated.

    +
    import json
    +import os
    +
    +import select_ai
    +from select_ai.agent import (
    +    Agent,
    +    AgentAttributes,
    +    Task,
    +    TaskAttributes,
    +    Team,
    +    TeamAttributes,
    +)
    +
    +user = os.getenv("SELECT_AI_USER")
    +password = os.getenv("SELECT_AI_PASSWORD")
    +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING")
    +profile_name = os.getenv("SELECT_AI_PROFILE_NAME", "LLAMA_4_MAVERICK")
    +
    +select_ai.connect(user=user, password=password, dsn=dsn)
    +
    +task = Task(
    +    task_name="EXPORT_IMPORT_MOVIE_TASK",
    +    description="Task used by the team export/import sample",
    +    attributes=TaskAttributes(
    +        instruction="Help the user with movie questions. Question: {query}",
    +        tools=[],
    +        enable_human_tool=False,
    +    ),
    +)
    +task.create(replace=True)
    +
    +agent = Agent(
    +    agent_name="EXPORT_IMPORT_MOVIE_ANALYST",
    +    description="Agent used by the team export/import sample",
    +    attributes=AgentAttributes(
    +        profile_name=profile_name,
    +        role="You are an AI Movie Analyst.",
    +        enable_human_tool=False,
    +    ),
    +)
    +agent.create(enabled=True, replace=True)
    +
    +source_team = Team(
    +    team_name="EXPORT_IMPORT_MOVIE_TEAM",
    +    attributes=TeamAttributes(
    +        agents=[
    +            {
    +                "name": agent.agent_name,
    +                "task": task.task_name,
    +            }
    +        ],
    +        process="sequential",
    +    ),
    +)
    +source_team.create(enabled=True, replace=True)
    +
    +specification = json.loads(source_team.export())
    +print("Exported specification:")
    +print(json.dumps(specification, indent=2))
    +
    +specification["name"] = "IMPORTED_MOVIE_ANALYST"
    +specification["task"]["task_name"] = "IMPORTED_ANALYZE_MOVIE_TASK"
    +
    +Team.import_team(
    +    profile_name=profile_name,
    +    team_name="IMPORTED_MOVIE_AGENT_TEAM",
    +    specification=specification,
    +    force=True,
    +)
    +
    +team = Team.fetch("IMPORTED_MOVIE_AGENT_TEAM")
    +print("Imported team:", team)
    +
    +
    +

    output:

    +
    Exported specification:
    +{
    +  "name": "EXPORT_IMPORT_MOVIE_ANALYST",
    +  "component_type": "Agent",
    +  "task": {
    +    "task_name": "EXPORT_IMPORT_MOVIE_TASK",
    +    "instruction": "Help the user with movie questions. Question: {query}",
    +    "task_attributes": {
    +      "enable_human_tool": "false",
    +      "tools": []
    +    }
    +  },
    +  "llm_config": {
    +    "name": "LLAMA_4_MAVERICK",
    +    "component_type": "oci"
    +  }
    +}
    +Imported team: Team(team_name=IMPORTED_MOVIE_AGENT_TEAM, ...)
    +
    +
    +

    The same APIs can also read from or write to object storage by passing both +object_storage_credential_name and location. When exporting to object +storage, Team.export_team() writes the specification to the location and +returns None. When importing from object storage, pass the same credential +and location instead of specification.

    +
    +
    +

    4.3. Lifecycle helpers

    +

    All agent object types support list, fetch, enable, disable, and delete +operations.

    +
    for tool in select_ai.agent.Tool.list():
    +    print(tool.tool_name)
    +
    +task = select_ai.agent.Task.fetch("ANALYZE_MOVIE_TASK")
    +agent = select_ai.agent.Agent.fetch("MOVIE_ANALYST")
    +team = select_ai.agent.Team.fetch("MOVIE_AGENT_TEAM")
    +
    +team.disable()
    +team.enable()
    +team.delete(force=True)
    +
    +
    +

    -

    AI agent examples

    +

    5. AI agent examples

    -

    Web Search Agent using OpenAI’s GPT model

    +

    5.1. Web Search Agent using OpenAI’s GPT model

    import os
     
     import select_ai
    @@ -1519,93 +1818,6 @@ 

    Web Search Agent using OpenAI’s GPT model -

    Async AI Agent

    -

    @@ -1619,7 +1831,8 @@

    Async AI AgentTable of Contents

    Previous topic

    1. SummaryParams

    + title="previous chapter">1. Inline content

    Next topic

    @@ -1748,7 +1965,7 @@

    Navigation

    next |
  • - previous |
  • Python logo
  • Python »
  • @@ -1758,7 +1975,7 @@

    Navigation

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • diff --git a/docs/user_guide/async_agent.html b/docs/user_guide/async_agent.html index 141feb6..f198f8b 100644 --- a/docs/user_guide/async_agent.html +++ b/docs/user_guide/async_agent.html @@ -5,19 +5,20 @@ - 1. AsyncTool — Select AI for Python 1.3.0 documentation + 1. AsyncTool — Select AI for Python 1.4.0rc1 documentation - + - + + @@ -127,7 +128,10 @@

    Table of Contents

  • AsyncTeam.delete_team()
  • AsyncTeam.disable()
  • AsyncTeam.enable()
  • +
  • AsyncTeam.export()
  • +
  • AsyncTeam.export_team()
  • AsyncTeam.fetch()
  • +
  • AsyncTeam.import_team()
  • AsyncTeam.list()
  • AsyncTeam.run()
  • AsyncTeam.set_attribute()
  • @@ -135,7 +139,9 @@

    Table of Contents

  • 4.1. Run Team
  • -
  • 4.2. List Teams
  • +
  • 4.2. Export and Import Team
  • +
  • 4.3. Lifecycle helpers
  • +
  • 4.4. List Teams
  • 5. Async AI agent examples
      @@ -150,6 +156,11 @@

      Previous topic

      1. Tool

  • +
    +

    Next topic

    +

    1. Command line interface

    +

    This Page

      @@ -177,6 +188,9 @@

      Navigation

    • index
    • +
    • + next |
    • previous |
    • @@ -188,10 +202,9 @@

      Navigation

    • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
    • -
    • @@ -223,9 +236,49 @@

      Navigation

      select_ai.agent also provides async interfaces to be used with -async / await keywords

      +async / await keywords. Use these classes in applications that already +use asyncio and select_ai.async_connect() or +select_ai.create_pool_async().

      +

      The async agent object model mirrors the synchronous agent object model:

      - + ++++ + + + + + + + + + + + + + + + + + + + +
      Select AI Async Agent ToolsSync and async agent APIs

      Sync class

      Async class

      select_ai.agent.Tool

      select_ai.agent.AsyncTool

      select_ai.agent.Task

      select_ai.agent.AsyncTask

      select_ai.agent.Agent

      select_ai.agent.AsyncAgent

      select_ai.agent.Team

      select_ai.agent.AsyncTeam

      +

      Create or reuse the same database objects as the synchronous APIs. Async +methods must be awaited, and async list methods return async iterators.

      +
      await select_ai.async_connect(user=user, password=password, dsn=dsn)
      +
      +async for tool in select_ai.agent.AsyncTool.list():
      +    print(tool.tool_name)
      +
      +
      +

      Tools, tasks, agents, and teams are database objects. Use replace=True when +you want to recreate an existing object with the same name, and force=True +when cleanup should succeed even if the object does not exist.

      + +@@ -249,16 +302,7 @@

      Navigation

      - - - - - + - + - + - + - +
      Select AI Async Agent Tools

      HTTP

      select_ai.agent.AsyncTool.create_http_tool

        -
      • tool_name

      • -
      • credential_name

      • -
      • endpoint

      • -
      -

      SQL

      SQL

      select_ai.agent.AsyncTool.create_sql_tool

      • tool_name

      • @@ -266,16 +310,16 @@

        Navigation

      SLACK

      SLACK

      select_ai.agent.AsyncTool.create_slack_notification_tool

      • tool_name

      • credential_name

      • -
      • slack_channel

      • +
      • channel

      WEBSEARCH

      WEBSEARCH

      select_ai.agent.AsyncTool.create_websearch_tool

      • tool_name

      • @@ -283,7 +327,7 @@

        Navigation

      PL/SQL custom tool

      PL/SQL custom tool

      select_ai.agent.AsyncTool.create_pl_sql_tool

      • tool_name

      • @@ -291,7 +335,7 @@

        Navigation

      RAG

      RAG

      select_ai.agent.AsyncTool.create_rag_tool

      • tool_name

      • @@ -301,6 +345,12 @@

        Navigation

      +

      Notification and web search tools require credentials and network access for +the external service. SQL and RAG tools require existing Select AI profiles.

      +

      Tool selection follows the same guidance as Agent: use SQL +tools for database questions, RAG tools for vector-index-backed content, +notification tools for Slack or email, web search tools for public web content, +and PL/SQL tools for application-specific database logic.

      1. AsyncTool

      @@ -309,15 +359,15 @@

      1.
      async create(enabled: bool | None = True, replace: bool | None = False)
      -

      Create an AI Tool in the database -:param Optional[bool] enabled: Whether the tool should be enabled.

      -
      -

      Default: True

      -
      +

      Create an AI Tool in the database

      Parameters:
      -

      replace (Optional[bool]) – Whether the tool should be replaced. -Default: False

      +
        +
      • enabled (Optional[bool]) – Whether the tool should be enabled. +Default: True

      • +
      • replace (Optional[bool]) – Whether the tool should be replaced. +Default: False

      • +

      @@ -631,7 +681,7 @@

      1.1. Create Toolprofile_name='oci_ai_profile', recipient=None, sender=None, - slack_channel=None, + channel=None, smtp_host=None), tool_inputs=None, tool_type=<ToolType.SQL: 'SQL'>) @@ -803,6 +853,9 @@

      2. 2.1. Create Task

      In the following task, we use the MOVIE_SQL_TOOL created in the previous step

      +

      The instruction is the main task prompt. Use placeholders such as +{query} when the user prompt should be inserted into the task. The +tools list limits which tools the agent can use for the task.

      import asyncio
       import os
       from pprint import pformat
      @@ -1141,6 +1194,67 @@ 

      4. AsyncTeam +
      +async export(object_storage_credential_name: str | None = None, location: str | None = None, params: str | Mapping | None = None) str | None
      +

      Export this AI agent team specification.

      +

      If object storage details are provided, the specification is written to +the given location and None is returned. Otherwise, the specification is +returned as a string.

      +
      +
      Parameters:
      +
        +
      • object_storage_credential_name (str) – Optional credential name +used to write the exported specification to object storage. Must be +specified together with location.

      • +
      • location (str) – Optional object storage URI where the exported +specification should be written. Must be specified together with +object_storage_credential_name.

      • +
      • params (str or Mapping) – Optional export parameters. May be a JSON string or a +Python mapping.

      • +
      +
      +
      Returns:
      +

      Exported team specification as a JSON string when exporting +inline, or None when exporting to object storage.

      +
      +
      Return type:
      +

      str or None

      +
      +
      +
      + +
      +
      +async classmethod export_team(team_name: str, object_storage_credential_name: str | None = None, location: str | None = None, params: str | Mapping | None = None) str | None
      +

      Export an AI agent team specification.

      +

      If object storage details are provided, the specification is written to +the given location and None is returned. Otherwise, the specification is +returned as a string.

      +
      +
      Parameters:
      +
        +
      • team_name (str) – Name of the AI agent team to export.

      • +
      • object_storage_credential_name (str) – Optional credential name +used to write the exported specification to object storage. Must be +specified together with location.

      • +
      • location (str) – Optional object storage URI where the exported +specification should be written. Must be specified together with +object_storage_credential_name.

      • +
      • params (str or Mapping) – Optional export parameters. May be a JSON string or a +Python mapping.

      • +
      +
      +
      Returns:
      +

      Exported team specification as a JSON string when exporting +inline, or None when exporting to object storage.

      +
      +
      Return type:
      +

      str or None

      +
      +
      +
      +
      async classmethod fetch(team_name: str) AsyncTeam
      @@ -1159,6 +1273,36 @@

      4. AsyncTeam +
      +async classmethod import_team(profile_name: str, team_name: str | None = None, specification: str | Mapping | None = None, object_storage_credential_name: str | None = None, location: str | None = None, force: bool | None = False, params: str | Mapping | None = None) None
      +

      Import an AI agent team specification and create the associated team, +agents, tasks, and tools in the database.

      +
      +
      Parameters:
      +
        +
      • profile_name (str) – Name of the Select AI profile to use for the +imported team and agents in the target database.

      • +
      • team_name (str) – Optional name for the imported team. If omitted, +the team name from the specification is used.

      • +
      • specification (str or Mapping) – Team specification to import. May be a JSON +string or a Python mapping. Omit this when importing from object +storage.

      • +
      • object_storage_credential_name (str) – Optional credential name +used to read the specification from object storage. Must be specified +together with location.

      • +
      • location (str) – Optional object storage URI of the specification +to import. Must be specified together with +object_storage_credential_name.

      • +
      • force (bool) – Whether to replace conflicting database objects +during import. Default value is False.

      • +
      • params (str or Mapping) – Optional import parameters. May be a JSON string or a +Python mapping.

      • +
      +
      +
      +

      +
      classmethod list(team_name_pattern: str | None = '.*') AsyncGenerator[AsyncTeam, None]
      @@ -1190,16 +1334,11 @@

      4. AsyncTeamconversation_id, which identifies the +conversation session associated with the agent team, and +variables, which provides additional key-value input to the agent +team.

    @@ -1222,6 +1361,20 @@

    4. AsyncTeam

    4.1. Run Team

    +

    AsyncTeam.run(...) starts the team workflow. The prompt argument is +passed to the task and can be referenced by task instructions using +{query}. params can include conversation_id to associate multiple +runs with the same conversation and variables to pass additional key-value +inputs.

    +
    result = await team.run(
    +    prompt="Could you list the movies in the database?",
    +    params={
    +        "conversation_id": conversation_id,
    +        "variables": {"audience": "analyst"},
    +    },
    +)
    +
    +
    import asyncio
     import os
     import uuid
    @@ -1280,8 +1433,151 @@ 

    4.1. Run Team

    +
    +

    4.2. Export and Import Team

    +

    Select AI agent teams can be exported into a portable specification and +imported into the same database, a different database, or another Select AI +service. The specification describes the team composition and the associated +agent, task, and tool definitions that are needed to recreate the team.

    +

    AsyncTeam.export_team() returns the specification as a JSON string by +default. AsyncTeam.import_team() accepts either that JSON string or a Python +mapping containing the same team definition structure. In most cases, pass a +dict, for example the result of json.loads(exported_spec). Other +JSON-serializable collections.abc.Mapping +objects, such as OrderedDict, can also be used. On import, +profile_name identifies the Select AI profile to use in the target +database. team_name can be provided to create the imported team under a new +name; this is useful when importing into the same database as the source team.

    +

    If imported object names conflict with existing agents, tasks, tools, or teams, +set force=True to let the database replace the conflicting objects. Use this +carefully when importing into a shared schema because conflicting components can +be dropped and recreated.

    +
    import asyncio
    +import json
    +import os
    +
    +import select_ai
    +from select_ai.agent import (
    +    AgentAttributes,
    +    AsyncAgent,
    +    AsyncTask,
    +    AsyncTeam,
    +    TaskAttributes,
    +    TeamAttributes,
    +)
    +
    +user = os.getenv("SELECT_AI_USER")
    +password = os.getenv("SELECT_AI_PASSWORD")
    +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING")
    +profile_name = os.getenv("SELECT_AI_PROFILE_NAME", "LLAMA_4_MAVERICK")
    +
    +
    +async def main():
    +    await select_ai.async_connect(user=user, password=password, dsn=dsn)
    +
    +    task = AsyncTask(
    +        task_name="EXPORT_IMPORT_MOVIE_TASK",
    +        description="Task used by the team export/import sample",
    +        attributes=TaskAttributes(
    +            instruction="Help the user with movie questions. Question: {query}",
    +            tools=[],
    +            enable_human_tool=False,
    +        ),
    +    )
    +    await task.create(replace=True)
    +
    +    agent = AsyncAgent(
    +        agent_name="EXPORT_IMPORT_MOVIE_ANALYST",
    +        description="Agent used by the team export/import sample",
    +        attributes=AgentAttributes(
    +            profile_name=profile_name,
    +            role="You are an AI Movie Analyst.",
    +            enable_human_tool=False,
    +        ),
    +    )
    +    await agent.create(enabled=True, replace=True)
    +
    +    source_team = AsyncTeam(
    +        team_name="EXPORT_IMPORT_MOVIE_TEAM",
    +        attributes=TeamAttributes(
    +            agents=[
    +                {
    +                    "name": agent.agent_name,
    +                    "task": task.task_name,
    +                }
    +            ],
    +            process="sequential",
    +        ),
    +    )
    +    await source_team.create(enabled=True, replace=True)
    +
    +    specification = json.loads(await source_team.export())
    +    print("Exported specification:")
    +    print(json.dumps(specification, indent=2))
    +
    +    specification["name"] = "IMPORTED_MOVIE_ANALYST"
    +    specification["task"]["task_name"] = "IMPORTED_ANALYZE_MOVIE_TASK"
    +
    +    await AsyncTeam.import_team(
    +        profile_name=profile_name,
    +        team_name="IMPORTED_MOVIE_AGENT_TEAM",
    +        specification=specification,
    +        force=True,
    +    )
    +
    +    team = await AsyncTeam.fetch("IMPORTED_MOVIE_AGENT_TEAM")
    +    print("Imported team:", team)
    +
    +
    +asyncio.run(main())
    +
    +
    +

    output:

    +
    Exported specification:
    +{
    +  "name": "EXPORT_IMPORT_MOVIE_ANALYST",
    +  "component_type": "Agent",
    +  "task": {
    +    "task_name": "EXPORT_IMPORT_MOVIE_TASK",
    +    "instruction": "Help the user with movie questions. Question: {query}",
    +    "task_attributes": {
    +      "enable_human_tool": "false",
    +      "tools": []
    +    }
    +  },
    +  "llm_config": {
    +    "name": "LLAMA_4_MAVERICK",
    +    "component_type": "oci"
    +  }
    +}
    +Imported team: AsyncTeam(team_name=IMPORTED_MOVIE_AGENT_TEAM, ...)
    +
    +
    +

    The same APIs can also read from or write to object storage by passing both +object_storage_credential_name and location. When exporting to object +storage, AsyncTeam.export_team() writes the specification to the location +and returns None. When importing from object storage, pass the same +credential and location instead of specification.

    +
    +
    +

    4.3. Lifecycle helpers

    +

    All async agent object types support list, fetch, enable, disable, and delete +operations.

    +
    async for tool in select_ai.agent.AsyncTool.list():
    +    print(tool.tool_name)
    +
    +task = await select_ai.agent.AsyncTask.fetch("ANALYZE_MOVIE_TASK")
    +agent = await select_ai.agent.AsyncAgent.fetch("MOVIE_ANALYST")
    +team = await select_ai.agent.AsyncTeam.fetch("MOVIE_AGENT_TEAM")
    +
    +await team.disable()
    +await team.enable()
    +await team.delete(force=True)
    +
    +
    +
    -

    4.2. List Teams

    +

    4.4. List Teams

    +
    +

    Next topic

    +

    1. Command line interface

    +

    This Page

      @@ -1598,6 +1904,9 @@

      Navigation

    • index
    • +
    • + next |
    • previous |
    • @@ -1609,10 +1918,9 @@

      Navigation

    • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
    • -
    • diff --git a/docs/user_guide/async_profile.html b/docs/user_guide/async_profile.html index 000c967..223716f 100644 --- a/docs/user_guide/async_profile.html +++ b/docs/user_guide/async_profile.html @@ -5,21 +5,21 @@ - 1. AsyncProfile API — Select AI for Python 1.3.0 documentation + 1. Async profile lifecycle — Select AI for Python 1.4.0rc1 documentation - + - + - + @@ -63,7 +63,9 @@

      Table of Contents

      Previous topic

      1. Profile Object Model

      + title="previous chapter">1. Profile lifecycle

      Next topic

      @@ -146,7 +155,7 @@

      Navigation

      next |
    • - previous |
    • Python logo
    • Python »
    • @@ -156,11 +165,10 @@

      Navigation

    • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
    • - - +
    • @@ -190,12 +198,86 @@

      Navigation

      -

      An AsyncProfile object can be created with select_ai.AsyncProfile() -AsyncProfile support use of concurrent programming with asyncio. +

      An AsyncProfile object can be created with select_ai.AsyncProfile(). +AsyncProfile supports concurrent programming with asyncio. Unless explicitly noted as synchronous, the AsyncProfile methods should be used with await.

      +

      Use AsyncProfile in applications that already use +select_ai.async_connect() or select_ai.create_pool_async(). The async +profile object uses the same database profile objects as Profile; only the +Python API style changes.

      +

      Because AsyncProfile initializes itself from the database, create or fetch +instances with await:

      +
      async_profile = await select_ai.AsyncProfile(
      +    profile_name="async_oci_ai_profile",
      +)
      +
      +
      +

      Before creating an async profile, make sure the database user has the required +privileges, a credential for the AI provider, network access to the provider +endpoint, and access to the database objects included in the profile. See +Privileges, Credential, +Provider, and +ProfileAttributes.

      +
      +

      1. Async profile lifecycle

      +

      The usual async profile lifecycle is:

      +
        +
      • Create or reuse an async database connection or async pool.

      • +
      • Create a provider object.

      • +
      • Create ProfileAttributes with the provider, credential name, and object +list.

      • +
      • Create the profile with await select_ai.AsyncProfile(...).

      • +
      • Reuse the profile later by name.

      • +
      • Update profile attributes when provider settings or object scope changes.

      • +
      • Delete profiles that are no longer needed.

      • +
      +

      replace=True recreates a profile when a profile with the same name already +exists. merge=True fetches the existing profile and updates it with the +non-null attributes passed by the caller.

      +
      +
      +

      2. Async profile actions

      + + ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Common async profile actions

      Method

      Description

      show_sql()

      Generates SQL for a natural language prompt without executing it.

      run_sql()

      Generates SQL, executes it, and returns a pandas.DataFrame.

      narrate()

      Generates SQL, executes it, and returns a natural language answer.

      explain_sql()

      Explains the generated SQL for a prompt.

      show_prompt()

      Shows the prompt sent to the model.

      chat()

      Sends a general chat prompt to the model.

      summarize()

      Summarizes inline content or content referenced by a URI.

      translate()

      Translates text from one language to another.

      -

      1. AsyncProfile API

      +

      2.1. AsyncProfile API

      class select_ai.AsyncProfile(*args, **kwargs)
      @@ -235,13 +317,15 @@

      1.
      -async chat(prompt, params: Mapping = None) str
      +async chat(prompt, params: Mapping = None, stream: bool = False, chunk_size: int = 8192) str | AsyncGenerator[str, None]

      Asynchronously chat with the LLM

      Parameters:
      • prompt (str) – Natural language prompt

      • params – Parameters to include in the LLM request

      • +
      • stream (bool) – Return an async iterator of response chunks

      • +
      • chunk_size (int) – Number of characters to read per stream chunk

      Returns:
      @@ -336,13 +420,15 @@

      1.
      -async explain_sql(prompt: str, params: Mapping = None)
      +async explain_sql(prompt: str, params: Mapping = None, stream: bool = False, chunk_size: int = 8192)

      Explain the generated SQL

      Parameters:
      • prompt (str) – Natural language prompt

      • params – Parameters to include in the LLM request

      • +
      • stream (bool) – Return an async iterator of response chunks

      • +
      • chunk_size (int) – Number of characters to read per stream chunk

      Returns:
      @@ -371,7 +457,7 @@

      1.
      -async generate(prompt: str, action=Action.SHOWSQL, params: Mapping = None) DataFrame | str | None
      +async generate(prompt: str, action=Action.SHOWSQL, params: Mapping = None, stream: bool = False, chunk_size: int = 8192) DataFrame | str | AsyncGenerator[str, None] | None

      Asynchronously perform AI translation using this profile

      Parameters:
      @@ -380,6 +466,8 @@

      1. Returns: @@ -438,13 +526,15 @@

      1.
      -async narrate(prompt, params: Mapping = None) str
      +async narrate(prompt, params: Mapping = None, stream: bool = False, chunk_size: int = 8192) str | AsyncGenerator[str, None]

      Narrate the result of the SQL

      Parameters:
      • prompt (str) – Natural language prompt

      • params – Parameters to include in the LLM request

      • +
      • stream (bool) – Return an async iterator of response chunks

      • +
      • chunk_size (int) – Number of characters to read per stream chunk

      Returns:
      @@ -526,13 +616,15 @@

      1.
      -async show_prompt(prompt: str, params: Mapping = None)
      +async show_prompt(prompt: str, params: Mapping = None, stream: bool = False, chunk_size: int = 8192)

      Show the prompt sent to LLM

      Parameters:
      • prompt (str) – Natural language prompt

      • params – Parameters to include in the LLM request

      • +
      • stream (bool) – Return an async iterator of response chunks

      • +
      • chunk_size (int) – Number of characters to read per stream chunk

      Returns:
      @@ -543,13 +635,15 @@

      1.
      -async show_sql(prompt, params: Mapping = None)
      +async show_sql(prompt, params: Mapping = None, stream: bool = False, chunk_size: int = 8192)

      Show the generated SQL

      Parameters:
      • prompt (str) – Natural language prompt

      • params – Parameters to include in the LLM request

      • +
      • stream (bool) – Return an async iterator of response chunks

      • +
      • chunk_size (int) – Number of characters to read per stream chunk

      Returns:
      @@ -601,7 +695,9 @@

      1. -

      2. Async Profile creation

      +

      2.2. Async Profile creation

      +

      The following example creates an OCI Gen AI profile that can generate SQL over +objects in the SH schema.

      import asyncio
       import os
       from pprint import pformat
      @@ -672,8 +768,62 @@ 

      2. Async Profile creation +

      2.3. Reuse Async Profile

      +

      After a profile has been created, instantiate AsyncProfile with only the +profile name to reuse the database profile:

      +
      async_profile = await select_ai.AsyncProfile(
      +    profile_name="async_oci_ai_profile",
      +)
      +sql = await async_profile.show_sql(prompt="How many promotions?")
      +
      +
      +

      Use AsyncProfile.fetch(...) when you want to create a proxy object from a +saved database profile and raise an error if the profile does not exist:

      +
      async_profile = await select_ai.AsyncProfile.fetch(
      +    "async_oci_ai_profile"
      +)
      +
      +
      +

      +
      +

      2.4. Update Async Profile

      +

      Use set_attribute(...) to update one profile attribute or +set_attributes(...) to update several attributes. Updates are saved to the +database profile.

      +
      async_profile = await select_ai.AsyncProfile(
      +    profile_name="async_oci_ai_profile",
      +)
      +await async_profile.set_attribute("temperature", 0.1)
      +
      +await async_profile.set_attributes(
      +    select_ai.ProfileAttributes(
      +        max_tokens=2048,
      +        enforce_object_list=True,
      +    )
      +)
      +
      +
      +
      +
      +

      2.5. Delete Async Profile

      +

      Use delete(...) or AsyncProfile.delete_profile(...) to remove a profile +from the database. Pass force=True when cleanup should succeed even if the +profile does not exist.

      +
      async_profile = await select_ai.AsyncProfile(
      +    profile_name="async_oci_ai_profile",
      +)
      +await async_profile.delete(force=True)
      +
      +await select_ai.AsyncProfile.delete_profile(
      +    "async_oci_ai_profile",
      +    force=True,
      +)
      +
      +
      +
      -

      3. Async explain SQL

      +

      2.6. Async explain SQL

      import asyncio
       import os
       
      @@ -718,7 +868,7 @@ 

      3. Async explain SQL -

      4. Async run SQL

      +

      2.7. Async run SQL

      import asyncio
       import os
       
      @@ -750,7 +900,7 @@ 

      4. Async run SQL

      -

      5. Async show SQL

      +

      2.8. Async show SQL

      import asyncio
       import os
       
      @@ -778,8 +928,21 @@ 

      5. Async show SQL

      +
      +

      2.9. Async show prompt

      +

      Use show_prompt(...) to inspect the prompt that Select AI sends to the +model. This is useful when tuning profile attributes, object lists, comments, +constraints, and provider settings.

      +
      async_profile = await select_ai.AsyncProfile(
      +    profile_name="async_oci_ai_profile",
      +)
      +prompt = await async_profile.show_prompt(prompt="How many promotions?")
      +print(prompt)
      +
      +
      +
      -

      6. Async concurrent SQL

      +

      2.10. Async concurrent SQL

      import asyncio
       import os
       
      @@ -838,7 +1001,7 @@ 

      6. Async concurrent SQL -

      7. Async chat

      +

      2.11. Async chat

      import asyncio
       import os
       
      @@ -886,8 +1049,47 @@ 

      7. Async chat

      +
      +

      2.12. Async streaming chat

      +
      import asyncio
      +import os
      +
      +import select_ai
      +
      +user = os.getenv("SELECT_AI_USER")
      +password = os.getenv("SELECT_AI_PASSWORD")
      +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING")
      +
      +
      +async def main():
      +    await select_ai.async_connect(user=user, password=password, dsn=dsn)
      +    async_profile = await select_ai.AsyncProfile(
      +        profile_name="async_oci_ai_profile"
      +    )
      +
      +    chunks = await async_profile.chat(
      +        prompt="What is OCI ?", stream=True, chunk_size=4096
      +    )
      +    async for chunk in chunks:
      +        print(chunk, end="")
      +    print()
      +
      +
      +asyncio.run(main())
      +
      +
      +

      stream=True lets callers consume generated CLOB responses chunk by chunk, +reducing memory pressure and making it easier to progressively forward output +to files, services, or user interfaces. Async streaming text APIs return an +async iterator of str chunks after the awaited method call. The +chunk_size parameter controls the number of CLOB characters read per chunk; +it is not a byte count.

      +

      Streaming is supported by generate(), chat(), narrate(), +explain_sql(), show_sql(), and show_prompt(). It is not supported +for run_sql(), which returns a pandas.DataFrame.

      +
      -

      8. Summarize

      +

      2.13. Summarize

      Summarize inline content

      import asyncio
       import os
      @@ -975,7 +1177,7 @@ 

      8. Summarize -

      9. Translate

      +

      2.14. Translate

      import asyncio
       import os
       
      @@ -1008,7 +1210,7 @@ 

      9. Translate -

      10. Async pipeline

      +

      2.15. Async pipeline

      import asyncio
       import os
       
      @@ -1077,7 +1279,9 @@ 

      10. Async pipeline

      -

      11. List profiles asynchronously

      +

      2.16. List profiles asynchronously

      +

      Profile listing returns profiles visible to the connected database user. The +async list API returns an async iterator.

      import asyncio
       import os
       
      @@ -1106,6 +1310,7 @@ 

      11. List profiles asynchronouslyOCI_AI_PROFILE

      +
      @@ -1118,7 +1323,9 @@

      11. List profiles asynchronously

      Table of Contents

      Previous topic

      1. Profile Object Model

      + title="previous chapter">1. Profile lifecycle

      Next topic

      @@ -1201,7 +1415,7 @@

      Navigation

      next |
    • - previous |
    • Python logo
    • Python »
    • @@ -1211,11 +1425,10 @@

      Navigation

    • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
    • - - +
    • diff --git a/docs/user_guide/cli.html b/docs/user_guide/cli.html new file mode 100644 index 0000000..f966bf2 --- /dev/null +++ b/docs/user_guide/cli.html @@ -0,0 +1,492 @@ + + + + + + + + 1. Command line interface — Select AI for Python 1.4.0rc1 documentation + + + + + + + + + + + + + + + + + + + + + +
      + + + +
      + + + +
      +
      +
      +
      + +
      +

      1. Command line interface

      +

      The select-ai command line interface (CLI) provides a terminal workflow for +using Select AI profiles without writing Python code. It is intended for quick +exploration, profile validation, prompt testing, SQL generation, +summarization, translation, and interactive chat against an existing profile.

      +

      The CLI is useful for developers who want a fast shell workflow and for +non-developers who are comfortable running terminal commands but do not want to +write Python code. It can help users check whether a profile is configured +correctly, inspect generated SQL, try prompts during development, or interact +with a curated profile through a simple command.

      +

      The CLI works with Select AI profiles. RAG is supported when the selected +profile is already configured with a vector index. Additional CLI options and +workflows will be added in upcoming releases as the CLI evolves.

      +Select AI CLI demo + +

      The package provides an optional select-ai command line tool. Install the +CLI extra to use it:

      +
      pip install 'select_ai[cli]'
      +
      +
      +

      Use select-ai --help to view the available command groups and +select-ai <command> --help to view options for a specific command.

      +

      Set the database connection details as environment variables, or pass them as +command line options:

      +
      export SELECT_AI_USER=<db_user>
      +export SELECT_AI_PASSWORD=<db_password>
      +export SELECT_AI_DB_CONNECT_STRING=<db_connect_string>
      +
      +
      +
      +

      1.1. Connection options

      +

      All CLI commands accept the same database connection options:

      + + ++++ + + + + + + + + + + + + + + + + + + + + + + +
      Connection options

      Option

      Environment variable

      --user

      SELECT_AI_USER

      --password

      SELECT_AI_PASSWORD

      --dsn

      SELECT_AI_DB_CONNECT_STRING

      --wallet-location

      SELECT_AI_WALLET_LOCATION

      --wallet-password

      SELECT_AI_WALLET_PASSWORD

      +

      If --password and SELECT_AI_PASSWORD are not set, the CLI prompts for +the database password. Wallet options are optional and are only needed for +wallet-based database connections.

      +
      +
      +

      1.2. Interactive chat

      +

      The chat subcommand starts an interactive profile chat +Read-Eval-Print Loop (REPL). A REPL is a terminal session that reads each +prompt you type, evaluates it, prints the response, and then waits for the next +prompt. Pass an existing Select AI profile with --profile:

      +
      select-ai chat --profile OCI_AI_PROFILE
      +
      +
      +

      The REPL uses Profile.chat_session() so prompts in the same terminal session +share conversation context. Responses stream by default. Use --no-stream to +print each response after it is fully generated.

      +
      Connected to Select AI profile: OCI_AI_PROFILE
      +Type /help for commands. Type /exit to quit.
      +select_ai> What tables can I ask about?
      +...
      +select_ai> /exit
      +
      +
      +

      Useful options:

      +
        +
      • --user, --password, and --dsn override the environment values.

      • +
      • --wallet-location and --wallet-password configure wallet connections.

      • +
      • --chunk-size controls the number of CLOB characters read per stream chunk.

      • +
      • --conversation-length controls how many prompts are retained in context.

      • +
      • --keep-conversation keeps the database conversation after the REPL exits.

      • +
      +

      Inside the REPL, use these commands:

      + + ++++ + + + + + + + + + + + + + + + + + + + +
      Chat REPL commands

      Command

      Description

      /help

      Show available REPL commands.

      /clear

      Start a fresh database conversation.

      /exit

      Exit the chat session.

      /quit

      Exit the chat session.

      +
      +
      +

      1.3. SQL commands

      +

      SQL operations are one-shot subcommands instead of a REPL:

      +
      select-ai sql show --profile OCI_AI_PROFILE "count movies by genre"
      +select-ai sql run --profile OCI_AI_PROFILE "count movies by genre"
      +select-ai sql explain --profile OCI_AI_PROFILE "count movies by genre"
      +select-ai sql narrate --profile OCI_AI_PROFILE "count movies by genre"
      +
      +
      +

      show, explain, and narrate stream text output by default. Use +--no-stream to print the response after it is fully generated, and +--chunk-size to control the number of CLOB characters read per stream +chunk.

      +

      run executes the generated SQL and prints the returned result table. It +does not support streaming.

      +
      +
      +

      1.4. Profile commands

      +

      Summarize and translate are available under the profile command group:

      +
      select-ai profile list
      +select-ai profile list --pattern "OCI.*"
      +
      +select-ai profile summarize --profile OCI_AI_PROFILE "Text to summarize"
      +select-ai profile summarize --profile OCI_AI_PROFILE --file notes.txt
      +select-ai profile summarize \
      +    --profile OCI_AI_PROFILE \
      +    --location-uri https://example.com/article.txt
      +select-ai profile summarize \
      +    --profile OCI_AI_PROFILE \
      +    --location-uri https://objectstorage.example.com/n/namespace/b/bucket/o/file.txt \
      +    --credential-name OBJECT_STORE_CRED
      +
      +select-ai profile translate \
      +    --profile OCI_AI_PROFILE \
      +    --source-language English \
      +    --target-language German \
      +    "Thank you"
      +
      +
      +

      profile list prints profile names visible to the connected database user. +Use --pattern to filter names with a regular expression.

      +

      profile summarize accepts one content source at a time: inline text, +--file, or --location-uri. Use --prompt to guide the summary and +--credential-name when the location URI requires an object storage +credential.

      +
      +
      +

      1.5. Command summary

      + + ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      CLI command summary

      Command

      Purpose

      select-ai chat

      Start an interactive context-aware chat session.

      select-ai sql show

      Generate SQL without executing it.

      select-ai sql run

      Generate SQL, execute it, and print the result table.

      select-ai sql explain

      Explain generated SQL.

      select-ai sql narrate

      Generate and execute SQL, then return a natural language answer.

      select-ai profile list

      List saved profile names.

      select-ai profile summarize

      Summarize inline content, a file, or a URI.

      select-ai profile translate

      Translate text with a saved profile.

      +
      +
      + + +
      +
      +
      +
      + +
      +
      + + + + + diff --git a/docs/user_guide/concurrent_prompt_processing.html b/docs/user_guide/concurrent_prompt_processing.html new file mode 100644 index 0000000..5ac3b16 --- /dev/null +++ b/docs/user_guide/concurrent_prompt_processing.html @@ -0,0 +1,814 @@ + + + + + + + + 1. Concurrent prompt processing — Select AI for Python 1.4.0rc1 documentation + + + + + + + + + + + + + + + + + + + + +
      + + + +
      + + + +
      +
      +
      +
      + +
      +

      1. Concurrent prompt processing

      +

      Use concurrent prompt processing when an application needs to send multiple +independent prompts without waiting for each prompt to finish before starting +the next one. The select_ai module supports this pattern with both the +synchronous Profile API and the asynchronous AsyncProfile API.

      +

      Create a connection pool before running concurrent work. Use +select_ai.create_pool() for synchronous recipes and +select_ai.create_pool_async() for asynchronous recipes.

      +
      +

      1.1. Recipe summary

      + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Recipe

      Script

      When to use

      Sync completion

      sync_thread_pool.py

      Use ThreadPoolExecutor when prompts are independent and results can +be handled as soon as each prompt completes.

      Sync input order

      sync_ordered_results.py

      Use ThreadPoolExecutor.map() when result order must match the input +prompt order.

      Sync queue

      sync_queue_workers.py

      Use worker threads and a queue for producer-consumer workloads where +prompts may arrive over time.

      Async input order

      async_gather.py

      Use asyncio.gather() when result order must match the input prompt +order.

      Async completion

      async_as_completed.py

      Use asyncio.as_completed() when each result should be processed as +soon as it is available.

      Async pipeline

      async_pipeline.py

      Use run_pipeline() when all prompt/action pairs are known up front +and should be sent in a single database round trip.

      Async queue

      async_queue_workers.py

      Use async queue workers for long-running async services or background +prompt processors.

      +
      +
      +

      1.2. Environment variables

      +

      The recipes use the same connection environment variables as the other samples:

      +
      export SELECT_AI_USER=<select_ai_db_user>
      +export SELECT_AI_PASSWORD=<select_ai_db_password>
      +export SELECT_AI_DB_CONNECT_STRING=<db_connect_string>
      +
      +
      +

      Optional environment variables control pool sizing and profile names:

      +
      export SELECT_AI_POOL_MIN=1
      +export SELECT_AI_POOL_MAX=4
      +export SELECT_AI_POOL_INCREMENT=1
      +export SELECT_AI_PROFILE_NAME=oci_ai_profile
      +
      +
      +

      Use SELECT_AI_PROFILE_NAME=async_oci_ai_profile for the async recipes if +that is the async profile name in your environment.

      +
      +
      +

      1.3. sync_thread_pool.py

      +

      This recipe uses ThreadPoolExecutor and as_completed(). Results are +printed in the order they finish.

      +
      from concurrent.futures import ThreadPoolExecutor, as_completed
      +import os
      +
      +import select_ai
      +
      +user = os.getenv("SELECT_AI_USER")
      +password = os.getenv("SELECT_AI_PASSWORD")
      +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING")
      +
      +pool_min = int(os.getenv("SELECT_AI_POOL_MIN", "1"))
      +pool_max = int(os.getenv("SELECT_AI_POOL_MAX", "4"))
      +pool_increment = int(os.getenv("SELECT_AI_POOL_INCREMENT", "1"))
      +
      +profile_name = os.getenv("SELECT_AI_PROFILE_NAME", "oci_ai_profile")
      +max_workers = int(os.getenv("SELECT_AI_MAX_WORKERS", str(pool_max)))
      +
      +prompts = [
      +    "How many customers?",
      +    "How many products?",
      +    "How many promotions?",
      +    "List the top 5 customers by sales.",
      +]
      +
      +
      +def show_sql(prompt):
      +    profile = select_ai.Profile(profile_name=profile_name)
      +    return prompt, profile.show_sql(prompt=prompt)
      +
      +
      +select_ai.create_pool(
      +    user=user,
      +    password=password,
      +    dsn=dsn,
      +    min_size=pool_min,
      +    max_size=pool_max,
      +    increment=pool_increment,
      +)
      +
      +try:
      +    with ThreadPoolExecutor(max_workers=max_workers) as executor:
      +        futures = [executor.submit(show_sql, prompt) for prompt in prompts]
      +
      +        for future in as_completed(futures):
      +            prompt, sql = future.result()
      +            print(f"\nPrompt: {prompt}")
      +            print(sql)
      +finally:
      +    select_ai.disconnect()
      +
      +
      +
      +
      +

      1.4. sync_ordered_results.py

      +

      This recipe uses ThreadPoolExecutor.map(). Prompts run concurrently, but +results are printed in the same order as the input list.

      +
      from concurrent.futures import ThreadPoolExecutor
      +import os
      +
      +import select_ai
      +
      +user = os.getenv("SELECT_AI_USER")
      +password = os.getenv("SELECT_AI_PASSWORD")
      +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING")
      +
      +pool_min = int(os.getenv("SELECT_AI_POOL_MIN", "1"))
      +pool_max = int(os.getenv("SELECT_AI_POOL_MAX", "4"))
      +pool_increment = int(os.getenv("SELECT_AI_POOL_INCREMENT", "1"))
      +
      +profile_name = os.getenv("SELECT_AI_PROFILE_NAME", "oci_ai_profile")
      +max_workers = int(os.getenv("SELECT_AI_MAX_WORKERS", str(pool_max)))
      +
      +prompts = [
      +    "How many customers?",
      +    "How many products?",
      +    "How many promotions?",
      +    "List the top 5 customers by sales.",
      +]
      +
      +
      +def show_sql(prompt):
      +    profile = select_ai.Profile(profile_name=profile_name)
      +    return profile.show_sql(prompt=prompt)
      +
      +
      +select_ai.create_pool(
      +    user=user,
      +    password=password,
      +    dsn=dsn,
      +    min_size=pool_min,
      +    max_size=pool_max,
      +    increment=pool_increment,
      +)
      +
      +try:
      +    with ThreadPoolExecutor(max_workers=max_workers) as executor:
      +        results = executor.map(show_sql, prompts)
      +
      +        for prompt, sql in zip(prompts, results):
      +            print(f"\nPrompt: {prompt}")
      +            print(sql)
      +finally:
      +    select_ai.disconnect()
      +
      +
      +
      +
      +

      1.5. sync_queue_workers.py

      +

      This recipe uses worker threads and queue.Queue. It is useful when prompt +producers and prompt processors are separate parts of an application.

      +
      import os
      +from queue import Queue
      +from threading import Thread
      +
      +import select_ai
      +
      +user = os.getenv("SELECT_AI_USER")
      +password = os.getenv("SELECT_AI_PASSWORD")
      +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING")
      +
      +pool_min = int(os.getenv("SELECT_AI_POOL_MIN", "1"))
      +pool_max = int(os.getenv("SELECT_AI_POOL_MAX", "4"))
      +pool_increment = int(os.getenv("SELECT_AI_POOL_INCREMENT", "1"))
      +
      +profile_name = os.getenv("SELECT_AI_PROFILE_NAME", "oci_ai_profile")
      +worker_count = int(os.getenv("SELECT_AI_WORKER_COUNT", str(pool_max)))
      +
      +prompts = [
      +    "How many customers?",
      +    "How many products?",
      +    "How many promotions?",
      +    "List the top 5 customers by sales.",
      +]
      +
      +
      +def worker(queue, results):
      +    while True:
      +        item = queue.get()
      +        try:
      +            if item is None:
      +                return
      +
      +            index, prompt = item
      +            profile = select_ai.Profile(profile_name=profile_name)
      +            sql = profile.show_sql(prompt=prompt)
      +            results[index] = (prompt, sql)
      +        finally:
      +            queue.task_done()
      +
      +
      +select_ai.create_pool(
      +    user=user,
      +    password=password,
      +    dsn=dsn,
      +    min_size=pool_min,
      +    max_size=pool_max,
      +    increment=pool_increment,
      +)
      +
      +try:
      +    queue = Queue()
      +    results = [None] * len(prompts)
      +
      +    workers = [
      +        Thread(target=worker, args=(queue, results)) for _ in range(worker_count)
      +    ]
      +    for thread in workers:
      +        thread.start()
      +
      +    for index, prompt in enumerate(prompts):
      +        queue.put((index, prompt))
      +
      +    for _ in workers:
      +        queue.put(None)
      +
      +    queue.join()
      +    for thread in workers:
      +        thread.join()
      +
      +    for prompt, sql in results:
      +        print(f"\nPrompt: {prompt}")
      +        print(sql)
      +finally:
      +    select_ai.disconnect()
      +
      +
      +
      +
      +

      1.6. async_gather.py

      +

      This recipe uses asyncio.gather(). Prompts run concurrently, and results +are returned in the same order as the input task list.

      +
      import asyncio
      +import os
      +
      +import select_ai
      +
      +user = os.getenv("SELECT_AI_USER")
      +password = os.getenv("SELECT_AI_PASSWORD")
      +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING")
      +
      +pool_min = int(os.getenv("SELECT_AI_POOL_MIN", "1"))
      +pool_max = int(os.getenv("SELECT_AI_POOL_MAX", "4"))
      +pool_increment = int(os.getenv("SELECT_AI_POOL_INCREMENT", "1"))
      +
      +profile_name = os.getenv("SELECT_AI_PROFILE_NAME", "async_oci_ai_profile")
      +
      +prompts = [
      +    "How many customers?",
      +    "How many products?",
      +    "How many promotions?",
      +    "List the top 5 customers by sales.",
      +]
      +
      +
      +async def show_sql(profile, prompt):
      +    return await profile.show_sql(prompt=prompt)
      +
      +
      +async def main():
      +    select_ai.create_pool_async(
      +        user=user,
      +        password=password,
      +        dsn=dsn,
      +        min_size=pool_min,
      +        max_size=pool_max,
      +        increment=pool_increment,
      +    )
      +
      +    try:
      +        profile = await select_ai.AsyncProfile(profile_name=profile_name)
      +
      +        tasks = [show_sql(profile, prompt) for prompt in prompts]
      +        results = await asyncio.gather(*tasks)
      +
      +        for prompt, sql in zip(prompts, results):
      +            print(f"\nPrompt: {prompt}")
      +            print(sql)
      +    finally:
      +        await select_ai.async_disconnect()
      +
      +
      +asyncio.run(main())
      +
      +
      +
      +
      +

      1.7. async_as_completed.py

      +

      This recipe uses asyncio.as_completed(). It is useful for command-line +tools or services that can forward each answer as soon as it is ready.

      +
      import asyncio
      +import os
      +
      +import select_ai
      +
      +user = os.getenv("SELECT_AI_USER")
      +password = os.getenv("SELECT_AI_PASSWORD")
      +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING")
      +
      +pool_min = int(os.getenv("SELECT_AI_POOL_MIN", "1"))
      +pool_max = int(os.getenv("SELECT_AI_POOL_MAX", "4"))
      +pool_increment = int(os.getenv("SELECT_AI_POOL_INCREMENT", "1"))
      +
      +profile_name = os.getenv("SELECT_AI_PROFILE_NAME", "async_oci_ai_profile")
      +
      +prompts = [
      +    "How many customers?",
      +    "How many products?",
      +    "How many promotions?",
      +    "List the top 5 customers by sales.",
      +]
      +
      +
      +async def show_sql(profile, prompt):
      +    sql = await profile.show_sql(prompt=prompt)
      +    return prompt, sql
      +
      +
      +async def main():
      +    select_ai.create_pool_async(
      +        user=user,
      +        password=password,
      +        dsn=dsn,
      +        min_size=pool_min,
      +        max_size=pool_max,
      +        increment=pool_increment,
      +    )
      +
      +    try:
      +        profile = await select_ai.AsyncProfile(profile_name=profile_name)
      +        tasks = [show_sql(profile, prompt) for prompt in prompts]
      +
      +        for task in asyncio.as_completed(tasks):
      +            prompt, sql = await task
      +            print(f"\nPrompt: {prompt}")
      +            print(sql)
      +    finally:
      +        await select_ai.async_disconnect()
      +
      +
      +asyncio.run(main())
      +
      +
      +
      +
      +

      1.8. async_pipeline.py

      +

      This recipe uses AsyncProfile.run_pipeline() to send multiple +prompt/action pairs in one database round trip. This is different from Python +task concurrency: the application submits a batch and receives the batch +results when the pipeline completes.

      +
      import asyncio
      +import os
      +
      +import select_ai
      +
      +user = os.getenv("SELECT_AI_USER")
      +password = os.getenv("SELECT_AI_PASSWORD")
      +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING")
      +
      +pool_min = int(os.getenv("SELECT_AI_POOL_MIN", "1"))
      +pool_max = int(os.getenv("SELECT_AI_POOL_MAX", "4"))
      +pool_increment = int(os.getenv("SELECT_AI_POOL_INCREMENT", "1"))
      +
      +profile_name = os.getenv("SELECT_AI_PROFILE_NAME", "async_oci_ai_profile")
      +
      +prompt_specifications = [
      +    ("How many customers?", select_ai.Action.SHOWSQL),
      +    ("How many promotions?", select_ai.Action.RUNSQL),
      +    ("Explain how to count products.", select_ai.Action.EXPLAINSQL),
      +]
      +
      +
      +async def main():
      +    select_ai.create_pool_async(
      +        user=user,
      +        password=password,
      +        dsn=dsn,
      +        min_size=pool_min,
      +        max_size=pool_max,
      +        increment=pool_increment,
      +    )
      +
      +    try:
      +        profile = await select_ai.AsyncProfile(profile_name=profile_name)
      +        results = await profile.run_pipeline(
      +            prompt_specifications, continue_on_error=True
      +        )
      +
      +        for (prompt, action), result in zip(prompt_specifications, results):
      +            print(f"\nPrompt: {prompt}")
      +            print(f"Action: {action}")
      +            print(result)
      +    finally:
      +        await select_ai.async_disconnect()
      +
      +
      +asyncio.run(main())
      +
      +
      +
      +
      +

      1.9. async_queue_workers.py

      +

      This recipe uses asyncio.Queue and async worker tasks. It is useful for +long-running async applications that receive prompts over time.

      +
      import asyncio
      +import os
      +
      +import select_ai
      +
      +user = os.getenv("SELECT_AI_USER")
      +password = os.getenv("SELECT_AI_PASSWORD")
      +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING")
      +
      +pool_min = int(os.getenv("SELECT_AI_POOL_MIN", "1"))
      +pool_max = int(os.getenv("SELECT_AI_POOL_MAX", "4"))
      +pool_increment = int(os.getenv("SELECT_AI_POOL_INCREMENT", "1"))
      +
      +profile_name = os.getenv("SELECT_AI_PROFILE_NAME", "async_oci_ai_profile")
      +worker_count = int(os.getenv("SELECT_AI_WORKER_COUNT", str(pool_max)))
      +
      +prompts = [
      +    "How many customers?",
      +    "How many products?",
      +    "How many promotions?",
      +    "List the top 5 customers by sales.",
      +]
      +
      +
      +async def worker(name, profile, queue, results):
      +    while True:
      +        item = await queue.get()
      +        try:
      +            if item is None:
      +                return
      +
      +            index, prompt = item
      +            sql = await profile.show_sql(prompt=prompt)
      +            results[index] = (prompt, sql)
      +        finally:
      +            queue.task_done()
      +
      +
      +async def main():
      +    select_ai.create_pool_async(
      +        user=user,
      +        password=password,
      +        dsn=dsn,
      +        min_size=pool_min,
      +        max_size=pool_max,
      +        increment=pool_increment,
      +    )
      +
      +    try:
      +        profile = await select_ai.AsyncProfile(profile_name=profile_name)
      +        queue = asyncio.Queue()
      +        results = [None] * len(prompts)
      +
      +        workers = [
      +            asyncio.create_task(worker(i, profile, queue, results))
      +            for i in range(worker_count)
      +        ]
      +
      +        for index, prompt in enumerate(prompts):
      +            await queue.put((index, prompt))
      +
      +        for _ in workers:
      +            await queue.put(None)
      +
      +        await queue.join()
      +        await asyncio.gather(*workers)
      +
      +        for prompt, sql in results:
      +            print(f"\nPrompt: {prompt}")
      +            print(sql)
      +    finally:
      +        await select_ai.async_disconnect()
      +
      +
      +asyncio.run(main())
      +
      +
      +
      +
      +

      1.10. Pool sizing

      +

      Pool size controls how many database connections the application can use at +one time. For thread and worker recipes, keep the worker count close to the +pool maximum unless the application intentionally needs additional queued work.

      +

      In multi-process deployments, each process creates its own pool. Total possible +database connections are approximately:

      +
      processes * SELECT_AI_POOL_MAX
      +
      +
      +

      Choose pool sizes that leave capacity for other database clients and for the +AI provider calls made by DBMS_CLOUD_AI.

      +
      +
      + + +
      +
      +
      +
      + +
      +
      + + + + + diff --git a/docs/user_guide/connection.html b/docs/user_guide/connection.html index 2d2005e..7a97b81 100644 --- a/docs/user_guide/connection.html +++ b/docs/user_guide/connection.html @@ -5,14 +5,14 @@ - 3. Connecting to Oracle Database — Select AI for Python 1.3.0 documentation + 3. Connecting to Oracle Database — Select AI for Python 1.4.0rc1 documentation - + - + @@ -67,6 +67,8 @@

      Table of Contents

    • 3.1. Synchronous connection
    • 3.2. Asynchronous connection
    • 3.3. Connection Pool
    • +
    • 3.4. Connection health
    • +
    • 3.5. Wallet connections
    @@ -123,7 +125,7 @@

    Navigation

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • @@ -160,10 +162,32 @@

    Navigation

    3. Connecting to Oracle Database

    select_ai uses the Python thin driver i.e. python-oracledb to connect to the database and execute PL/SQL subprograms.

    +

    The library keeps the active connection or connection pool for the current +process so profile, credential, provider, vector index, and agent APIs can use +it without passing a connection object to each call. Use a standalone +connection for scripts and notebooks. Use a connection pool for applications +that handle concurrent work, such as web services or worker processes.

    +

    Most samples read connection values from environment variables:

    +
    export SELECT_AI_USER=<db_user>
    +export SELECT_AI_PASSWORD=<db_password>
    +export SELECT_AI_DB_CONNECT_STRING=<db_connect_string>
    +
    +
    +

    Then the Python code can load those values:

    +
    import os
    +import select_ai
    +
    +user = os.getenv("SELECT_AI_USER")
    +password = os.getenv("SELECT_AI_PASSWORD")
    +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING")
    +
    +select_ai.connect(user=user, password=password, dsn=dsn)
    +
    +

    3.1. Synchronous connection

    To connect to an Oracle Database synchronously, use -select_ai.connect() method as shown below

    +select_ai.connect() as shown below:

    import select_ai
     
     user = "<your_db_user>"
    @@ -172,6 +196,10 @@ 

    Navigation

    select_ai.connect(user=user, password=password, dsn=dsn)
    +

    Close a standalone synchronous connection with select_ai.disconnect():

    +
    select_ai.disconnect()
    +
    +

    3.2. Asynchronous connection

    @@ -185,11 +213,18 @@

    Navigation

    await select_ai.async_connect(user=user, password=password, dsn=dsn)

    +

    Close a standalone asynchronous connection with +await select_ai.async_disconnect():

    +
    await select_ai.async_disconnect()
    +
    +

    3.3. Connection Pool

    You can create a connection pool using the select_ai.create_pool -and select_ai.create_pool_async methods

    +and select_ai.create_pool_async methods. After a pool is created, these +methods configure Select AI operations to acquire and release connections from +the pool for each operation.

    -

    Check this blog which shows the benefit of connection pooling along with FastAPI service

    +

    Close a synchronous pool with select_ai.disconnect() and an asynchronous +pool with await select_ai.async_disconnect().

    +

    Create one pool per process. In multi-process deployments, each process creates +its own pool, so total database connections can grow quickly. Size pools based +on request concurrency and database capacity.

    +

    Use pooling for:

    +
      +
    • Web applications and API services.

    • +
    • Worker processes that handle multiple prompts.

    • +
    • Concurrent prompt processing.

    • +
    • Long-running applications that should avoid opening a new database connection +for every request.

    • +
    +

    Use a standalone connection for:

    +
      +
    • Short scripts.

    • +
    • Local examples.

    • +
    • One-off administration tasks.

    • +
    +

    Check this blog +which shows the benefit of connection pooling with a FastAPI service.

    +
    +
    +

    3.4. Connection health

    +

    Use select_ai.is_connected() or await select_ai.async_is_connected() +to check whether the current connection or pool is available:

    +
    if not select_ai.is_connected():
    +    select_ai.connect(user=user, password=password, dsn=dsn)
    +
    +
    +
    if not await select_ai.async_is_connected():
    +    await select_ai.async_connect(user=user, password=password, dsn=dsn)
    +
    +
    +
    +
    +

    3.5. Wallet connections

    Note

    -

    For m-TLS (wallet) based connection, additional parameters like -wallet_location, wallet_password, https_proxy, -https_proxy_port can be passed to the connect and async_connect -methods

    +

    For m-TLS (wallet) based connections, additional parameters like +wallet_location, wallet_password, config_dir, https_proxy, +and https_proxy_port can be passed to connect, async_connect, +create_pool, and create_pool_async.

    +
    +

    For example:

    +
    select_ai.connect(
    +    user=user,
    +    password=password,
    +    dsn=dsn,
    +    wallet_location="/path/to/wallet",
    +    config_dir="/path/to/wallet",
    +    wallet_password="<wallet_password>",
    +)
    +
    +

    The same keyword arguments can be used with async_connect and the pool +creation APIs.

    @@ -241,6 +326,8 @@

    Table of Contents

  • 3.1. Synchronous connection
  • 3.2. Asynchronous connection
  • 3.3. Connection Pool
  • +
  • 3.4. Connection health
  • +
  • 3.5. Wallet connections
  • @@ -297,7 +384,7 @@

    Navigation

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • diff --git a/docs/user_guide/conversation.html b/docs/user_guide/conversation.html index c268473..7c634b0 100644 --- a/docs/user_guide/conversation.html +++ b/docs/user_guide/conversation.html @@ -5,21 +5,21 @@ - 1. Conversation Object model — Select AI for Python 1.3.0 documentation + 1. Conversation Object model — Select AI for Python 1.4.0rc1 documentation - + - + - - + + @@ -78,7 +78,7 @@

    Table of Contents

  • Conversation.set_attributes()
  • -
  • 3.1. Create conversion
  • +
  • 3.1. Create conversation
  • 3.2. Chat session
  • 3.3. List conversations
  • 3.4. Delete conversation
  • @@ -104,12 +104,12 @@

    Table of Contents

    Previous topic

    12.1. AsyncProfile API

    + title="previous chapter">1. Async profile lifecycle

    Next topic

    1. VectorIndex Object Model

    + title="next chapter">1. Vector Index

    This Page

    @@ -139,10 +139,10 @@

    Navigation

    index
  • - next |
  • - previous |
  • Python logo
  • Python »
  • @@ -152,7 +152,7 @@

    Navigation

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • @@ -188,6 +188,24 @@

    Navigation

    Conversations in Select AI represent an interactive exchange between the user and the system, enabling users to query or interact with the database through a series of natural language prompts.

    +

    A conversation is stored in the database and identified by a +conversation_id. Pass that conversation to Profile.chat_session() or +AsyncProfile.chat_session() when follow-up prompts should use prior prompts +as context. This is useful for chat workflows where the user asks a question, +then asks follow-up questions such as “explain that further” or “show another +example”.

    +

    Use conversations when you need context across multiple prompts. For one-off +prompts, call profile methods such as chat(), show_sql(), or +narrate() directly without creating a conversation.

    +

    The usual lifecycle is:

    +
      +
    1. Create ConversationAttributes with a title, optional description, +retention period, and conversation length.

    2. +
    3. Create a Conversation or AsyncConversation object.

    4. +
    5. Use the conversation in profile.chat_session(...).

    6. +
    7. List, fetch, or update the conversation metadata when needed.

    8. +
    9. Delete the conversation when the stored history is no longer needed.

    10. +

    1. Conversation Object model

    @@ -196,6 +214,45 @@

    1.

    2. ConversationAttributes

    +

    ConversationAttributes controls the metadata and retention behavior for a +conversation:

    + + + + + + + + + + + + + + + + + + + + +

    Attribute

    Use

    title

    Human-readable conversation title. If omitted, the default is +"New Conversation".

    description

    Optional description of the conversation topic.

    retention_days

    Number of days to keep the conversation in the database from its +creation date. Use datetime.timedelta(days=...). A value of +datetime.timedelta(days=0) keeps the conversation until it is +manually deleted.

    conversation_length

    Number of prompts retained in the conversation context. The default is +10.

    +

    Example:

    +
    import datetime
    +
    +attributes = select_ai.ConversationAttributes(
    +    title="Sales analysis",
    +    description="Follow-up questions about quarterly sales",
    +    retention_days=datetime.timedelta(days=14),
    +    conversation_length=20,
    +)
    +
    +
    class select_ai.ConversationAttributes(title: str | None = 'New Conversation', description: str | None = None, retention_days: timedelta | None = datetime.timedelta(days=7), conversation_length: int | None = 10)
    @@ -277,7 +334,7 @@

    3.
    Returns:
    -

    Iterator[VectorIndex]

    +

    Iterator[Conversation]

    @@ -290,8 +347,45 @@

    3. -

    3.1. Create conversion

    +

    The synchronous API is used with select_ai.connect() or +select_ai.create_pool(). Important methods:

    + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Method

    Use

    create()

    Create a database conversation and return its conversation_id.

    fetch(conversation_id)

    Build a Conversation object from an existing database conversation.

    get_attributes()

    Read conversation metadata from the database.

    set_attributes(attributes)

    Update the title, description, retention period, or conversation +length.

    list()

    Iterate over conversations visible to the current user.

    delete(force=False)

    Drop the conversation. Use force=True to ignore missing-conversation +errors.

    +

    Profile.chat_session(conversation=..., delete=False) is a context manager. +If the conversation has attributes but no conversation_id, the session +creates it automatically. While the context manager is active, every +session.chat(...) call passes the same conversation_id to Select AI, so +follow-up prompts can use the conversation history. If delete=True, the +conversation is deleted when the session exits.

    +
    +

    3.1. Create conversation

    import os
     
     import select_ai
    @@ -318,6 +412,9 @@ 

    3.1. Create conversion

    3.2. Chat session

    +

    Use chat_session() to keep context across multiple chat prompts. The second +prompt in this example can refer to the previous answer because both prompts use +the same database conversation.

    import os
     
     import select_ai
    @@ -366,6 +463,8 @@ 

    3.2. Chat session

    3.3. List conversations

    +

    Listing returns Conversation objects with their conversation_id and +metadata. It does not replay the conversation transcript.

    import os
     
     import select_ai
    @@ -391,6 +490,10 @@ 

    3.3. List conversations

    3.4. Delete conversation

    +

    Delete conversations that are no longer needed, especially when +retention_days is set to 0 or when the content should not remain in the +database after a session ends. For temporary sessions, prefer +profile.chat_session(conversation=conversation, delete=True).

    import os
     
     import select_ai
    @@ -469,7 +572,7 @@ 

    4.
    Returns:
    -

    Iterator[VectorIndex]

    +

    AsyncGenerator[AsyncConversation, None]

    @@ -482,8 +585,42 @@

    4. select_ai.async_connect() or select_ai.create_pool_async().

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Synchronous API

    Async API

    Conversation.create()

    await AsyncConversation.create()

    Conversation.fetch(...)

    await AsyncConversation.fetch(...)

    Conversation.get_attributes()

    await AsyncConversation.get_attributes()

    Conversation.set_attributes(...)

    await AsyncConversation.set_attributes(...)

    for conversation in Conversation.list()

    async for conversation in AsyncConversation.list()

    Conversation.delete(...)

    await AsyncConversation.delete(...)

    with profile.chat_session(...)

    async with async_profile.chat_session(...)

    4.1. Async chat session

    +

    Use AsyncProfile.chat_session() in async applications. The conversation is +created automatically when the object has attributes and no conversation_id.

    import asyncio
     import os
     
    @@ -541,6 +678,7 @@ 

    4.1. Async chat session

    4.2. Async list conversations

    +

    AsyncConversation.list() is an async iterator.

    import asyncio
     import os
     
    @@ -597,7 +735,7 @@ 

    Table of Contents

  • Conversation.set_attributes()
  • -
  • 3.1. Create conversion
  • +
  • 3.1. Create conversation
  • 3.2. Chat session
  • 3.3. List conversations
  • 3.4. Delete conversation
  • @@ -623,12 +761,12 @@

    Table of Contents

    Previous topic

    12.1. AsyncProfile API

    + title="previous chapter">1. Async profile lifecycle

    Next topic

    1. VectorIndex Object Model

    + title="next chapter">1. Vector Index

    This Page

    @@ -658,10 +796,10 @@

    Navigation

    index
  • - next |
  • - previous |
  • Python logo
  • Python »
  • @@ -671,7 +809,7 @@

    Navigation

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • diff --git a/docs/user_guide/credential.html b/docs/user_guide/credential.html index 81d85a0..9014f3b 100644 --- a/docs/user_guide/credential.html +++ b/docs/user_guide/credential.html @@ -5,14 +5,14 @@ - 1. Create credential — Select AI for Python 1.3.0 documentation + 1. Create credential — Select AI for Python 1.4.0rc1 documentation - + - + @@ -68,13 +68,18 @@

    Table of Contents

  • 1.2. Async API
  • +
  • 2. Delete credential +
  • Previous topic

    1. Provider

    + title="previous chapter">1. Provider

    Next topic

    @@ -122,7 +127,7 @@

    Navigation

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • @@ -155,40 +160,113 @@

    Navigation

    -

    Credential object securely stores API key from your AI provider for use by Oracle Database. -The following table shows AI Provider and corresponding credential object format

    - - +

    A credential object securely stores authentication details from your AI +provider for use by Oracle Database. Select AI profiles, vector indexes, and +agent tools refer to the credential later by credential_name; the secret +values are stored in Oracle Database and are not passed again when the profile +or tool runs.

    +

    A credential is created in the connected user’s schema by +DBMS_CLOUD.CREATE_CREDENTIAL. Create credentials while connected as the +database user that will own and use them. Before creating credentials, make +sure the user has the required Select AI package privileges. If the credential +will be used to call an external AI provider, the database user also needs +network access to that provider endpoint.

    +

    Every credential object must include credential_name and the fields +required by the target provider. The library accepts the following credential +keys: credential_name, username, password, user_ocid, +tenancy_ocid, private_key, fingerprint, and comments.

    +

    The following table shows AI providers and corresponding credential object +formats.

    +
    AI Provider and expected credential format
    + - + - + + + + + + + + + + + + - - - @@ -199,6 +277,9 @@

    Navigation

    1. Create credential

    In this example, we create a credential object to authenticate to OCI Gen AI service provider:

    +

    Pass replace=True when you want to recreate an existing credential with the +same name. Without replace=True, creating a credential that already exists +raises a database error.

    1.1. Sync API

    import os
    @@ -273,6 +354,61 @@ 

    1.2. Async API

    + +
    +

    2. Delete credential

    +

    Use select_ai.delete_credential(...) to drop a credential that is no longer +needed. Pass force=True when cleanup should succeed even if the credential +does not exist.

    +
    +

    2.1. Sync API

    +
    
    +import select_ai
    +
    +user = os.getenv("SELECT_AI_USER")
    +password = os.getenv("SELECT_AI_PASSWORD")
    +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING")
    +
    +select_ai.connect(user=user, password=password, dsn=dsn)
    +select_ai.delete_credential(
    +    credential_name="my_oci_ai_profile_key", force=True
    +)
    +print("Deleted credential: my_oci_ai_profile_key")
    +
    +
    +

    output:

    +
    Deleted credential: my_oci_ai_profile_key
    +
    +
    +
    +
    +

    2.2. Async API

    +
    import asyncio
    +import os
    +
    +import select_ai
    +
    +user = os.getenv("SELECT_AI_USER")
    +password = os.getenv("SELECT_AI_PASSWORD")
    +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING")
    +
    +
    +async def main():
    +    await select_ai.async_connect(user=user, password=password, dsn=dsn)
    +    await select_ai.async_delete_credential(
    +        credential_name="my_oci_ai_profile_key", force=True
    +    )
    +    print("Deleted credential: my_oci_ai_profile_key")
    +
    +
    +asyncio.run(main())
    +
    +
    +

    output:

    +
    Deleted credential: my_oci_ai_profile_key
    +
    +
    +
    @@ -290,13 +426,18 @@

    Table of Contents

  • 1.2. Async API
  • +
  • 2. Delete credential +
  • Previous topic

    1. Provider

    + title="previous chapter">1. Provider

    Next topic

    @@ -344,7 +485,7 @@

    Navigation

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • diff --git a/docs/user_guide/installation.html b/docs/user_guide/installation.html index 2a5194e..984df2e 100644 --- a/docs/user_guide/installation.html +++ b/docs/user_guide/installation.html @@ -5,14 +5,14 @@ - 2. Installing select_ai — Select AI for Python 1.3.0 documentation + 2. Installing select_ai — Select AI for Python 1.4.0rc1 documentation - + - + @@ -66,6 +66,8 @@

    Table of Contents

  • 2. Installing select_ai
  • @@ -122,7 +124,7 @@

    Navigation

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • @@ -161,67 +163,105 @@

    Navigation

    2.1. Installation requirements

    To use select_ai you need:

      -
    • Python 3.9, 3.10, 3.11, 3.12, 3.13 or 3.14

    • -
    -
    -

    Warning

    -

    For async APIs, use Python 3.11 or higher. Python 3.11 stabilized the async -event loop management and introduced better-structured APIs

    -
    -
      -
    • python-oracledb - This package is automatically installed as a dependency requirement

    • -
    • pandas - This package is automatically installed as a dependency requirement

    • +
    • Python 3.11, 3.12, 3.13, or 3.14.

    • +
    • Access to an Oracle Database environment where Select AI is available.

    • +
    • A database user with the required Select AI package privileges. See +Privileges.

    • +
    • Network access from the database to any AI provider endpoints you plan to +use.

    • +
    • python-oracledb and pandas. These packages are installed +automatically as dependencies.

    +

    Using a virtual environment is recommended so the package and its dependencies +are isolated from your system Python installation.

    2.2. select_ai installation

    -

    select_ai can be installed from Python’s package repository +

    select_ai can be installed from the Python Package Index PyPI using pip.

    -
      +
      1. Install Python 3 if it is not already -available. Use any version from Python 3.9 through 3.14.

      2. -
      3. Install select_ai:

      4. -
      -
      -
      python3 -m pip install select_ai --upgrade --user
      +available. Use any version from Python 3.11 through 3.14.

      +
    1. Create and activate a virtual environment:

      +
      python3 -m venv .venv
      +source .venv/bin/activate
       
      -
    2. -
        -
      1. If you are behind a proxy, use the --proxy option. For example:

      2. -
      -
      -
      python3 -m pip install select_ai --upgrade --user --proxy=http://proxy.example.com:80
      +

      On Windows PowerShell:

      +
      py -3 -m venv .venv
      +.venv\Scripts\Activate.ps1
      +
      +
      + +
    3. Upgrade pip:

      +
      python -m pip install --upgrade pip
       
      -
    4. -
        -
      1. Create a file select_ai_connection_test.py such as:

      2. + +
      3. Install select_ai:

        +
        python -m pip install --upgrade select_ai
        +
        +
        +
      4. +
      5. If you want the optional command line interface, install the cli extra:

        +
        python -m pip install --upgrade "select_ai[cli]"
        +
        +
        +

        This installs the select-ai command. See Command Line Interface.

        +
      6. +
      7. If you are behind a proxy, use the --proxy option. For example:

        +
        python -m pip install --upgrade select_ai --proxy=http://proxy.example.com:80
        +
        +
        +
      -
      -
      import select_ai
      +
    +
    +

    2.3. Connection smoke test

    +

    After installation, verify that Python can import select_ai and connect to +Oracle Database.

    +
      +
    1. Set database connection environment variables:

      +
      export SELECT_AI_USER=<select_ai_db_user>
      +export SELECT_AI_PASSWORD=<select_ai_db_password>
      +export SELECT_AI_DB_CONNECT_STRING=<db_connect_string>
      +
      +
      +
    2. +
    3. Create a file select_ai_connection_test.py:

      +
      import os
      +
      +import select_ai
      +
      +user = os.getenv("SELECT_AI_USER")
      +password = os.getenv("SELECT_AI_PASSWORD")
      +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING")
       
      -user = "<your_db_user>"
      -password = "<your_db_password>"
      -dsn = "<your_db_dsn>"
       select_ai.connect(user=user, password=password, dsn=dsn)
       print("Connected to the Database")
       
      -
    -
      -
    1. Run select_ai_connection_test.py

    2. -
    -
    -
    python3 select_ai_connection_test.py
    +
    +
  • Run the script:

    +
    python select_ai_connection_test.py
     
    -

    Enter the database password when prompted and message will be shown:

    +

    If the connection succeeds, the script prints:

    Connected to the Database
     
    -
  • + + + +
    +

    2.4. Install documentation dependencies

    +

    If you are building this documentation locally from the repository, install the +documentation dependencies:

    +
    python -m pip install -r doc/requirements.txt
    +
    +
    +

    Then build the docs with the project’s Sphinx command or Makefile target.

    @@ -238,6 +278,8 @@

    Table of Contents

  • 2. Installing select_ai
  • @@ -294,7 +336,7 @@

    Navigation

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • diff --git a/docs/user_guide/introduction.html b/docs/user_guide/introduction.html index ce880d1..9bde940 100644 --- a/docs/user_guide/introduction.html +++ b/docs/user_guide/introduction.html @@ -5,14 +5,14 @@ - 1. Introduction to Select AI for Python — Select AI for Python 1.3.0 documentation + 1. Introduction to Select AI for Python — Select AI for Python 1.4.0rc1 documentation - + - + @@ -60,6 +60,19 @@ +

    Previous topic

    Navigation

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • @@ -150,10 +163,100 @@

    Navigation

    using Python. It supports text-to-SQL generation, retrieval augmented generation (RAG), synthetic data generation, and several other features using Oracle-based and third-party AI providers.

    -

    select_ai supports both synchronous and concurrent(asynchronous) -programming styles.

    -

    The Select AI Python API supports Python versions 3.9, 3.10, 3.11, 3.12 and -3.13.

    +

    Select AI for Python bridges Oracle Database’s Select AI capabilities and the +Python ecosystem. It gives Python applications a higher-level API for working +with AI providers, credentials, profiles, natural language prompts, vector +indexes, conversations, summarization, synthetic data, and AI agent workflows.

    +
    +

    1.1. What you can build

    +

    Use select_ai to:

    +
      +
    • Ask questions about database objects in natural language and generate SQL.

    • +
    • Run generated SQL and return results as Python objects such as pandas data +frames.

    • +
    • Generate narrative answers, explanations, prompt previews, translations, and +summaries.

    • +
    • Use Retrieval Augmented Generation (RAG) with vector indexes over documents +and object storage content.

    • +
    • Create synthetic data for database tables.

    • +
    • Build context-aware chat sessions with database-backed conversations.

    • +
    • Register tools, tasks, agents, and teams for database-backed AI agent +workflows.

    • +
    • Use the optional select-ai command line interface for interactive chat +and SQL workflows.

    • +
    • Use synchronous APIs, asynchronous APIs, and connection pools in scripts, +services, and web applications.

    • +
    +
    +
    +

    1.2. Core concepts

    +

    Most workflows use the same building blocks:

    +
    AI provider and expected credential format

    AI Provider

    AI provider

    Credential format

    Anthropic

    {"username": "anthropic", "password": "sk-xxx"}
    +
    {
    +    "credential_name": "ANTHROPIC_CRED",
    +    "username": "anthropic",
    +    "password": "sk-ant-xxx",
    +}
    +
    +
    +

    AWS Bedrock

    {
    +    "credential_name": "AWS_BEDROCK_CRED",
    +    "username": "<aws_access_key_id>",
    +    "password": "<aws_secret_access_key>",
    +}
    +
    +
    +

    Azure OpenAI

    {
    +    "credential_name": "AZURE_OPENAI_CRED",
    +    "username": "azure",
    +    "password": "<azure_openai_api_key>",
    +}
    +
    +
    +

    Cohere

    {
    +    "credential_name": "COHERE_CRED",
    +    "username": "cohere",
    +    "password": "<cohere_api_key>",
    +}
    +
    +
    +

    Google

    {
    +    "credential_name": "GOOGLE_CRED",
    +    "username": "google",
    +    "password": "<google_api_key>",
    +}
     

    HuggingFace

    {"username": "hf", "password": "hf_xxx"}
    +
    {
    +    "credential_name": "HUGGINGFACE_CRED",
    +    "username": "hf",
    +    "password": "hf_xxx",
    +}
     

    OCI Gen AI

    {"user_ocid": "", "tenancy_ocid": "", "private_key": "", "fingerprint": ""}
    +
    {
    +    "credential_name": "OCI_GENAI_CRED",
    +    "user_ocid": "<user_ocid>",
    +    "tenancy_ocid": "<tenancy_ocid>",
    +    "private_key": "<private_key_contents>",
    +    "fingerprint": "<fingerprint>",
    +}
     

    OpenAI

    {"username": "openai", "password": "sk-xxx"}
    +
    {
    +    "credential_name": "OPENAI_CRED",
    +    "username": "openai",
    +    "password": "sk-xxx",
    +}
     
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Concept

    Purpose

    Start here

    Connection

    Connect to Oracle Database using a standalone connection or a pool.

    Connection

    Privileges

    Grant package privileges and network ACLs required for Select AI calls.

    Privileges

    Provider

    Describe the AI service, model, endpoint, region, or provider-specific +options.

    Provider

    Credential

    Store provider and service secrets securely in Oracle Database.

    Credential

    Profile

    Combine provider, credential, database object scope, and generation +options into a reusable Select AI profile.

    Profile

    Actions

    Choose what Select AI should do with a prompt, such as show SQL, run +SQL, chat, narrate, summarize, or translate.

    Actions

    Conversation

    Keep prompt history for context-aware chat sessions.

    Conversation

    Vector index

    Index document content for RAG over trusted source material.

    Vector Index

    Agent

    Define tools, tasks, agents, and teams for multi-step AI workflows.

    Agent

    +

    +
    +

    1.3. Synchronous and asynchronous APIs

    +

    select_ai supports both synchronous and asynchronous programming styles. +Use the synchronous APIs for scripts, notebooks, command-line tools, and simple +services. Use the asynchronous APIs with asyncio applications, async web +frameworks, and workloads that need to run many prompts concurrently.

    +

    For long-running services, create a connection pool once during application +startup and close it during shutdown. See Connection, +Web Frameworks, and +Concurrent Prompt Processing for +patterns.

    +
    +
    +

    1.4. Supported Python versions

    +

    The Select AI Python API supports Python versions 3.11, 3.12, 3.13, and 3.14.

    +

    @@ -163,6 +266,19 @@

    Navigation

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • diff --git a/docs/user_guide/privileges.html b/docs/user_guide/privileges.html index 7b3ac63..27472c2 100644 --- a/docs/user_guide/privileges.html +++ b/docs/user_guide/privileges.html @@ -5,14 +5,14 @@ - 1. Grant privilege — Select AI for Python 1.3.0 documentation + 1. Grant privilege — Select AI for Python 1.4.0rc1 documentation - + - + @@ -65,6 +65,8 @@

    Table of Contents

    @@ -76,7 +78,7 @@

    Previous topic

    Next topic

    1. Provider

    + title="next chapter">1. Provider

    This Page

    @@ -119,7 +121,7 @@

    Navigation

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • @@ -152,14 +154,27 @@

    Navigation

    -

    Admin user should grant execute privilege to select ai database users -on the packages DBMS_CLOUD, DBMS_CLOUD_AI, DBMS_CLOUD_AI_AGENT -and DBMS_CLOUD_PIPELINE

    +

    An admin user should grant execute privilege to Select AI database users +on the packages DBMS_CLOUD, DBMS_CLOUD_AI, DBMS_CLOUD_AI_AGENT, +and DBMS_CLOUD_PIPELINE.

    +

    The privilege helper APIs are intended for database administrators who need to +prepare one or more database schemas for Select AI workloads. These operations +should be run from a connection that has permission to grant package execute +privileges and manage database network ACLs.

    +

    There are two separate setup steps:

    +
      +
    • Package privileges allow a Select AI database user to call the Oracle Database +PL/SQL packages used by this library.

    • +
    • Network access allows the database user to make outbound calls to specific +hosts, such as AI provider endpoints or SMTP servers.

    • +
    +

    The users argument accepts either a single database user name or a list of +database user names.

    Note

    All sample scripts in this documentation read Oracle database connection details from the environment. Create a dotenv file .env, export the -the following environment variables and source it before running the +following environment variables and source it before running the scripts.

    export SELECT_AI_ADMIN_USER=<db_admin>
     export SELECT_AI_ADMIN_PASSWORD=<db_admin_password>
    @@ -172,9 +187,11 @@ 

    Navigation

    1. Grant privilege

    -

    Connect as admin and run the method -select_ai.grant_privileges(users=select_ai_user) to grant relevant select ai -privileges to other users

    +

    Connect as an admin user and run +select_ai.grant_privileges(users=select_ai_user) to grant the package +execute privileges required by Select AI. This grants execute access on +DBMS_CLOUD, DBMS_CLOUD_AI, DBMS_CLOUD_AI_AGENT, and +DBMS_CLOUD_PIPELINE.

    import os
     
     import select_ai
    @@ -215,7 +232,131 @@ 

    2. Revoke privilege

    output:

    -
    Granted privileges to: <select_ai_db_user>
    +
    Revoked privileges from: <select_ai_db_user>
    +
    +
    +
    +
    +

    3. Grant network access

    +

    Connect as admin and run +select_ai.grant_network_access(...) to add a network ACL entry for +host access. This wraps DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE and can be +used for hosts that require privileges such as connect, http, or +smtp.

    +

    Network ACLs are required when the database needs to reach an external host. +For example, use http access for AI provider endpoints and smtp access +for mail servers. Include connect with protocol-specific privileges when +the host requires it.

    +

    When granting access, specify the target host and, when applicable, the port +range. When revoking access, use the same host, privileges, and port range that +were used for the grant.

    +
    import os
    +
    +import select_ai
    +
    +admin_user = os.getenv("SELECT_AI_ADMIN_USER")
    +password = os.getenv("SELECT_AI_ADMIN_PASSWORD")
    +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING")
    +select_ai_user = os.getenv("SELECT_AI_USER")
    +
    +select_ai.connect(user=admin_user, password=password, dsn=dsn)
    +select_ai.grant_network_access(
    +    users=select_ai_user,
    +    host="smtp.example.com",
    +    privileges=["connect", "smtp"],
    +    lower_port=587,
    +    upper_port=587,
    +)
    +print("Granted network access to: ", select_ai_user)
    +
    +
    +

    output:

    +
    Granted network access to: <select_ai_db_user>
    +
    +
    +

    The async API is select_ai.async_grant_network_access(...).

    +
    import asyncio
    +import os
    +
    +import select_ai
    +
    +admin_user = os.getenv("SELECT_AI_ADMIN_USER")
    +password = os.getenv("SELECT_AI_ADMIN_PASSWORD")
    +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING")
    +select_ai_user = os.getenv("SELECT_AI_USER")
    +
    +
    +async def main():
    +    await select_ai.async_connect(user=admin_user, password=password, dsn=dsn)
    +    await select_ai.async_grant_network_access(
    +        users=select_ai_user,
    +        host="smtp.example.com",
    +        privileges=["connect", "smtp"],
    +        lower_port=587,
    +        upper_port=587,
    +    )
    +    print("Granted network access to: ", select_ai_user)
    +
    +
    +asyncio.run(main())
    +
    +
    +
    +
    +

    4. Revoke network access

    +

    Connect as admin and run +select_ai.revoke_network_access(...) to remove a network ACL entry for +host access. This wraps DBMS_NETWORK_ACL_ADMIN.REMOVE_HOST_ACE and should +use the same host, privileges, and port range that were used to grant access.

    +
    import os
    +
    +import select_ai
    +
    +admin_user = os.getenv("SELECT_AI_ADMIN_USER")
    +password = os.getenv("SELECT_AI_ADMIN_PASSWORD")
    +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING")
    +select_ai_user = os.getenv("SELECT_AI_USER")
    +
    +select_ai.connect(user=admin_user, password=password, dsn=dsn)
    +select_ai.revoke_network_access(
    +    users=select_ai_user,
    +    host="smtp.example.com",
    +    privileges=["connect", "smtp"],
    +    lower_port=587,
    +    upper_port=587,
    +)
    +print("Revoked network access from: ", select_ai_user)
    +
    +
    +

    output:

    +
    Revoked network access from: <select_ai_db_user>
    +
    +
    +

    The async API is select_ai.async_revoke_network_access(...).

    +
    import asyncio
    +import os
    +
    +import select_ai
    +
    +admin_user = os.getenv("SELECT_AI_ADMIN_USER")
    +password = os.getenv("SELECT_AI_ADMIN_PASSWORD")
    +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING")
    +select_ai_user = os.getenv("SELECT_AI_USER")
    +
    +
    +async def main():
    +    await select_ai.async_connect(user=admin_user, password=password, dsn=dsn)
    +    await select_ai.async_revoke_network_access(
    +        users=select_ai_user,
    +        host="smtp.example.com",
    +        privileges=["connect", "smtp"],
    +        lower_port=587,
    +        upper_port=587,
    +    )
    +    print("Revoked network access from: ", select_ai_user)
    +
    +
    +asyncio.run(main())
     
    @@ -232,6 +373,8 @@

    Table of Contents

    @@ -243,7 +386,7 @@

    Previous topic

    Next topic

    1. Provider

    + title="next chapter">1. Provider

    This Page

    @@ -286,7 +429,7 @@

    Navigation

  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • diff --git a/docs/user_guide/profile.html b/docs/user_guide/profile.html index 9f45411..738f801 100644 --- a/docs/user_guide/profile.html +++ b/docs/user_guide/profile.html @@ -5,20 +5,20 @@ - 1. Profile Object Model — Select AI for Python 1.3.0 documentation + 1. Profile lifecycle — Select AI for Python 1.4.0rc1 documentation - + - + - + @@ -63,12 +63,14 @@ @@ -116,7 +125,7 @@

    Previous topic

    Next topic

    1. AsyncProfile API

    + title="next chapter">1. Async profile lifecycle

    This Page

    @@ -146,7 +155,7 @@

    Navigation

    index
  • - next |
  • Navigation
  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • - +
  • @@ -195,15 +204,80 @@

    Navigation

    An AI profile is a specification that includes the AI provider to use and other details regarding metadata and database objects required for generating responses to natural language prompts.

    -

    An AI profile object can be created using select_ai.Profile()

    +

    An AI profile object can be created using select_ai.Profile(). Creating a +profile stores the profile in Oracle Database. Later, you can instantiate +select_ai.Profile(profile_name="...") to reuse an existing database profile +without passing all attributes again.

    +

    Before creating a profile, make sure the database user has the required +privileges, a credential for the AI provider, network access to the provider +endpoint, and access to the database objects included in the profile. See +Privileges, Credential, +Provider, and +ProfileAttributes.

    +
    +

    1. Profile lifecycle

    +

    The usual profile lifecycle is:

    +
      +
    • Create a provider object.

    • +
    • Create ProfileAttributes with the provider, credential name, and object +list.

    • +
    • Create the profile with select_ai.Profile(...).

    • +
    • Reuse the profile later by name.

    • +
    • Update profile attributes when provider settings or object scope changes.

    • +
    • Delete profiles that are no longer needed.

    • +
    +

    replace=True recreates a profile when a profile with the same name already +exists. merge=True fetches the existing profile and updates it with the +non-null attributes passed by the caller.

    +
    +
    +

    2. Profile actions

    + + ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Common profile actions

    Method

    Description

    show_sql()

    Generates SQL for a natural language prompt without executing it.

    run_sql()

    Generates SQL, executes it, and returns a pandas.DataFrame.

    narrate()

    Generates SQL, executes it, and returns a natural language answer.

    explain_sql()

    Explains the generated SQL for a prompt.

    show_prompt()

    Shows the prompt sent to the model.

    chat()

    Sends a general chat prompt to the model.

    summarize()

    Summarizes inline content or content referenced by a URI.

    translate()

    Translates text from one language to another.

    -

    Profile Object Model

    +

    2.1. Profile Object Model

    Select AI Profile and Providers
    -

    Base Profile API

    +

    2.2. Base Profile API

    class select_ai.BaseProfile(profile_name: str | None = None, attributes: ProfileAttributes | None = None, description: str | None = None, merge: bool | None = False, replace: bool | None = False, raise_error_if_exists: bool | None = True, raise_error_on_empty_attributes: bool | None = False)
    @@ -235,7 +309,7 @@

    Base Profile
    -

    Profile API

    +

    2.3. Profile API

    class select_ai.Profile(*args, **kwargs)
    @@ -277,13 +351,15 @@

    Profile<
    -chat(prompt: str, params: Mapping = None) str
    +chat(prompt: str, params: Mapping = None, stream: bool = False, chunk_size: int = 8192) str | Generator[str, None, None]

    Chat with the LLM

    Parameters:
    • prompt (str) – Natural language prompt

    • params – Parameters to include in the LLM request

    • +
    • stream (bool) – Return an iterator of response chunks

    • +
    • chunk_size (int) – Number of characters to read per stream chunk

    Returns:
    @@ -381,13 +457,15 @@

    Profile<
    -explain_sql(prompt: str, params: Mapping = None) str
    +explain_sql(prompt: str, params: Mapping = None, stream: bool = False, chunk_size: int = 8192) str | Generator[str, None, None]

    Explain the generated SQL

    Parameters:
    • prompt (str) – Natural language prompt

    • params – Parameters to include in the LLM request

    • +
    • stream (bool) – Return an iterator of response chunks

    • +
    • chunk_size (int) – Number of characters to read per stream chunk

    Returns:
    @@ -416,7 +494,7 @@

    Profile<
    -generate(prompt: str, action: Action | None = Action.RUNSQL, params: Mapping = None) DataFrame | str | None
    +generate(prompt: str, action: Action | None = Action.RUNSQL, params: Mapping = None, stream: bool = False, chunk_size: int = 8192) DataFrame | str | Generator[str, None, None] | None

    Perform AI translation using this profile

    Parameters:
    @@ -425,6 +503,8 @@

    Profile<
  • action (select_ai.profile.Action)

  • params – Parameters to include in the LLM request. For e.g. conversation_id for context-aware chats

  • +
  • stream (bool) – Return an iterator of response chunks

  • +
  • chunk_size (int) – Number of characters to read per stream chunk

  • Returns:
    @@ -480,13 +560,15 @@

    Profile<
    -narrate(prompt: str, params: Mapping = None) str
    +narrate(prompt: str, params: Mapping = None, stream: bool = False, chunk_size: int = 8192) str | Generator[str, None, None]

    Narrate the result of the SQL

    Parameters:
    • prompt (str) – Natural language prompt

    • params – Parameters to include in the LLM request

    • +
    • stream (bool) – Return an iterator of response chunks

    • +
    • chunk_size (int) – Number of characters to read per stream chunk

    Returns:
    @@ -550,13 +632,15 @@

    Profile<
    -show_prompt(prompt: str, params: Mapping = None) str
    +show_prompt(prompt: str, params: Mapping = None, stream: bool = False, chunk_size: int = 8192) str | Generator[str, None, None]

    Show the prompt sent to LLM

    Parameters:
    • prompt (str) – Natural language prompt

    • params – Parameters to include in the LLM request

    • +
    • stream (bool) – Return an iterator of response chunks

    • +
    • chunk_size (int) – Number of characters to read per stream chunk

    Returns:
    @@ -567,13 +651,15 @@

    Profile<
    -show_sql(prompt: str, params: Mapping = None) str
    +show_sql(prompt: str, params: Mapping = None, stream: bool = False, chunk_size: int = 8192) str | Generator[str, None, None]

    Show the generated SQL

    Parameters:
    • prompt (str) – Natural language prompt

    • params – Parameters to include in the LLM request

    • +
    • stream (bool) – Return an iterator of response chunks

    • +
    • chunk_size (int) – Number of characters to read per stream chunk

    Returns:
    @@ -625,7 +711,9 @@

    Profile<

    -

    Create Profile

    +

    2.4. Create Profile

    +

    The following example creates an OCI Gen AI profile that can generate SQL over +objects in the SH schema.

    import os
     from pprint import pformat
     
    @@ -689,8 +777,51 @@ 

    Create Profile +

    2.5. Reuse Profile

    +

    After a profile has been created, instantiate Profile with only the profile +name to reuse the database profile:

    +
    profile = select_ai.Profile(profile_name="oci_ai_profile")
    +sql = profile.show_sql(prompt="How many promotions?")
    +
    +
    +

    Use Profile.fetch(...) when you want to create a proxy object from a saved +database profile and raise an error if the profile does not exist:

    +
    profile = select_ai.Profile.fetch("oci_ai_profile")
    +
    +
    +

    +
    +

    2.6. Update Profile

    +

    Use set_attribute(...) to update one profile attribute or +set_attributes(...) to update several attributes. Updates are saved to the +database profile.

    +
    profile = select_ai.Profile(profile_name="oci_ai_profile")
    +profile.set_attribute("temperature", 0.1)
    +
    +profile.set_attributes(
    +    select_ai.ProfileAttributes(
    +        max_tokens=2048,
    +        enforce_object_list=True,
    +    )
    +)
    +
    +
    +
    +
    +

    2.7. Delete Profile

    +

    Use delete(...) or Profile.delete_profile(...) to remove a profile from +the database. Pass force=True when cleanup should succeed even if the +profile does not exist.

    +
    profile = select_ai.Profile(profile_name="oci_ai_profile")
    +profile.delete(force=True)
    +
    +select_ai.Profile.delete_profile("oci_ai_profile", force=True)
    +
    +
    +
    -

    Narrate

    +

    2.8. Narrate

    import os
     
     import select_ai
    @@ -713,7 +844,7 @@ 

    Narrate

    -

    Show SQL

    +

    2.9. Show SQL

    import os
     
     import select_ai
    @@ -735,8 +866,29 @@ 

    Show SQL

    +
    +

    2.10. Explain SQL

    +

    Use explain_sql(...) to generate SQL and return a natural language +explanation without executing the SQL.

    +
    profile = select_ai.Profile(profile_name="oci_ai_profile")
    +explanation = profile.explain_sql(prompt="How many promotions?")
    +print(explanation)
    +
    +
    +
    +
    +

    2.11. Show Prompt

    +

    Use show_prompt(...) to inspect the prompt that Select AI sends to the +model. This is useful when tuning profile attributes, object lists, comments, +constraints, and provider settings.

    +
    profile = select_ai.Profile(profile_name="oci_ai_profile")
    +prompt = profile.show_prompt(prompt="How many promotions?")
    +print(prompt)
    +
    +
    +
    -

    Run SQL

    +

    2.12. Run SQL

    import os
     
     import select_ai
    @@ -760,7 +912,7 @@ 

    Run SQL

    -

    Chat

    +

    2.13. Chat

    import os
     
     import select_ai
    @@ -783,8 +935,37 @@ 

    Chat

    +
    +

    2.14. Streaming chat

    +
    import os
    +
    +import select_ai
    +
    +user = os.getenv("SELECT_AI_USER")
    +password = os.getenv("SELECT_AI_PASSWORD")
    +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING")
    +
    +select_ai.connect(user=user, password=password, dsn=dsn)
    +profile = select_ai.Profile(profile_name="oci_ai_profile")
    +
    +for chunk in profile.chat(
    +    prompt="What is OCI ?", stream=True, chunk_size=4096
    +):
    +    print(chunk, end="")
    +print()
    +
    +
    +

    stream=True lets callers consume generated CLOB responses chunk by chunk, +reducing memory pressure and making it easier to progressively forward output +to files, services, or user interfaces. Streaming text APIs return an iterator +of str chunks. The chunk_size parameter controls the number of CLOB +characters read per chunk; it is not a byte count.

    +

    Streaming is supported by generate(), chat(), narrate(), +explain_sql(), show_sql(), and show_prompt(). It is not supported +for run_sql(), which returns a pandas.DataFrame.

    +
    -

    Summarize

    +

    2.15. Summarize

    Summarize inline content

    @@ -961,12 +1100,14 @@

    Async ProfileTable of Contents

  • @@ -1014,7 +1162,7 @@

    Previous topic

    Next topic

    1. AsyncProfile API

    + title="next chapter">1. Async profile lifecycle

    This Page

    @@ -1044,7 +1192,7 @@

    Navigation

    index
  • - next |
  • Navigation
  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • - +
  • diff --git a/docs/user_guide/profile_attributes.html b/docs/user_guide/profile_attributes.html index fd440cd..67b91ed 100644 --- a/docs/user_guide/profile_attributes.html +++ b/docs/user_guide/profile_attributes.html @@ -5,20 +5,20 @@ - 1. ProfileAttributes — Select AI for Python 1.3.0 documentation + 1. ProfileAttributes — Select AI for Python 1.4.0rc1 documentation - + - + - + @@ -64,9 +64,15 @@

    Table of Contents

  • @@ -78,7 +84,7 @@

    Previous topic

    Next topic

    1. Profile Object Model

    + title="next chapter">1. Profile lifecycle

    This Page

    @@ -108,7 +114,7 @@

    Navigation

    index
  • - next |
  • Navigation
  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • @@ -156,9 +162,134 @@

    Navigation

    1. ProfileAttributes

    -

    This class defines attributes to manage and configure the behavior of -the AI profile. The ProfileAttributes objects are created -by select_ai.ProfileAttributes().

    +

    This class defines attributes that manage and configure the behavior of an AI +profile. ProfileAttributes objects are created with +select_ai.ProfileAttributes() and passed to select_ai.Profile or +select_ai.AsyncProfile when creating or updating a profile.

    +

    Profile attributes describe what the profile can access, which AI provider it +uses, how much metadata is sent to the model, and how generation should behave. +Provider-specific settings, such as OCI region or Azure deployment name, are +configured on the provider object and assigned to the provider attribute.

    +
    +

    1.1. Common required attributes

    +

    Most profiles need these attributes:

    +
      +
    • provider: A select_ai.Provider object, such as +select_ai.OCIGenAIProvider or select_ai.OpenAIProvider.

    • +
    • credential_name: The database credential used to authenticate with the +AI provider.

    • +
    • object_list: The schemas, tables, or views that Select AI can use when +generating SQL from natural language prompts.

    • +
    +

    For example:

    +
    attributes = select_ai.ProfileAttributes(
    +    provider=select_ai.OCIGenAIProvider(
    +        region="us-chicago-1",
    +        oci_apiformat="GENERIC",
    +    ),
    +    credential_name="my_oci_ai_profile_key",
    +    object_list=[
    +        {"owner": "SH", "name": "CUSTOMERS"},
    +        {"owner": "SH", "name": "SALES"},
    +    ],
    +)
    +
    +
    +
    +
    +

    1.2. Attribute groups

    + + ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Profile attribute groups

    Attribute

    Purpose

    provider

    Selects the AI provider, model, endpoint, and provider-specific +options.

    credential_name

    Names the database credential used to authenticate with the AI provider.

    object_list

    Defines which schemas, tables, or views are eligible for natural +language to SQL generation.

    object_list_mode

    Controls whether Select AI sends metadata for the most relevant objects +or for all eligible objects.

    enforce_object_list

    Restricts generated SQL to objects in object_list.

    comments, constraints, annotations

    Controls whether additional database metadata is included in the prompt +sent to the model.

    case_sensitive_values

    Helps prompts that depend on case-sensitive database values.

    max_tokens, temperature, stop_tokens, seed

    Tunes model generation behavior.

    conversation

    Enables conversation history for context-aware chat workflows.

    vector_index_name, enable_sources, +enable_source_offsets, enable_custom_source_uri

    Configures retrieval-augmented generation and source reporting for +vector index workflows.

    +
    +
    +

    1.3. Object list examples

    +

    Grant access to every supported object in a schema:

    +
    object_list = [{"owner": "SH"}]
    +
    +
    +

    Grant access to selected tables:

    +
    object_list = [
    +    {"owner": "SH", "name": "CUSTOMERS"},
    +    {"owner": "SH", "name": "SALES"},
    +    {"owner": "SH", "name": "PRODUCTS"},
    +]
    +
    +
    +

    Restrict generated SQL to the selected objects:

    +
    attributes = select_ai.ProfileAttributes(
    +    provider=provider,
    +    credential_name="my_oci_ai_profile_key",
    +    object_list=[
    +        {"owner": "SH", "name": "CUSTOMERS"},
    +        {"owner": "SH", "name": "SALES"},
    +    ],
    +    enforce_object_list=True,
    +)
    +
    +
    +
    +
    +

    1.4. Generation controls

    +

    Use generation controls when you need more predictable or constrained model +responses:

    +
    attributes = select_ai.ProfileAttributes(
    +    provider=provider,
    +    credential_name="my_oci_ai_profile_key",
    +    object_list=[{"owner": "SH"}],
    +    max_tokens=1024,
    +    temperature=0.1,
    +    stop_tokens='[";"]',
    +)
    +
    +
    class select_ai.ProfileAttributes(annotations: bool | None = None, case_sensitive_values: bool | None = None, comments: bool | None = None, constraints: bool | None = None, conversation: bool | None = None, credential_name: str | None = None, enable_custom_source_uri: bool | None = None, enable_sources: bool | None = None, enable_source_offsets: bool | None = None, enforce_object_list: bool | None = None, max_tokens: int | None = 1024, object_list: List[Mapping] | None = None, object_list_mode: str | None = None, provider: Provider | None = None, seed: str | None = None, stop_tokens: str | None = None, streaming: str | None = None, temperature: float | None = None, vector_index_name: str | None = None)
    @@ -199,6 +330,7 @@

    Navigation

    +
    @@ -212,9 +344,15 @@

    Navigation

    Table of Contents

    @@ -226,7 +364,7 @@

    Previous topic

    Next topic

    1. Profile Object Model

    + title="next chapter">1. Profile lifecycle

    This Page

    @@ -256,7 +394,7 @@

    Navigation

    index
  • - next |
  • Navigation
  • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
  • diff --git a/docs/user_guide/provider.html b/docs/user_guide/provider.html index 7a999a7..6c80485 100644 --- a/docs/user_guide/provider.html +++ b/docs/user_guide/provider.html @@ -5,14 +5,14 @@ - 1. Provider — Select AI for Python 1.3.0 documentation + 1. Provider — Select AI for Python 1.4.0rc1 documentation - + - + @@ -63,50 +63,54 @@

    Table of Contents

      -
    • 1. Provider
        +
      • 1. Provider
          +
        • 1.1. Examples
        • +
        • 1.2. Provider
        • -
        • 2. AnthropicProvider
            +
          • 1.3. AnthropicProvider
          • -
          • 3. AzureProvider
              +
            • 1.4. AzureProvider
            • -
            • 4. AWSProvider
                +
              • 1.5. AWSProvider
              • -
              • 5. CohereProvider
                  +
                • 1.6. CohereProvider
                • -
                • 6. OpenAIProvider
                    +
                  • 1.7. OpenAIProvider
                  • -
                  • 7. OCIGenAIProvider
                      +
                    • 1.8. OCIGenAIProvider
                    • -
                    • 8. GoogleProvider
                        +
                      • 1.9. GoogleProvider
                      • -
                      • 9. HuggingFaceProvider
                          +
                        • 1.10. HuggingFaceProvider
                        • -
                        • 10. Enable AI service provider @@ -163,10 +167,10 @@

                          Navigation

                        • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
                        • - +
                        • @@ -196,14 +200,139 @@

                          Navigation

                          -

                          An AI Provider in Select AI refers to the service provider of the +

                          +

                          1. Provider

                          +

                          An AI Provider in Select AI refers to the service provider of the LLM, transformer or both for processing and generating responses to natural language prompts. These providers offer models that can interpret and convert natural language for the use cases highlighted under the LLM concept.

                          See Select your AI Provider -for the supported providers

                          -
                          -

                          1. Provider

                          +for the supported providers.

                          +

                          A provider object describes the AI service that a Select AI profile, vector +index, or agent tool should call. The provider object is separate from the +credential object: the provider selects the service, model, endpoint, region, +and provider-specific options, while the credential stores authentication +details.

                          +

                          Most applications should instantiate one of the concrete provider classes +instead of using Provider directly. Use the base Provider class when +you need to call a compatible provider endpoint that does not have a dedicated +class in this library.

                          + + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                          Provider classes

                          Provider class

                          Provider name

                          Default endpoint behavior

                          AnthropicProvider

                          anthropic

                          Uses api.anthropic.com.

                          AWSProvider

                          aws

                          Builds bedrock-runtime.<region>.amazonaws.com from region.

                          AzureProvider

                          azure

                          Builds <azure_resource_name>.openai.azure.com.

                          CohereProvider

                          cohere

                          Uses api.cohere.ai.

                          GoogleProvider

                          google

                          Uses generativelanguage.googleapis.com.

                          HuggingFaceProvider

                          huggingface

                          Uses api-inference.huggingface.co.

                          OCIGenAIProvider

                          oci

                          Uses OCI region and OCI Gen AI attributes.

                          OpenAIProvider

                          openai

                          Uses api.openai.com.

                          +
                          +

                          1.1. Examples

                          +

                          OCI Gen AI provider:

                          +
                          provider = select_ai.OCIGenAIProvider(
                          +    region="us-chicago-1",
                          +    oci_apiformat="GENERIC",
                          +    model="cohere.command-r-plus",
                          +)
                          +
                          +
                          +

                          OpenAI provider:

                          +
                          provider = select_ai.OpenAIProvider(
                          +    model="gpt-4.1",
                          +)
                          +
                          +
                          +

                          Azure OpenAI provider:

                          +
                          provider = select_ai.AzureProvider(
                          +    azure_resource_name="my-azure-openai-resource",
                          +    azure_deployment_name="gpt-4o-deployment",
                          +    azure_embedding_deployment_name="text-embedding-deployment",
                          +)
                          +
                          +
                          +

                          AWS Bedrock provider:

                          +
                          provider = select_ai.AWSProvider(
                          +    region="us-east-1",
                          +    aws_apiformat="ANTHROPIC",
                          +    model="anthropic.claude-3-5-sonnet-20240620-v1:0",
                          +)
                          +
                          +
                          +

                          Custom provider endpoint:

                          +
                          select_ai.create_credential(
                          +    credential={
                          +        "credential_name": "xai_credential",
                          +        "username": "xai",
                          +        "password": "<xai_api_key>",
                          +    },
                          +    replace=True,
                          +)
                          +
                          +xai_profile = select_ai.Profile(
                          +    profile_name="xai",
                          +    attributes=select_ai.ProfileAttributes(
                          +        provider=select_ai.Provider(
                          +            provider_endpoint="https://api.x.ai",
                          +            model="grok-4-1-fast-reasoning",
                          +        ),
                          +        credential_name="xai_credential",
                          +        object_list=[
                          +            {"owner": "SH", "name": "CUSTOMERS"},
                          +            {"owner": "SH", "name": "SALES"},
                          +            {"owner": "SH", "name": "PRODUCTS"},
                          +            {"owner": "SH", "name": "COUNTRIES"},
                          +        ],
                          +    ),
                          +    replace=True,
                          +)
                          +
                          +sql = xai_profile.show_sql(
                          +    prompt="How many customers do I have?",
                          +)
                          +
                          +
                          +
                          +
                          +

                          1.2. Provider

                          class select_ai.Provider(embedding_model: str | None = None, model: str | None = None, provider_name: str | None = None, provider_endpoint: str | None = None, region: str | None = None)
                          @@ -228,7 +357,7 @@

                          1. -

                          2. AnthropicProvider

                          +

                          1.3. AnthropicProvider

                          class select_ai.AnthropicProvider(embedding_model: str | None = None, model: str | None = None, provider_name: str = 'anthropic', provider_endpoint: str | None = None, region: str | None = None)
                          @@ -237,7 +366,7 @@

                          2. -

                          3. AzureProvider

                          +

                          1.4. AzureProvider

                          class select_ai.AzureProvider(embedding_model: str | None = None, model: str | None = None, provider_name: str = 'azure', provider_endpoint: str | None = None, region: str | None = None, azure_deployment_name: str | None = None, azure_embedding_deployment_name: str | None = None, azure_resource_name: str | None = None)
                          @@ -257,7 +386,7 @@

                          3. -

                          4. AWSProvider

                          +

                          1.5. AWSProvider

                          class select_ai.AWSProvider(embedding_model: str | None = None, model: str | None = None, provider_name: str = 'aws', provider_endpoint: str | None = None, region: str | None = None, aws_apiformat: str | None = None)
                          @@ -266,7 +395,7 @@

                          4. -

                          5. CohereProvider

                          +

                          1.6. CohereProvider

                          class select_ai.CohereProvider(embedding_model: str | None = None, model: str | None = None, provider_name: str = 'cohere', provider_endpoint: str | None = None, region: str | None = None)
                          @@ -275,7 +404,7 @@

                          5. -

                          6. OpenAIProvider

                          +

                          1.7. OpenAIProvider

                          class select_ai.OpenAIProvider(embedding_model: str | None = None, model: str | None = None, provider_name: str = 'openai', provider_endpoint: str | None = 'api.openai.com', region: str | None = None)
                          @@ -284,7 +413,7 @@

                          6. -

                          7. OCIGenAIProvider

                          +

                          1.8. OCIGenAIProvider

                          class select_ai.OCIGenAIProvider(embedding_model: str | None = None, model: str | None = None, provider_name: str = 'oci', provider_endpoint: str | None = None, region: str | None = None, oci_apiformat: str | None = None, oci_compartment_id: str | None = None, oci_endpoint_id: str | None = None, oci_runtimetype: str | None = None)
                          @@ -307,7 +436,7 @@

                          7. -

                          8. GoogleProvider

                          +

                          1.9. GoogleProvider

                          class select_ai.GoogleProvider(embedding_model: str | None = None, model: str | None = None, provider_name: str = 'google', provider_endpoint: str | None = None, region: str | None = None)
                          @@ -316,7 +445,7 @@

                          8. -

                          9. HuggingFaceProvider

                          +

                          1.10. HuggingFaceProvider

                          class select_ai.HuggingFaceProvider(embedding_model: str | None = None, model: str | None = None, provider_name: str = 'huggingface', provider_endpoint: str | None = None, region: str | None = None)
                          @@ -325,11 +454,12 @@

                          9. -

                          10. Enable AI service provider

                          +

                          1.11. Enable AI service provider

                          -

                          10.1. Enable using Sync API

                          +

                          1.11.1. Enable using Sync API

                          This method adds ACL allowing database users to invoke AI provider’s -HTTP endpoint

                          +HTTP endpoint. For non-HTTP or port-specific network access, use the network +ACL helpers described in Privileges.

                          import os
                           
                           import select_ai
                          @@ -352,7 +482,7 @@ 

                          10.1. Enable using Sync API -

                          10.2. Enable using Async API

                          +

                          1.11.2. Enable using Async API

                          import asyncio
                           import os
                           
                          @@ -382,11 +512,11 @@ 

                          10.2. Enable using Async API -

                          11. Disable AI service provider

                          -

                          This method removes ACL blocking database users to invoke AI provider’s -HTTP endpoint

                          +

                          1.12. Disable AI service provider

                          +

                          This method removes the ACL entry that allows database users to invoke an AI +provider’s HTTP endpoint.

                          -

                          11.1. Disable using Sync API

                          +

                          1.12.1. Disable using Sync API

                          import os
                           
                           import select_ai
                          @@ -409,7 +539,7 @@ 

                          11.1. Disable using Sync API -

                          11.2. Disable using Async API

                          +

                          1.12.2. Disable using Async API

                          import asyncio
                           import os
                           
                          @@ -437,6 +567,7 @@ 

                          11.2. Disable using Async API11.2. Disable using Async APITable of Contents

                            -
                          • 1. Provider
                              +
                            • 1. Provider
                                +
                              • 1.1. Examples
                              • +
                              • 1.2. Provider
                              • -
                              • 2. AnthropicProvider
                                  +
                                • 1.3. AnthropicProvider
                                • -
                                • 3. AzureProvider
                                    +
                                  • 1.4. AzureProvider
                                  • -
                                  • 4. AWSProvider
                                      +
                                    • 1.5. AWSProvider
                                    • -
                                    • 5. CohereProvider
                                        +
                                      • 1.6. CohereProvider
                                      • -
                                      • 6. OpenAIProvider
                                          +
                                        • 1.7. OpenAIProvider
                                        • -
                                        • 7. OCIGenAIProvider
                                            +
                                          • 1.8. OCIGenAIProvider
                                          • -
                                          • 8. GoogleProvider
                                              +
                                            • 1.9. GoogleProvider
                                            • -
                                            • 9. HuggingFaceProvider
                                                +
                                              • 1.10. HuggingFaceProvider
                                              • -
                                              • 10. Enable AI service provider @@ -549,10 +684,10 @@

                                                Navigation

                                              • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
                                              • - +
                                              • diff --git a/docs/user_guide/summary.html b/docs/user_guide/summary.html index 66db962..836e9f9 100644 --- a/docs/user_guide/summary.html +++ b/docs/user_guide/summary.html @@ -5,21 +5,21 @@ - 1. SummaryParams — Select AI for Python 1.3.0 documentation + 1. Inline content — Select AI for Python 1.4.0rc1 documentation - + - + - - + + @@ -63,34 +63,42 @@

                                                Previous topic

                                                1. SyntheticDataAttributes

                                                + title="previous chapter">1. Generation modes

                                                Next topic

                                                Tool

                                                + title="next chapter">1. Tool

                                                This Page

                                                @@ -120,10 +128,10 @@

                                                Navigation

                                                index
                                              • - next |
                                              • - previous |
                                              • Python logo
                                              • Python »
                                              • @@ -133,10 +141,10 @@

                                                Navigation

                                              • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
                                              • - +
                                              • @@ -166,8 +174,99 @@

                                                Navigation

                                                -
                                                -

                                                1. SummaryParams

                                                +

                                                Summarization uses a Select AI profile to summarize inline text or content +available from a URI. The profile supplies the AI provider, model, credential, +and generation settings. The summarize APIs are available on both +Profile and AsyncProfile.

                                                +

                                                Use one content source per call:

                                                +
                                                  +
                                                • content for inline text.

                                                • +
                                                • location_uri for content available from a URL, object storage URI, or +supported file location.

                                                • +
                                                +

                                                Use credential_name when the location_uri requires a database +credential, such as object storage access. Use prompt to guide what the +summary should focus on.

                                                +
                                                +

                                                1. Inline content

                                                +
                                                profile = select_ai.Profile(profile_name="oci_ai_profile")
                                                +
                                                +summary = profile.summarize(
                                                +    content="Long text to summarize...",
                                                +    prompt="Summarize the key business implications.",
                                                +)
                                                +print(summary)
                                                +
                                                +
                                                +
                                                +
                                                +

                                                2. Content from a URI

                                                +
                                                profile = select_ai.Profile(profile_name="oci_ai_profile")
                                                +
                                                +summary = profile.summarize(
                                                +    location_uri="https://en.wikipedia.org/wiki/Astronomy",
                                                +)
                                                +print(summary)
                                                +
                                                +
                                                +
                                                +
                                                +

                                                3. Content from object storage

                                                +

                                                Pass credential_name when the target location requires authentication:

                                                +
                                                profile = select_ai.Profile(profile_name="oci_ai_profile")
                                                +
                                                +summary = profile.summarize(
                                                +    location_uri=(
                                                +        "https://objectstorage.us-ashburn-1.oraclecloud.com/"
                                                +        "n/namespace/b/bucket/o/document.txt"
                                                +    ),
                                                +    credential_name="OBJECT_STORE_CRED",
                                                +)
                                                +print(summary)
                                                +
                                                +
                                                +
                                                +
                                                +

                                                4. Summary parameters

                                                +

                                                Use SummaryParams to control output length, output style, chunk processing, +and extractiveness:

                                                +
                                                params = select_ai.summary.SummaryParams(
                                                +    min_words=50,
                                                +    max_words=150,
                                                +    summary_style=select_ai.summary.Style.LIST,
                                                +    chunk_processing_method=(
                                                +        select_ai.summary.ChunkProcessingMethod.MAP_REDUCE
                                                +    ),
                                                +    extractiveness_level=select_ai.summary.ExtractivenessLevel.MEDIUM,
                                                +)
                                                +
                                                +summary = profile.summarize(
                                                +    content="Long text to summarize...",
                                                +    params=params,
                                                +)
                                                +
                                                +
                                                +
                                                +
                                                +

                                                5. Async summary

                                                +
                                                async_profile = await select_ai.AsyncProfile(
                                                +    profile_name="async_oci_ai_profile",
                                                +)
                                                +
                                                +summary = await async_profile.summarize(
                                                +    content="Long text to summarize...",
                                                +    prompt="Summarize the main points.",
                                                +)
                                                +print(summary)
                                                +
                                                +
                                                +
                                                +
                                                +

                                                6. Validation

                                                +

                                                summarize requires exactly one of content or location_uri. Passing +both, or passing neither, raises an error.

                                                +
                                                +

                                                6.1. SummaryParams

                                                class select_ai.summary.SummaryParams(min_words: int | None = None, max_words: int | None = None, summary_style: Style | None = None, chunk_processing_method: ChunkProcessingMethod | None = None, extractiveness_level: ExtractivenessLevel | None = None)
                                                @@ -192,7 +291,7 @@

                                                Navigation

                                                -

                                                2. ChunkProcessingMethod

                                                +

                                                6.2. ChunkProcessingMethod

                                                class select_ai.summary.ChunkProcessingMethod(*values)
                                                @@ -205,7 +304,7 @@

                                                2. ChunkProcessingMethod -

                                                3. ExtractivenessLevel

                                                +

                                                6.3. ExtractivenessLevel

                                                class select_ai.summary.ExtractivenessLevel(*values)
                                                @@ -219,7 +318,7 @@

                                                3. ExtractivenessLevel -

                                                4. SummaryStyle

                                                +

                                                6.4. SummaryStyle

                                                class select_ai.summary.Style(*values)
                                                @@ -229,6 +328,7 @@

                                                4. SummaryStyle

                                                +
                                                @@ -241,34 +341,42 @@

                                                4. SummaryStyle

                                                Table of Contents

                                                Previous topic

                                                1. SyntheticDataAttributes

                                                + title="previous chapter">1. Generation modes

                                                Next topic

                                                Tool

                                                + title="next chapter">1. Tool

                                                This Page

                                                @@ -298,10 +406,10 @@

                                                Navigation

                                                index
                                              • - next |
                                              • - previous |
                                              • Python logo
                                              • Python »
                                              • @@ -311,10 +419,10 @@

                                                Navigation

                                              • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
                                              • - +
                                              • diff --git a/docs/user_guide/synthetic_data.html b/docs/user_guide/synthetic_data.html index 0e801f7..3336060 100644 --- a/docs/user_guide/synthetic_data.html +++ b/docs/user_guide/synthetic_data.html @@ -5,21 +5,21 @@ - 1. SyntheticDataAttributes — Select AI for Python 1.3.0 documentation + 1. Generation modes — Select AI for Python 1.4.0rc1 documentation - + - + - - + + @@ -63,22 +63,27 @@

                                                Table of Contents

                                                  -
                                                • 1. SyntheticDataAttributes
                                                    +
                                                  • 1. Generation modes
                                                  • +
                                                  • 2. Generation parameters
                                                  • +
                                                  • 3. Sync and async APIs
                                                      +
                                                    • 3.1. SyntheticDataAttributes
                                                    • -
                                                    • 2. SyntheticDataParams
                                                        +
                                                      • 3.2. SyntheticDataParams
                                                      • -
                                                      • 3. Single table synthetic data @@ -87,12 +92,12 @@

                                                        Table of Contents

                                                        Previous topic

                                                        1. VectorIndex Object Model

                                                        + title="previous chapter">1. Vector Index

                                                        Next topic

                                                        1. SummaryParams

                                                        + title="next chapter">1. Inline content

                                                        This Page

                                                        @@ -122,10 +127,10 @@

                                                        Navigation

                                                        index
                                                      • - next |
                                                      • - previous |
                                                      • Python logo
                                                      • Python »
                                                      • @@ -135,10 +140,10 @@

                                                        Navigation

                                                      • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
                                                      • - +
                                                      • @@ -168,8 +173,92 @@

                                                        Navigation

                                                        -
                                                        -

                                                        1. SyntheticDataAttributes

                                                        +

                                                        Synthetic data generation uses a Select AI profile to populate database tables +with generated rows. It is useful for demos, development, testing, and +prototyping when representative data is needed but production data should not +be copied.

                                                        +

                                                        Synthetic data is inserted into the target tables in the connected database +schema or in the schema identified by owner_name or object_list. Before +running generation, make sure the connected user has privileges on the target +tables and that the Select AI profile is configured with a provider and +credential.

                                                        +

                                                        Use synthetic data generation with care in shared schemas. The API writes rows +to the target tables; use dedicated test tables or schemas when experimenting.

                                                        +
                                                        +

                                                        1. Generation modes

                                                        +

                                                        Use object_name for a single target table:

                                                        +
                                                        attributes = select_ai.SyntheticDataAttributes(
                                                        +    object_name="MOVIE",
                                                        +    record_count=100,
                                                        +    user_prompt="the release date for the movies should be in 2019",
                                                        +)
                                                        +
                                                        +
                                                        +

                                                        Use object_list for multiple target tables in one request:

                                                        +
                                                        attributes = select_ai.SyntheticDataAttributes(
                                                        +    object_list=[
                                                        +        {
                                                        +            "owner": "SH",
                                                        +            "name": "MOVIE",
                                                        +            "record_count": 100,
                                                        +            "user_prompt": (
                                                        +                "the release date for the movies should be in 2019"
                                                        +            ),
                                                        +        },
                                                        +        {"owner": "SH", "name": "ACTOR", "record_count": 10},
                                                        +        {"owner": "SH", "name": "DIRECTOR", "record_count": 5},
                                                        +    ]
                                                        +)
                                                        +
                                                        +
                                                        +

                                                        Exactly one of object_name or object_list must be set.

                                                        +
                                                        +
                                                        +

                                                        2. Generation parameters

                                                        +

                                                        Use SyntheticDataParams to control how generation is performed:

                                                        +
                                                        params = select_ai.SyntheticDataParams(
                                                        +    sample_rows=100,
                                                        +    table_statistics=True,
                                                        +    priority="HIGH",
                                                        +    comments=True,
                                                        +)
                                                        +
                                                        +attributes = select_ai.SyntheticDataAttributes(
                                                        +    object_name="MOVIE",
                                                        +    record_count=100,
                                                        +    user_prompt="Generate movie data for releases in 2019.",
                                                        +    params=params,
                                                        +)
                                                        +
                                                        +
                                                        +

                                                        sample_rows controls how many existing rows are used as examples for the +model. table_statistics and comments include additional table metadata. +priority controls resource priority for generation work; supported values +are HIGH, MEDIUM, and LOW.

                                                        +
                                                        +
                                                        +

                                                        3. Sync and async APIs

                                                        +

                                                        Use Profile.generate_synthetic_data(...) for synchronous applications and +await AsyncProfile.generate_synthetic_data(...) for asynchronous +applications:

                                                        +
                                                        profile = select_ai.Profile(profile_name="oci_ai_profile")
                                                        +profile.generate_synthetic_data(
                                                        +    synthetic_data_attributes=attributes,
                                                        +)
                                                        +
                                                        +
                                                        +
                                                        async_profile = await select_ai.AsyncProfile(
                                                        +    profile_name="async_oci_ai_profile",
                                                        +)
                                                        +await async_profile.generate_synthetic_data(
                                                        +    synthetic_data_attributes=attributes,
                                                        +)
                                                        +
                                                        +
                                                        +

                                                        For additional database-side attribute details, see the +generate_synthetic_data PL/SQL API.

                                                        +
                                                        +

                                                        3.1. SyntheticDataAttributes

                                                        class select_ai.SyntheticDataAttributes(object_name: str | None = None, object_list: List[Mapping] | None = None, owner_name: str | None = None, params: SyntheticDataParams | None = None, record_count: int | None = None, user_prompt: str | None = None)
                                                        @@ -192,7 +281,7 @@

                                                        Navigation

                                                        -

                                                        2. SyntheticDataParams

                                                        +

                                                        3.2. SyntheticDataParams

                                                        class select_ai.SyntheticDataParams(sample_rows: int | None = None, table_statistics: bool | None = False, priority: str | None = 'HIGH', comments: bool | None = False)
                                                        @@ -215,14 +304,12 @@

                                                        2. generate_synthetic_data PL/SQL API -for attribute details

                                                        -

                                                        3. Single table synthetic data

                                                        +

                                                        3.3. Single table synthetic data

                                                        The below example shows single table synthetic data generation

                                                        -

                                                        3.1. Single Table Sync API

                                                        +

                                                        3.3.1. Single Table Sync API

                                                        import os
                                                         
                                                         import select_ai
                                                        @@ -256,8 +343,8 @@ 

                                                        3.1. Single Table Sync API -

                                                        3.2. Singe Table Async API

                                                        +
                                                        +

                                                        3.3.2. Single Table Async API

                                                        import asyncio
                                                         import os
                                                         
                                                        @@ -301,10 +388,10 @@ 

                                                        3.2. Singe Table Async API -

                                                        4. Multi table synthetic data

                                                        -

                                                        The below example shows multitable synthetic data generation

                                                        +

                                                        3.4. Multi table synthetic data

                                                        +

                                                        The below example shows multi-table synthetic data generation

                                                        -

                                                        4.1. Multi table Sync API

                                                        +

                                                        3.4.1. Multi table Sync API

                                                        import os
                                                         
                                                         import select_ai
                                                        @@ -358,7 +445,7 @@ 

                                                        4.1. Multi table Sync API -

                                                        4.2. Multi table Async API

                                                        +

                                                        3.4.2. Multi table Async API

                                                        import asyncio
                                                         import os
                                                         
                                                        @@ -419,6 +506,7 @@ 

                                                        4.2. Multi table Async API4.2. Multi table Async APITable of Contents

                                                      • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
                                                      • - +
                                                      • @@ -206,21 +207,120 @@

                                                        Navigation

                                                        -

                                                        VectorIndex supports Retrieval Augmented Generation (RAG). -For e.g., you can convert text into vector embeddings and store them in a -vector store. Select AI will augment the natural language prompt by retrieving -content from the vector store using semantic similarity search.

                                                        +
                                                        +

                                                        1. Vector Index

                                                        +

                                                        VectorIndex supports Retrieval Augmented Generation (RAG). It converts +source documents into vector embeddings, stores the embeddings in a vector +store, and links the vector index to a Select AI profile. When that profile is +used for natural language generation, Select AI can retrieve semantically +similar content from the vector index and use that content as grounding context +for the response.

                                                        +

                                                        A vector index is useful when the answer should come from files or documents +that are not represented as relational tables. Typical sources include +documents in Object Storage, product manuals, generated reports, logs, JSON +files, and other text-heavy content that should be searched by meaning rather +than exact keywords.

                                                        +

                                                        Before creating a vector index, make sure the database user has:

                                                        +
                                                          +
                                                        • A Select AI profile with an AI provider that supports embeddings.

                                                        • +
                                                        • A credential for the AI provider used by the profile.

                                                        • +
                                                        • A credential for the object storage location if the source objects are not +public.

                                                        • +
                                                        • Network access to the AI provider endpoint and the source location. See +Privileges for network ACL helpers.

                                                        • +
                                                        +

                                                        The usual lifecycle is:

                                                        +
                                                          +
                                                        1. Create a profile with a provider and embedding model.

                                                        2. +
                                                        3. Create OracleVectorIndexAttributes with the source location and storage +credential.

                                                        4. +
                                                        5. Create VectorIndex and call create().

                                                        6. +
                                                        7. Use the linked profile for RAG actions such as narrate().

                                                        8. +
                                                        9. Fetch, list, update, disable, enable, or delete the index as needed.

                                                        10. +
                                                        +
                                                        -

                                                        1. VectorIndex Object Model

                                                        +

                                                        2. VectorIndex Object Model

                                                        Select AI Vector Index
                                                        -

                                                        2. VectorIndexAttributes

                                                        +

                                                        3. VectorIndexAttributes

                                                        A VectorIndexAttributes object can be created with select_ai.VectorIndexAttributes(). Also check vector index attributes

                                                        +

                                                        For Oracle vector indexes, use OracleVectorIndexAttributes. It sets +vector_db_provider to VectorDBProvider.ORACLE and is the preferred +attribute class for the examples in this guide.

                                                        +

                                                        Common attributes:

                                                        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

                                                        Attribute

                                                        Use

                                                        location

                                                        Object Storage URI or source location containing the documents to +embed.

                                                        object_storage_credential_name

                                                        Credential used to read the source location.

                                                        profile_name

                                                        Select AI profile used to create embeddings and answer RAG prompts. +If omitted during create(), it is taken from the profile object +passed to VectorIndex.

                                                        chunk_size and chunk_overlap

                                                        Control how source text is split before embedding. Larger chunks keep +more context together; overlap helps preserve context across chunk +boundaries.

                                                        match_limit

                                                        Maximum number of matching chunks returned during semantic search.

                                                        similarity_threshold

                                                        Minimum similarity score required for retrieved chunks to be considered +relevant.

                                                        vector_distance_metric

                                                        Distance metric used to compare embeddings. Supported values include +COSINE, EUCLIDEAN, L2_SQUARED, DOT, MANHATTAN, and +HAMMING.

                                                        refresh_rate

                                                        Refresh interval, in minutes, for loading new or changed source data.

                                                        vector_table_name

                                                        Name of the table used to store vector embeddings and chunked data. +Leave unset unless you need to control the storage table name.

                                                        enable_sources

                                                        Include filenames and source links in RAG output when supported by the +profile and model response.

                                                        +

                                                        Example attributes:

                                                        +
                                                        attributes = select_ai.OracleVectorIndexAttributes(
                                                        +    location="https://objectstorage.us-ashburn-1.oraclecloud.com/n/example/b/docs/o/product-guides",
                                                        +    object_storage_credential_name="object_store_credential",
                                                        +    chunk_size=1024,
                                                        +    chunk_overlap=128,
                                                        +    match_limit=5,
                                                        +    similarity_threshold=0.5,
                                                        +    vector_distance_metric=select_ai.VectorDistanceMetric.COSINE,
                                                        +    refresh_rate=1440,
                                                        +)
                                                        +
                                                        +
                                                        +

                                                        The embedding model is configured on the provider inside the linked +ProfileAttributes. Keep the profile provider and vector index attributes +together conceptually: the profile decides how embeddings are generated, while +the vector index attributes decide where content is read from, how it is +chunked, and how the vector store is searched.

                                                        class select_ai.VectorIndexAttributes(chunk_size: int | None = None, chunk_overlap: int | None = None, enable_sources: bool | None = None, location: str | None = None, match_limit: int | None = None, object_storage_credential_name: str | None = None, profile_name: str | None = None, refresh_rate: int | None = None, similarity_threshold: float | None = None, vector_distance_metric: VectorDistanceMetric | None = None, vector_db_endpoint: str | None = None, vector_db_credential_name: str | None = None, vector_db_provider: VectorDBProvider | None = None, vector_dimension: int | None = None, vector_table_name: str | None = None, pipeline_name: str | None = None)
                                                        @@ -262,7 +362,7 @@

                                                        2. -

                                                        2.1. OracleVectorIndexAttributes

                                                        +

                                                        3.1. OracleVectorIndexAttributes

                                                        class select_ai.OracleVectorIndexAttributes(chunk_size: int | None = None, chunk_overlap: int | None = None, enable_sources: bool | None = None, location: str | None = None, match_limit: int | None = None, object_storage_credential_name: str | None = None, profile_name: str | None = None, refresh_rate: int | None = None, similarity_threshold: float | None = None, vector_distance_metric: VectorDistanceMetric | None = None, vector_db_endpoint: str | None = None, vector_db_credential_name: str | None = None, vector_db_provider: VectorDBProvider | None = VectorDBProvider.ORACLE, vector_dimension: int | None = None, vector_table_name: str | None = None, pipeline_name: str | None = None)
                                                        @@ -272,7 +372,7 @@

                                                        2.1. -

                                                        3. VectorIndex API

                                                        +

                                                        4. VectorIndex API

                                                        A VectorIndex object can be created with select_ai.VectorIndex()

                                                        @@ -489,11 +589,55 @@

                                                        3. select_ai.connect(). Use AsyncVectorIndex in applications already using +asyncio and select_ai.async_connect() or an async connection pool.

                                                        +

                                                        Important lifecycle methods:

                                                        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

                                                        Method

                                                        Use

                                                        create(replace=False, wait_for_completion=False)

                                                        Create the database vector index and start the load pipeline. If +replace=True and the index already exists, the existing index is +dropped and recreated. Use wait_for_completion=True when the next +step depends on the initial load being complete.

                                                        fetch(index_name)

                                                        Build a VectorIndex proxy from database metadata, including +attributes and the linked profile when it still exists.

                                                        list(index_name_pattern=".*")

                                                        Iterate over vector indexes visible to the current user. The pattern is +evaluated with Oracle REGEXP_LIKE.

                                                        set_attribute() and set_attributes()

                                                        Update one or more index attributes.

                                                        get_next_refresh_timestamp()

                                                        Return the next scheduled refresh timestamp in UTC when the index has a +refresh rate and a recorded pipeline execution.

                                                        disable() and enable()

                                                        Pause or resume use of the vector index for loading, indexing, +searching, and querying.

                                                        delete(include_data=True, force=False)

                                                        Drop the vector index. include_data=True also removes associated +vector store data. force=True ignores missing-index errors.

                                                        +

                                                        Check the examples below to understand how to create vector indexes.

                                                        -

                                                        3.1. Create vector index

                                                        +

                                                        4.1. Create vector index

                                                        In the following example, vector database provider is Oracle and -objects (to create embedding for) reside in OCI’s object store

                                                        +objects used to create embeddings reside in OCI Object Storage. The profile +uses an OCI Generative AI provider with an embedding model, and the vector +index is linked to that profile during create().

                                                        import os
                                                         
                                                         import select_ai
                                                        @@ -549,7 +693,7 @@ 

                                                        3.1. Create vector index -

                                                        3.2. List vector index

                                                        +

                                                        4.2. List vector index

                                                        import os
                                                         
                                                         import select_ai
                                                        @@ -572,9 +716,11 @@ 

                                                        3.2. List vector index -

                                                        3.3. Fetch vector index

                                                        +

                                                        4.3. Fetch vector index

                                                        You can fetch the vector index attributes and associated AI profile using -the class method VectorIndex.fetch(index_name)

                                                        +the class method VectorIndex.fetch(index_name). Fetch is useful when the +index was created earlier or by another process and you want to inspect or +update it without recreating the original Python object.

                                                        import os
                                                         
                                                         import select_ai
                                                        @@ -599,9 +745,10 @@ 

                                                        3.3. Fetch vector index -

                                                        3.4. Update vector index attributes

                                                        +

                                                        4.4. Update vector index attributes

                                                        To update attributes, use either vector_index.set_attribute() or -vector_index.set_attributes()

                                                        +vector_index.set_attributes(). Use set_attribute() for a single value +and set_attributes() when updating several values together.

                                                        import os
                                                         
                                                         import select_ai
                                                        @@ -631,7 +778,11 @@ 

                                                        3.4. Update vector index attributes

                                                        -

                                                        3.5. RAG using vector index

                                                        +

                                                        4.5. RAG using vector index

                                                        +

                                                        After create() succeeds, the profile has its vector_index_name set to +the new index. Use that profile with text-returning actions such as +narrate() to retrieve relevant chunks from the vector index and ground the +answer in the indexed content.

                                                        import os
                                                         
                                                         import select_ai
                                                        @@ -664,7 +815,11 @@ 

                                                        3.5. RAG using vector index -

                                                        3.6. Delete vector index

                                                        +

                                                        4.6. Delete vector index

                                                        +

                                                        Use delete() when the index is no longer needed. By default, +include_data=True removes the vector index metadata and the associated +vector store data. Set include_data=False only when you intentionally want +to keep the underlying vector store data.

                                                        import os
                                                         
                                                         import select_ai
                                                        @@ -686,8 +841,9 @@ 

                                                        3.6. Delete vector index -

                                                        4. AsyncVectorIndex API

                                                        -

                                                        A AsyncVectorIndex object can be created with select_ai.AsyncVectorIndex()

                                                        +

                                                        5. AsyncVectorIndex API

                                                        +

                                                        An AsyncVectorIndex object can be created with +select_ai.AsyncVectorIndex()

                                                        class select_ai.AsyncVectorIndex(profile: BaseProfile | None = None, index_name: str | None = None, description: str | None = None, attributes: VectorIndexAttributes | None = None)
                                                        @@ -900,8 +1056,38 @@

                                                        4. AsyncVectorIndex.list() is an async iterator.

                                                        + + + + + + + + + + + + + + + + + + + + + + + + + + +

                                                        Synchronous API

                                                        Async API

                                                        select_ai.connect(...)

                                                        await select_ai.async_connect(...)

                                                        Profile(...)

                                                        await AsyncProfile(...)

                                                        VectorIndex.create(...)

                                                        await AsyncVectorIndex.create(...)

                                                        VectorIndex.fetch(...)

                                                        await AsyncVectorIndex.fetch(...)

                                                        for index in VectorIndex.list(...)

                                                        async for index in AsyncVectorIndex.list(...)

                                                        profile.narrate(...)

                                                        await async_profile.narrate(...)

                                                        -

                                                        4.1. Async create vector index

                                                        +

                                                        5.1. Async create vector index

                                                        import asyncio
                                                         import os
                                                         
                                                        @@ -955,7 +1141,7 @@ 

                                                        4.1. Async create vector index -

                                                        4.2. Async list vector index

                                                        +

                                                        5.2. Async list vector index

                                                        import asyncio
                                                         import os
                                                         
                                                        @@ -984,7 +1170,7 @@ 

                                                        4.2. Async list vector index -

                                                        4.3. Async fetch vector index

                                                        +

                                                        5.3. Async fetch vector index

                                                        You can fetch the vector index attributes and associated AI profile using the class method AsyncVectorIndex.fetch(index_name)

                                                        import asyncio
                                                        @@ -1018,7 +1204,7 @@ 

                                                        4.3. Async fetch vector index -

                                                        4.4. Async update vector index attributes

                                                        +

                                                        5.4. Async update vector index attributes

                                                        To update attributes, use either async_vector_index.set_attribute() or async_vector_index.set_attributes()

                                                        import asyncio
                                                        @@ -1059,7 +1245,7 @@ 

                                                        4.4. Async update vector index attribute

                                                        -

                                                        4.5. Async RAG using vector index

                                                        +

                                                        5.5. Async RAG using vector index

                                                        import os
                                                         
                                                         import select_ai
                                                        @@ -1112,16 +1298,17 @@ 

                                                        4.5. Async RAG using vector index

                                                        Table of Contents

                                                      • - Select AI for Python 1.3.0 documentation » + Select AI for Python 1.4.0rc1 documentation »
                                                      • - +
                                                      • diff --git a/docs/user_guide/web_frameworks.html b/docs/user_guide/web_frameworks.html new file mode 100644 index 0000000..4d9f286 --- /dev/null +++ b/docs/user_guide/web_frameworks.html @@ -0,0 +1,617 @@ + + + + + + + + 1. Using select_ai with Python web frameworks — Select AI for Python 1.4.0rc1 documentation + + + + + + + + + + + + + + + + + + + + + +
                                                        + + + +
                                                        + + + +
                                                        +
                                                        +
                                                        +
                                                        + +
                                                        +

                                                        1. Using select_ai with Python web frameworks

                                                        +

                                                        Python web applications should create a Select AI connection pool when the +application starts and close it when the application shuts down. A pool lets +concurrent requests share a bounded set of database connections instead of +creating standalone connections per request.

                                                        +

                                                        This pattern works with Python Web Server Gateway Interface (WSGI) and +Asynchronous Server Gateway Interface (ASGI) frameworks. FastAPI is used below +as a concrete example, but the same approach applies to frameworks such as +Flask, Django, Starlette, Sanic, and Quart: initialize the pool during +application startup, use select_ai APIs inside request handlers, and close +the pool during application shutdown.

                                                        +

                                                        Do not call select_ai.connect() or select_ai.create_pool() inside every +request handler. Creating connections per request adds latency, increases +database connection churn, and can exhaust the database connection limit under +load. Create one pool per worker process and let select_ai acquire and +release connections from that pool for each API call.

                                                        +

                                                        For background and concurrency measurements, see this +connection pooling blog.

                                                        +
                                                        +

                                                        1.1. Framework patterns

                                                        +

                                                        Use the framework lifecycle API that runs once per process:

                                                        +
                                                          +
                                                        • FastAPI / +Starlette: use a lifespan async +context manager. Create the pool before yield and close it after +yield.

                                                        • +
                                                        • Flask: +create the pool in create_app(). Close the pool from the shutdown hook +provided by the process that runs Flask, such as a Gunicorn worker_exit +hook. For simple local applications, atexit.register() can be used for +normal interpreter shutdown.

                                                        • +
                                                        • Django: +create the pool in AppConfig.ready(). Close the pool from the shutdown +hook provided by the process that runs Django, such as a Gunicorn +worker_exit hook. For simple local applications, atexit.register() +can be used for normal interpreter shutdown.

                                                        • +
                                                        • Quart: +use @app.before_serving / @app.after_serving, or +@app.while_serving with cleanup after yield.

                                                        • +
                                                        • Sanic: use +@app.before_server_start and @app.after_server_stop.

                                                        • +
                                                        +

                                                        Use select_ai.create_pool() for synchronous request handlers and +select_ai.create_pool_async() for asynchronous request handlers. In +general, synchronous routes should call synchronous Select AI methods, and async +routes should call async Select AI methods. Avoid mixing blocking synchronous +database calls into async routes unless the framework runs them in a worker +thread.

                                                        +

                                                        For Flask and Django, be careful with hooks that run per request or per +application context. A Select AI pool should live for the worker process, not +for a single request. For example, Flask’s teardown_appcontext runs when an +application context is popped, so it is not a good place to close a process-wide +pool after every request.

                                                        +
                                                        +
                                                        +

                                                        1.2. Install dependencies

                                                        +

                                                        Install select_ai and FastAPI server dependencies:

                                                        +
                                                        python -m pip install select_ai fastapi uvicorn
                                                        +
                                                        +
                                                        +

                                                        For local development, set the database connection details as environment +variables:

                                                        +
                                                        export SELECT_AI_USER=<select_ai_db_user>
                                                        +export SELECT_AI_PASSWORD=<select_ai_db_password>
                                                        +export SELECT_AI_DB_CONNECT_STRING=<db_connect_string>
                                                        +export SELECT_AI_POOL_MIN=5
                                                        +export SELECT_AI_POOL_MAX=10
                                                        +export SELECT_AI_POOL_INCREMENT=5
                                                        +
                                                        +
                                                        +

                                                        If you use an mTLS wallet, also set TNS_ADMIN or pass wallet parameters to +select_ai.create_pool() / select_ai.create_pool_async().

                                                        +

                                                        For production deployments, store these values in your deployment platform’s +secret manager or environment configuration. Do not hard-code database +passwords, wallet passwords, or provider credentials in application source.

                                                        +
                                                        +
                                                        +

                                                        1.3. FastAPI synchronous endpoints

                                                        +

                                                        Create a file named app.py:

                                                        +
                                                        import os
                                                        +from contextlib import asynccontextmanager
                                                        +
                                                        +from fastapi import FastAPI
                                                        +
                                                        +import select_ai
                                                        +
                                                        +user = os.getenv("SELECT_AI_USER")
                                                        +password = os.getenv("SELECT_AI_PASSWORD")
                                                        +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING")
                                                        +
                                                        +pool_min = int(os.getenv("SELECT_AI_POOL_MIN", "5"))
                                                        +pool_max = int(os.getenv("SELECT_AI_POOL_MAX", "10"))
                                                        +pool_increment = int(os.getenv("SELECT_AI_POOL_INCREMENT", "5"))
                                                        +
                                                        +
                                                        +@asynccontextmanager
                                                        +async def lifespan(app: FastAPI):
                                                        +    select_ai.create_pool(
                                                        +        user=user,
                                                        +        password=password,
                                                        +        dsn=dsn,
                                                        +        min_size=pool_min,
                                                        +        max_size=pool_max,
                                                        +        increment=pool_increment,
                                                        +    )
                                                        +    yield
                                                        +    select_ai.disconnect()
                                                        +
                                                        +
                                                        +app = FastAPI(lifespan=lifespan)
                                                        +
                                                        +
                                                        +@app.get("/chat")
                                                        +def chat(prompt: str):
                                                        +    profile = select_ai.Profile(profile_name="oci_ai_profile")
                                                        +    return {"response": profile.chat(prompt=prompt)}
                                                        +
                                                        +
                                                        +@app.get("/show_sql")
                                                        +def show_sql(prompt: str):
                                                        +    profile = select_ai.Profile(profile_name="oci_ai_profile")
                                                        +    return {"sql": profile.show_sql(prompt=prompt)}
                                                        +
                                                        +
                                                        +

                                                        Start the server:

                                                        +
                                                        uvicorn app:app --host 0.0.0.0 --port 8000
                                                        +
                                                        +
                                                        +

                                                        Call the service:

                                                        +
                                                        curl "http://localhost:8000/chat?prompt=What%20is%20OCI%3F"
                                                        +
                                                        +
                                                        +

                                                        Stop the server by pressing Ctrl+C in the terminal where uvicorn is +running. FastAPI runs the lifespan shutdown hook and select_ai.disconnect() +closes the pool.

                                                        +

                                                        This example creates the Profile proxy inside each handler. The proxy is +lightweight; the database connection is acquired from the pool only when the +profile method calls the database.

                                                        +
                                                        +
                                                        +

                                                        1.4. FastAPI asynchronous endpoints

                                                        +

                                                        For async endpoints, initialize the async pool with +select_ai.create_pool_async() and close it with +select_ai.async_disconnect().

                                                        +
                                                        import os
                                                        +from contextlib import asynccontextmanager
                                                        +
                                                        +from fastapi import FastAPI
                                                        +
                                                        +import select_ai
                                                        +
                                                        +user = os.getenv("SELECT_AI_USER")
                                                        +password = os.getenv("SELECT_AI_PASSWORD")
                                                        +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING")
                                                        +
                                                        +
                                                        +@asynccontextmanager
                                                        +async def lifespan(app: FastAPI):
                                                        +    select_ai.create_pool_async(
                                                        +        user=user,
                                                        +        password=password,
                                                        +        dsn=dsn,
                                                        +        min_size=5,
                                                        +        max_size=10,
                                                        +        increment=5,
                                                        +    )
                                                        +    yield
                                                        +    await select_ai.async_disconnect()
                                                        +
                                                        +
                                                        +app = FastAPI(lifespan=lifespan)
                                                        +
                                                        +
                                                        +@app.get("/chat")
                                                        +async def chat(prompt: str):
                                                        +    profile = await select_ai.AsyncProfile(
                                                        +        profile_name="async_oci_ai_profile"
                                                        +    )
                                                        +    return {"response": await profile.chat(prompt=prompt)}
                                                        +
                                                        +
                                                        +

                                                        Start and stop the server the same way:

                                                        +
                                                        uvicorn app:app --host 0.0.0.0 --port 8000
                                                        +
                                                        +
                                                        +

                                                        Press Ctrl+C to stop it.

                                                        +
                                                        +
                                                        +

                                                        1.5. Flask example

                                                        +

                                                        Flask applications normally use synchronous request handlers, so initialize a +synchronous Select AI pool when the application is created.

                                                        +
                                                        import atexit
                                                        +import os
                                                        +
                                                        +from flask import Flask, jsonify, request
                                                        +
                                                        +import select_ai
                                                        +
                                                        +
                                                        +def create_app():
                                                        +    app = Flask(__name__)
                                                        +
                                                        +    select_ai.create_pool(
                                                        +        user=os.getenv("SELECT_AI_USER"),
                                                        +        password=os.getenv("SELECT_AI_PASSWORD"),
                                                        +        dsn=os.getenv("SELECT_AI_DB_CONNECT_STRING"),
                                                        +        min_size=int(os.getenv("SELECT_AI_POOL_MIN", "1")),
                                                        +        max_size=int(os.getenv("SELECT_AI_POOL_MAX", "4")),
                                                        +        increment=int(os.getenv("SELECT_AI_POOL_INCREMENT", "1")),
                                                        +    )
                                                        +
                                                        +    @app.get("/show_sql")
                                                        +    def show_sql():
                                                        +        prompt = request.args["prompt"]
                                                        +        profile = select_ai.Profile(profile_name="oci_ai_profile")
                                                        +        return jsonify({"sql": profile.show_sql(prompt=prompt)})
                                                        +
                                                        +    @atexit.register
                                                        +    def close_select_ai_pool():
                                                        +        if select_ai.is_connected():
                                                        +            select_ai.disconnect()
                                                        +
                                                        +    return app
                                                        +
                                                        +
                                                        +
                                                        +
                                                        +

                                                        1.6. Django example

                                                        +

                                                        Django has its own database connection management, but select_ai uses the +Oracle Database connection pool created by this package. Create the Select AI +pool once per process, then call Profile APIs inside views.

                                                        +
                                                        # myapp/apps.py
                                                        +import os
                                                        +
                                                        +from django.apps import AppConfig
                                                        +
                                                        +import select_ai
                                                        +
                                                        +
                                                        +class MyAppConfig(AppConfig):
                                                        +    name = "myapp"
                                                        +
                                                        +    def ready(self):
                                                        +        if not select_ai.is_connected():
                                                        +            select_ai.create_pool(
                                                        +                user=os.getenv("SELECT_AI_USER"),
                                                        +                password=os.getenv("SELECT_AI_PASSWORD"),
                                                        +                dsn=os.getenv("SELECT_AI_DB_CONNECT_STRING"),
                                                        +                min_size=int(os.getenv("SELECT_AI_POOL_MIN", "1")),
                                                        +                max_size=int(os.getenv("SELECT_AI_POOL_MAX", "4")),
                                                        +                increment=int(os.getenv("SELECT_AI_POOL_INCREMENT", "1")),
                                                        +            )
                                                        +
                                                        +
                                                        +
                                                        # myapp/views.py
                                                        +from django.http import JsonResponse
                                                        +
                                                        +import select_ai
                                                        +
                                                        +
                                                        +def show_sql(request):
                                                        +    profile = select_ai.Profile(profile_name="oci_ai_profile")
                                                        +    sql = profile.show_sql(prompt=request.GET["prompt"])
                                                        +    return JsonResponse({"sql": sql})
                                                        +
                                                        +
                                                        +

                                                        When using Django’s development autoreloader, startup hooks may run more than +once. The is_connected() check prevents this example from creating a second +pool in the same process.

                                                        +
                                                        +
                                                        +

                                                        1.7. Pool sizing

                                                        +

                                                        Use connection pooling for concurrent services such as API applications, +workloads with mixed fast and slow requests, and applications with tail-latency +requirements. Use standalone connections for simple scripts, command-line +tools, or low-concurrency batch jobs.

                                                        +

                                                        Set pool sizing based on expected request concurrency and database capacity. +In multi-worker deployments, each worker process creates its own pool, so total +possible database connections are approximately:

                                                        +
                                                        workers * SELECT_AI_POOL_MAX
                                                        +
                                                        +
                                                        +

                                                        Choose pool sizes that leave capacity for other database clients and avoid +overwhelming small database deployments.

                                                        +

                                                        For example, a service running four worker processes with +SELECT_AI_POOL_MAX=10 can open up to forty Select AI database connections. +If the database can only spare twenty connections for the application, use fewer +workers, reduce SELECT_AI_POOL_MAX, or both.

                                                        +
                                                        +
                                                        +

                                                        1.8. Pool wait behavior

                                                        +

                                                        select_ai.create_pool() and select_ai.create_pool_async() pass pool +options through to python-oracledb. Use wait_timeout and getmode to +control what happens when all pooled connections are busy.

                                                        +
                                                        select_ai.create_pool(
                                                        +    user=user,
                                                        +    password=password,
                                                        +    dsn=dsn,
                                                        +    min_size=2,
                                                        +    max_size=8,
                                                        +    increment=2,
                                                        +    wait_timeout=10,
                                                        +)
                                                        +
                                                        +
                                                        +

                                                        Choose a timeout that matches your API latency budget. For public HTTP APIs, +it is usually better to fail fast and return an application error than to let +requests pile up until every worker is blocked.

                                                        +
                                                        +
                                                        +

                                                        1.9. Request handling

                                                        +

                                                        Validate prompts and profile names before calling Select AI methods. If clients +can choose a profile, check the requested profile against an application +allowlist instead of passing arbitrary user input directly into +Profile(profile_name=...).

                                                        +

                                                        For long-running prompts, set HTTP server timeouts and client timeouts +deliberately. Text generation and RAG calls can take longer than simple SQL +metadata operations, especially when external AI providers or object storage +are involved.

                                                        +

                                                        For streaming responses, prefer async frameworks and async Select AI methods when +the rest of the application is already async. For ordinary JSON responses, +either synchronous or asynchronous routes are fine as long as the connection +pool matches the route style.

                                                        +
                                                        +
                                                        + + +
                                                        +
                                                        +
                                                        +
                                                        + +
                                                        +
                                                        + + + + + diff --git a/recipes/concurrent_prompt_processing/async_as_completed.py b/recipes/concurrent_prompt_processing/async_as_completed.py new file mode 100644 index 0000000..3665a38 --- /dev/null +++ b/recipes/concurrent_prompt_processing/async_as_completed.py @@ -0,0 +1,64 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2026, Oracle and/or its affiliates. +# +# Licensed under the Universal Permissive License v 1.0 as shown at +# http://oss.oracle.com/licenses/upl. +# ----------------------------------------------------------------------------- + +# ----------------------------------------------------------------------------- +# concurrent_prompt_processing/async_as_completed.py +# +# Process async prompt results as each task completes. +# ----------------------------------------------------------------------------- + +import asyncio +import os + +import select_ai + +user = os.getenv("SELECT_AI_USER") +password = os.getenv("SELECT_AI_PASSWORD") +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING") + +pool_min = int(os.getenv("SELECT_AI_POOL_MIN", "1")) +pool_max = int(os.getenv("SELECT_AI_POOL_MAX", "4")) +pool_increment = int(os.getenv("SELECT_AI_POOL_INCREMENT", "1")) + +profile_name = os.getenv("SELECT_AI_PROFILE_NAME", "async_oci_ai_profile") + +prompts = [ + "How many customers?", + "How many products?", + "How many promotions?", + "List the top 5 customers by sales.", +] + + +async def show_sql(profile, prompt): + sql = await profile.show_sql(prompt=prompt) + return prompt, sql + + +async def main(): + select_ai.create_pool_async( + user=user, + password=password, + dsn=dsn, + min_size=pool_min, + max_size=pool_max, + increment=pool_increment, + ) + + try: + profile = await select_ai.AsyncProfile(profile_name=profile_name) + tasks = [show_sql(profile, prompt) for prompt in prompts] + + for task in asyncio.as_completed(tasks): + prompt, sql = await task + print(f"\nPrompt: {prompt}") + print(sql) + finally: + await select_ai.async_disconnect() + + +asyncio.run(main()) diff --git a/recipes/concurrent_prompt_processing/async_gather.py b/recipes/concurrent_prompt_processing/async_gather.py new file mode 100644 index 0000000..3432d6b --- /dev/null +++ b/recipes/concurrent_prompt_processing/async_gather.py @@ -0,0 +1,64 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2026, Oracle and/or its affiliates. +# +# Licensed under the Universal Permissive License v 1.0 as shown at +# http://oss.oracle.com/licenses/upl. +# ----------------------------------------------------------------------------- + +# ----------------------------------------------------------------------------- +# concurrent_prompt_processing/async_bounded_gather.py +# +# Process independent prompts concurrently with the asynchronous Profile API. +# ----------------------------------------------------------------------------- + +import asyncio +import os + +import select_ai + +user = os.getenv("SELECT_AI_USER") +password = os.getenv("SELECT_AI_PASSWORD") +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING") + +pool_min = int(os.getenv("SELECT_AI_POOL_MIN", "1")) +pool_max = int(os.getenv("SELECT_AI_POOL_MAX", "4")) +pool_increment = int(os.getenv("SELECT_AI_POOL_INCREMENT", "1")) + +profile_name = os.getenv("SELECT_AI_PROFILE_NAME", "async_oci_ai_profile") + +prompts = [ + "How many customers?", + "How many products?", + "How many promotions?", + "List the top 5 customers by sales.", +] + + +async def show_sql(profile, prompt): + return await profile.show_sql(prompt=prompt) + + +async def main(): + select_ai.create_pool_async( + user=user, + password=password, + dsn=dsn, + min_size=pool_min, + max_size=pool_max, + increment=pool_increment, + ) + + try: + profile = await select_ai.AsyncProfile(profile_name=profile_name) + + tasks = [show_sql(profile, prompt) for prompt in prompts] + results = await asyncio.gather(*tasks) + + for prompt, sql in zip(prompts, results): + print(f"\nPrompt: {prompt}") + print(sql) + finally: + await select_ai.async_disconnect() + + +asyncio.run(main()) diff --git a/recipes/concurrent_prompt_processing/async_pipeline.py b/recipes/concurrent_prompt_processing/async_pipeline.py new file mode 100644 index 0000000..87e09af --- /dev/null +++ b/recipes/concurrent_prompt_processing/async_pipeline.py @@ -0,0 +1,60 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2026, Oracle and/or its affiliates. +# +# Licensed under the Universal Permissive License v 1.0 as shown at +# http://oss.oracle.com/licenses/upl. +# ----------------------------------------------------------------------------- + +# ----------------------------------------------------------------------------- +# concurrent_prompt_processing/async_pipeline.py +# +# Send multiple prompts in one database round trip using run_pipeline(). +# ----------------------------------------------------------------------------- + +import asyncio +import os + +import select_ai + +user = os.getenv("SELECT_AI_USER") +password = os.getenv("SELECT_AI_PASSWORD") +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING") + +pool_min = int(os.getenv("SELECT_AI_POOL_MIN", "1")) +pool_max = int(os.getenv("SELECT_AI_POOL_MAX", "4")) +pool_increment = int(os.getenv("SELECT_AI_POOL_INCREMENT", "1")) + +profile_name = os.getenv("SELECT_AI_PROFILE_NAME", "async_oci_ai_profile") + +prompt_specifications = [ + ("How many customers?", select_ai.Action.SHOWSQL), + ("How many promotions?", select_ai.Action.RUNSQL), + ("Explain how to count products.", select_ai.Action.EXPLAINSQL), +] + + +async def main(): + select_ai.create_pool_async( + user=user, + password=password, + dsn=dsn, + min_size=pool_min, + max_size=pool_max, + increment=pool_increment, + ) + + try: + profile = await select_ai.AsyncProfile(profile_name=profile_name) + results = await profile.run_pipeline( + prompt_specifications, continue_on_error=True + ) + + for (prompt, action), result in zip(prompt_specifications, results): + print(f"\nPrompt: {prompt}") + print(f"Action: {action}") + print(result) + finally: + await select_ai.async_disconnect() + + +asyncio.run(main()) diff --git a/recipes/concurrent_prompt_processing/async_queue_workers.py b/recipes/concurrent_prompt_processing/async_queue_workers.py new file mode 100644 index 0000000..032af1e --- /dev/null +++ b/recipes/concurrent_prompt_processing/async_queue_workers.py @@ -0,0 +1,88 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2026, Oracle and/or its affiliates. +# +# Licensed under the Universal Permissive License v 1.0 as shown at +# http://oss.oracle.com/licenses/upl. +# ----------------------------------------------------------------------------- + +# ----------------------------------------------------------------------------- +# concurrent_prompt_processing/async_queue_workers.py +# +# Process prompts with async queue workers. +# ----------------------------------------------------------------------------- + +import asyncio +import os + +import select_ai + +user = os.getenv("SELECT_AI_USER") +password = os.getenv("SELECT_AI_PASSWORD") +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING") + +pool_min = int(os.getenv("SELECT_AI_POOL_MIN", "1")) +pool_max = int(os.getenv("SELECT_AI_POOL_MAX", "4")) +pool_increment = int(os.getenv("SELECT_AI_POOL_INCREMENT", "1")) + +profile_name = os.getenv("SELECT_AI_PROFILE_NAME", "async_oci_ai_profile") +worker_count = int(os.getenv("SELECT_AI_WORKER_COUNT", str(pool_max))) + +prompts = [ + "How many customers?", + "How many products?", + "How many promotions?", + "List the top 5 customers by sales.", +] + + +async def worker(name, profile, queue, results): + while True: + item = await queue.get() + try: + if item is None: + return + + index, prompt = item + sql = await profile.show_sql(prompt=prompt) + results[index] = (prompt, sql) + finally: + queue.task_done() + + +async def main(): + select_ai.create_pool_async( + user=user, + password=password, + dsn=dsn, + min_size=pool_min, + max_size=pool_max, + increment=pool_increment, + ) + + try: + profile = await select_ai.AsyncProfile(profile_name=profile_name) + queue = asyncio.Queue() + results = [None] * len(prompts) + + workers = [ + asyncio.create_task(worker(i, profile, queue, results)) + for i in range(worker_count) + ] + + for index, prompt in enumerate(prompts): + await queue.put((index, prompt)) + + for _ in workers: + await queue.put(None) + + await queue.join() + await asyncio.gather(*workers) + + for prompt, sql in results: + print(f"\nPrompt: {prompt}") + print(sql) + finally: + await select_ai.async_disconnect() + + +asyncio.run(main()) diff --git a/recipes/concurrent_prompt_processing/sync_ordered_results.py b/recipes/concurrent_prompt_processing/sync_ordered_results.py new file mode 100644 index 0000000..8eab7ce --- /dev/null +++ b/recipes/concurrent_prompt_processing/sync_ordered_results.py @@ -0,0 +1,60 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2026, Oracle and/or its affiliates. +# +# Licensed under the Universal Permissive License v 1.0 as shown at +# http://oss.oracle.com/licenses/upl. +# ----------------------------------------------------------------------------- + +# ----------------------------------------------------------------------------- +# concurrent_prompt_processing/sync_ordered_results.py +# +# Process independent prompts concurrently and keep results in input order. +# ----------------------------------------------------------------------------- + +import os +from concurrent.futures import ThreadPoolExecutor + +import select_ai + +user = os.getenv("SELECT_AI_USER") +password = os.getenv("SELECT_AI_PASSWORD") +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING") + +pool_min = int(os.getenv("SELECT_AI_POOL_MIN", "1")) +pool_max = int(os.getenv("SELECT_AI_POOL_MAX", "4")) +pool_increment = int(os.getenv("SELECT_AI_POOL_INCREMENT", "1")) + +profile_name = os.getenv("SELECT_AI_PROFILE_NAME", "oci_ai_profile") +max_workers = int(os.getenv("SELECT_AI_MAX_WORKERS", str(pool_max))) + +prompts = [ + "How many customers?", + "How many products?", + "How many promotions?", + "List the top 5 customers by sales.", +] + + +def show_sql(prompt): + profile = select_ai.Profile(profile_name=profile_name) + return profile.show_sql(prompt=prompt) + + +select_ai.create_pool( + user=user, + password=password, + dsn=dsn, + min_size=pool_min, + max_size=pool_max, + increment=pool_increment, +) + +try: + with ThreadPoolExecutor(max_workers=max_workers) as executor: + results = executor.map(show_sql, prompts) + + for prompt, sql in zip(prompts, results): + print(f"\nPrompt: {prompt}") + print(sql) +finally: + select_ai.disconnect() diff --git a/recipes/concurrent_prompt_processing/sync_queue_workers.py b/recipes/concurrent_prompt_processing/sync_queue_workers.py new file mode 100644 index 0000000..71e0545 --- /dev/null +++ b/recipes/concurrent_prompt_processing/sync_queue_workers.py @@ -0,0 +1,88 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2026, Oracle and/or its affiliates. +# +# Licensed under the Universal Permissive License v 1.0 as shown at +# http://oss.oracle.com/licenses/upl. +# ----------------------------------------------------------------------------- + +# ----------------------------------------------------------------------------- +# concurrent_prompt_processing/sync_queue_workers.py +# +# Process prompts with synchronous queue workers. +# ----------------------------------------------------------------------------- + +import os +from queue import Queue +from threading import Thread + +import select_ai + +user = os.getenv("SELECT_AI_USER") +password = os.getenv("SELECT_AI_PASSWORD") +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING") + +pool_min = int(os.getenv("SELECT_AI_POOL_MIN", "1")) +pool_max = int(os.getenv("SELECT_AI_POOL_MAX", "4")) +pool_increment = int(os.getenv("SELECT_AI_POOL_INCREMENT", "1")) + +profile_name = os.getenv("SELECT_AI_PROFILE_NAME", "oci_ai_profile") +worker_count = int(os.getenv("SELECT_AI_WORKER_COUNT", str(pool_max))) + +prompts = [ + "How many customers?", + "How many products?", + "How many promotions?", + "List the top 5 customers by sales.", +] + + +def worker(queue, results): + while True: + item = queue.get() + try: + if item is None: + return + + index, prompt = item + profile = select_ai.Profile(profile_name=profile_name) + sql = profile.show_sql(prompt=prompt) + results[index] = (prompt, sql) + finally: + queue.task_done() + + +select_ai.create_pool( + user=user, + password=password, + dsn=dsn, + min_size=pool_min, + max_size=pool_max, + increment=pool_increment, +) + +try: + queue = Queue() + results = [None] * len(prompts) + + workers = [ + Thread(target=worker, args=(queue, results)) + for _ in range(worker_count) + ] + for thread in workers: + thread.start() + + for index, prompt in enumerate(prompts): + queue.put((index, prompt)) + + for _ in workers: + queue.put(None) + + queue.join() + for thread in workers: + thread.join() + + for prompt, sql in results: + print(f"\nPrompt: {prompt}") + print(sql) +finally: + select_ai.disconnect() diff --git a/recipes/concurrent_prompt_processing/sync_thread_pool.py b/recipes/concurrent_prompt_processing/sync_thread_pool.py new file mode 100644 index 0000000..f117a87 --- /dev/null +++ b/recipes/concurrent_prompt_processing/sync_thread_pool.py @@ -0,0 +1,61 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2026, Oracle and/or its affiliates. +# +# Licensed under the Universal Permissive License v 1.0 as shown at +# http://oss.oracle.com/licenses/upl. +# ----------------------------------------------------------------------------- + +# ----------------------------------------------------------------------------- +# concurrent_prompt_processing/sync_thread_pool.py +# +# Process independent prompts concurrently with the synchronous Profile API. +# ----------------------------------------------------------------------------- + +import os +from concurrent.futures import ThreadPoolExecutor, as_completed + +import select_ai + +user = os.getenv("SELECT_AI_USER") +password = os.getenv("SELECT_AI_PASSWORD") +dsn = os.getenv("SELECT_AI_DB_CONNECT_STRING") + +pool_min = int(os.getenv("SELECT_AI_POOL_MIN", "1")) +pool_max = int(os.getenv("SELECT_AI_POOL_MAX", "4")) +pool_increment = int(os.getenv("SELECT_AI_POOL_INCREMENT", "1")) + +profile_name = os.getenv("SELECT_AI_PROFILE_NAME", "oci_ai_profile") +max_workers = int(os.getenv("SELECT_AI_MAX_WORKERS", str(pool_max))) + +prompts = [ + "How many customers?", + "How many products?", + "How many promotions?", + "List the top 5 customers by sales.", +] + + +def show_sql(prompt): + profile = select_ai.Profile(profile_name=profile_name) + return prompt, profile.show_sql(prompt=prompt) + + +select_ai.create_pool( + user=user, + password=password, + dsn=dsn, + min_size=pool_min, + max_size=pool_max, + increment=pool_increment, +) + +try: + with ThreadPoolExecutor(max_workers=max_workers) as executor: + futures = [executor.submit(show_sql, prompt) for prompt in prompts] + + for future in as_completed(futures): + prompt, sql = future.result() + print(f"\nPrompt: {prompt}") + print(sql) +finally: + select_ai.disconnect() diff --git a/src/select_ai/agent/team.py b/src/select_ai/agent/team.py index 34ea8cb..e5682a2 100644 --- a/src/select_ai/agent/team.py +++ b/src/select_ai/agent/team.py @@ -306,12 +306,10 @@ def run(self, prompt: str = None, params: Mapping = None): WAITING_FOR_HUMAN state, the input serves as the human response. :param Mapping[str, str] params: Optional parameters for the task. - Currently, the following parameters are supported: - - - conversation_id: Identifies the conversation session associated - with the agent team - - - variables: key-value pairs that provide additional input to the agent team. + Supported keys include ``conversation_id``, which identifies the + conversation session associated with the agent team, and + ``variables``, which provides additional key-value input to the agent + team. """ parameters = { @@ -752,12 +750,10 @@ async def run(self, prompt: str = None, params: Mapping = None): WAITING_FOR_HUMAN state, the input serves as the human response. :param Mapping[str, str] params: Optional parameters for the task. - Currently, the following parameters are supported: - - - conversation_id: Identifies the conversation session associated - with the agent team - - - variables: key-value pairs that provide additional input to the agent team. + Supported keys include ``conversation_id``, which identifies the + conversation session associated with the agent team, and + ``variables``, which provides additional key-value input to the agent + team. """ parameters = { diff --git a/src/select_ai/agent/tool.py b/src/select_ai/agent/tool.py index f2cd523..b4e2aaf 100644 --- a/src/select_ai/agent/tool.py +++ b/src/select_ai/agent/tool.py @@ -193,13 +193,8 @@ class ToolAttributes(SelectAIDataClass): :param select_ai.agent.ToolParams tool_params: Tool parameters for built-in tools :param List[Mapping] tool_inputs: Describes input arguments. - Similar to column comments in a table. For example: - "tool_inputs": [ - { - "name": "data_guard", - "description": "Only supported values are "Enabled" and "Disabled"" - } - ] + Similar to column comments in a table. Each mapping can include keys such + as ``name`` and ``description``. """ @@ -777,6 +772,7 @@ async def create( ): """ Create an AI Tool in the database + :param Optional[bool] enabled: Whether the tool should be enabled. Default: True :param Optional[bool] replace: Whether the tool should be replaced. diff --git a/src/select_ai/conversation.py b/src/select_ai/conversation.py index 64cf99a..414717e 100644 --- a/src/select_ai/conversation.py +++ b/src/select_ai/conversation.py @@ -161,7 +161,7 @@ def get_attributes(self) -> ConversationAttributes: def list(cls) -> Iterator["Conversation"]: """List all conversations - :return: Iterator[VectorIndex] + :return: Iterator[Conversation] """ with cursor() as cr: cr.execute( @@ -270,7 +270,7 @@ async def get_attributes(self) -> ConversationAttributes: async def list(cls) -> AsyncGenerator["AsyncConversation", None]: """List all conversations - :return: Iterator[VectorIndex] + :return: AsyncGenerator[AsyncConversation, None] """ async with async_cursor() as cr: await cr.execute(