diff --git a/.env.template b/.env.template new file mode 100644 index 0000000..ab27178 --- /dev/null +++ b/.env.template @@ -0,0 +1,2 @@ +POETRY=poetry +POETRY_PYTHON=python diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 4f0af95..c94a565 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -14,5 +14,5 @@ jobs: secrets: inherit with: python-version: "3.10" - poetry-version: "1.8.5" + poetry-version: "2.3.2" code-checks-python-versions: '["3.10", "3.11", "3.12", "3.13"]' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1094b5c..fceaeef 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,5 +14,5 @@ jobs: secrets: inherit with: python-version: "3.10" - poetry-version: "1.8.5" + poetry-version: "2.3.2" code-checks-python-versions: '["3.10", "3.11", "3.12", "3.13"]' diff --git a/Makefile b/Makefile index cd85160..e5c389e 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,16 @@ VENV_DIR ?= .venv -POETRY ?= $(VENV_DIR)/bin/poetry -POETRY_VERSION ?= 1.8.5 +POETRY ?= poetry +POETRY_PYTHON ?= python .PHONY: all init_env install clean lint format test spell_check +-include .env +export + all: build init_env: - python -m venv $(VENV_DIR) - $(VENV_DIR)/bin/pip install poetry==$(POETRY_VERSION) --quiet + $(POETRY) env use $(POETRY_PYTHON) install: init_env $(POETRY) install diff --git a/README.md b/README.md index 4857823..bf258f1 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,52 @@ -# AI DIAL Client (Python) - -## Table of Contents - -- [Authentication](#authentication) - - [API Keys](#api-keys) - - [Bearer Token](#bearer-token) -- [List Deployments](#list-deployments) -- [Make Chat Completions Requests](#make-completions-requests) - - [Without Streaming](#without-streaming) - - [With Streaming](#with-streaming) -- [Working with Files](#working-with-files) - - [Working with URLs](#working-with-urls) - - [Uploading Files](#uploading-files) - - [Downloading Files](#downloading-files) - - [Deleting Files](#deleting-files) - - [Accessing Metadata](#accessing-metadata) -- [Applications](#applications) - - [List Applications](#list-applications) - - [Get Application by Id](#get-application-by-id) -- [Client Pool](#client-pool) - - [Synchronous Client Pool](#synchronous-client-pool) - - [Asynchronous Client Pool](#asynchronous-client-pool) - -## Authentication - -### API Keys +

+ AI DIAL Client (Python) +

+

+

+ + About DIALX + +

+

+ + Discord + +

+ +- [Usage](#usage) + - [Authentication](#authentication) + - [API Keys](#api-keys) + - [Bearer Token](#bearer-token) + - [List Deployments](#list-deployments) + - [Make Chat Completions Requests](#make-completions-requests) + - [Without Streaming](#without-streaming) + - [With Streaming](#with-streaming) + - [Working with Files](#working-with-files) + - [Working with URLs](#working-with-urls) + - [Uploading Files](#uploading-files) + - [Downloading Files](#downloading-files) + - [Deleting Files](#deleting-files) + - [Accessing Metadata](#accessing-metadata) + - [Applications](#applications) + - [List Applications](#list-applications) + - [Get Application by Id](#get-application-by-id) + - [Client Pool](#client-pool) + - [Synchronous Client Pool](#synchronous-client-pool) + - [Asynchronous Client Pool](#asynchronous-client-pool) +- [Development](#development) + - [Pre-requisites](#pre-requisites) + - [Setup](#setup) + - [Main commands](#main-commands) + +## Usage + +This section outlines how to use the AI DIAL Python client to interact with the DIAL Core API. +It covers authentication methods, making chat completion requests, working with files, managing applications, +and utilizing client pools for efficient connection management. + +### Authentication + +#### API Keys For authentication with an API key, pass it during the client initialization: @@ -66,7 +88,7 @@ async_dial_client = AsyncDial( ) ``` -### Bearer Token +#### Bearer Token You can use a Bearer Token for a token-based authentication of API calls. Client instances will use it to construct the `Authorization` header when making requests: @@ -115,7 +137,7 @@ dial_client = Dial( ) ``` -## List Deployments +### List Deployments If you want to get a list of available deployments, use `client.deployments.list()` or method: @@ -128,9 +150,9 @@ If you want to get a list of available deployments, use `client.deployments.list ] ``` -## Make Completions Requests +### Make Completions Requests -### Without Streaming +#### Without Streaming Synchronous: @@ -203,7 +225,7 @@ ChatCompletionResponse( ) ``` -### With Streaming +#### With Streaming Synchronous: @@ -304,9 +326,9 @@ ChatCompletionChunk( ) ``` -## Working with Files +### Working with Files -### Working with URLs +#### Working with URLs Files are AI DIAL resources that operate with URL-like objects. Use `pathlib.PurePosixPath` or `str` to create to create new URL-like objects or to get a `string` representation of them. @@ -341,7 +363,7 @@ sync_client.files.upload(url=absolute_url, ...) **Note**, that an invalid URL provided to the function, will raise an `InvalidDialURLException` exception. -### Uploading Files +#### Uploading Files Use `upload()` to add files into your storage bucket: @@ -367,7 +389,7 @@ sync_client.files.upload( ) ``` -### Downloading Files +#### Downloading Files Use `download()` to download files from your storage bucket: @@ -406,7 +428,7 @@ result.write_to("./some-local-file.txt") await result.awrite_to("./some-local-file.txt") ``` -### Deleting Files +#### Deleting Files Use `delete()` to remove files from your storage bucket: @@ -421,7 +443,7 @@ await async_client.files.delete( ) ``` -### Accessing Metadata +#### Accessing Metadata Use `metadata()` to access metadata of a file: @@ -450,9 +472,9 @@ FileMetadata( ) ``` -## Applications +### Applications -### List Applications +#### List Applications To get a list of your DIAL applications: @@ -501,7 +523,7 @@ As a result, you will receive a list of `Application` objects: ] ``` -### Get Application by Id +#### Get Application by Id You can get your DIAL applications by their Ids: @@ -514,11 +536,11 @@ application = await async_client.application.get("app_id") As a result, you will receive a list of `Application` objects. Refer to the [previous example](#list-applications). -## Client Pool +### Client Pool When you need to create multiple DIAL clients and wish to enhance performance by reusing the HTTP connection for the same DIAL instance, consider using synchronous and asynchronous **client pools**. -### Synchronous Client Pool +#### Synchronous Client Pool ```python from aidial_client import DialClientPool @@ -534,7 +556,7 @@ second_client = client_pool.create_client( ) ``` -### Asynchronous Client Pool +#### Asynchronous Client Pool ```python from dial_client import ( @@ -551,3 +573,44 @@ second_client = client_pool.create_client( base_url="https://your-dial-instance.com", bearer_token="your-bearer-token" ) ``` + + +## Development + +To set up the development environment and run the project, follow the instructions below. + +### Pre-requisites + +The following tools are required to work with the project: + +1. `Make` +2. `Python 3.10` +3. `Poetry 2.*`. Installation guidance can be found [here](https://python-poetry.org/docs/#installation) + +### Setup + +1. Create `.env` file in the root of the project. Copy `.env.template` file data to the `.env` and customize the values + if needed. You can customize python and poetry locations. +2. Create and activate virtual environment + ```bash + make init_env + source .venv/bin/activate + ``` +3. Install dependencies + ```bash + make install + ``` + +### Main commands + +| Command | Description | +|-------------------------|-----------------------------------------------| +| `make install` | Install virtual environment and dependencies | +| `make build` | Build the package | +| `make clean` | Clean virtual environment and build artifacts | +| `make lint` | Run linters | +| `make format` | Run code formatters | +| `make test` | Run tests (e.g., `make test PYTHON=3.12`) | +| `make integration_test` | Run integration tests | +| `make coverage` | Generate test coverage report | +| `make help` | Show available commands | diff --git a/poetry.lock b/poetry.lock index d496a0f..8978c08 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.3.2 and should not be changed by hand. [[package]] name = "aiofiles" @@ -335,7 +335,7 @@ description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" groups = ["main", "test"] -markers = "python_version < \"3.11\"" +markers = "python_version == \"3.10\"" files = [ {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, @@ -935,7 +935,7 @@ files = [ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] -markers = {lint = "python_version < \"3.11\"", test = "python_full_version <= \"3.11.0a6\""} +markers = {lint = "python_version == \"3.10\"", test = "python_full_version <= \"3.11.0a6\""} [[package]] name = "tqdm" @@ -969,7 +969,7 @@ files = [ {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, ] -markers = {lint = "python_version < \"3.11\"", test = "python_version < \"3.11\""} +markers = {lint = "python_version == \"3.10\"", test = "python_version == \"3.10\""} [[package]] name = "virtualenv" @@ -995,5 +995,5 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess [metadata] lock-version = "2.1" -python-versions = ">=3.10,<4.0" -content-hash = "4219233c94f0a43d22424667aa17e3702edeadba1c441a1343a6f3838cbd17b5" +python-versions = ">=3.10,<3.14" +content-hash = "33d395195b5d29cd7aa1c28017af7a543b1c33babdd72386ee1dd113c230956f" diff --git a/pyproject.toml b/pyproject.toml index d8831af..62bd752 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,27 +1,29 @@ -[tool.poetry] +[project] name = "aidial-client" version = "0.5.0rc" - description = "A Python client library for the AI DIAL API" -authors = ["EPAM RAIL "] -homepage = "https://epam-rail.com" -license = "Apache-2.0" readme = "README.md" -repository = "https://github.com/epam/ai-dial-client-python" -packages = [{ include = "aidial_client" }] +license = "Apache-2.0" +requires-python = ">=3.10,<3.14" +authors = [ + { name = "DIALX", email = "SpecialEPM-DIALDevTeam@epam.com" }, +] +dependencies = [ + "openai>=1.1.0,<2.0.0", + "httpx>=0.25.0,<1.0", + "pydantic>=1.10,<3", + "aiofiles>=0.5.0", +] -[tool.poetry.dependencies] -python = ">=3.10,<4.0" -openai = ">=1.1.0,<2.0.0" -httpx = ">=0.25.0,<1.0" -pydantic = ">=1.10,<3" -aiofiles = ">=0.5.0" +[project.urls] +Homepage = "https://dialx.ai" +Repository = "https://github.com/epam/ai-dial-client-python" -[tool.setuptools] -packages = ["aidial_client"] +[tool.poetry] +packages = [{ include = "aidial_client" }] [build-system] -requires = ["poetry-core>=1.0.0"] +requires = ["poetry-core>=2.0"] build-backend = "poetry.core.masonry.api" [tool.poetry.group.test.dependencies]