Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "gigachat"
version = "0.1.38"
version = "0.1.39"
description = "GigaChat. Python-library for GigaChain and LangChain"
authors = ["Konstantin Krestnikov <[email protected]>", "Sergey Malyshev <[email protected]>"]
license = "MIT"
Expand All @@ -11,7 +11,7 @@ packages = [{include = "gigachat", from = "src"}]
[tool.poetry.dependencies]
python = "^3.8"
pydantic = ">=1"
httpx = "<=0.27.2"
httpx = "<1"

[tool.poetry.group.dev.dependencies]
black = "^23.12.1"
Expand Down
44 changes: 44 additions & 0 deletions src/gigachat/api/get_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from typing import Any, Dict, Optional

import httpx

from gigachat.api.utils import build_headers, build_response
from gigachat.models import UploadedFile


def _get_kwargs(
*,
file: str,
access_token: Optional[str] = None,
) -> Dict[str, Any]:
headers = build_headers(access_token)

return {
"method": "GET",
"url": f"/files/{file}",
"headers": headers,
}


def sync(
client: httpx.Client,
*,
file: str,
access_token: Optional[str] = None,
) -> UploadedFile:
"""Возвращает объект с описанием указанного файла."""
kwargs = _get_kwargs(file=file, access_token=access_token)
response = client.request(**kwargs)
return build_response(response, UploadedFile)


async def asyncio(
client: httpx.AsyncClient,
*,
file: str,
access_token: Optional[str] = None,
) -> UploadedFile:
"""Возвращает объект с описанием указанного файла."""
kwargs = _get_kwargs(file=file, access_token=access_token)
response = await client.request(**kwargs)
return build_response(response, UploadedFile)
41 changes: 41 additions & 0 deletions src/gigachat/api/get_files.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from typing import Any, Dict, Optional

import httpx

from gigachat.api.utils import build_headers, build_response
from gigachat.models import UploadedFiles


def _get_kwargs(
*,
access_token: Optional[str] = None,
) -> Dict[str, Any]:
headers = build_headers(access_token)

return {
"method": "GET",
"url": "/files",
"headers": headers,
}


def sync(
client: httpx.Client,
*,
access_token: Optional[str] = None,
) -> UploadedFiles:
"""Возвращает загруженные файлы"""
kwargs = _get_kwargs(access_token=access_token)
response = client.request(**kwargs)
return build_response(response, UploadedFiles)


async def asyncio(
client: httpx.AsyncClient,
*,
access_token: Optional[str] = None,
) -> UploadedFiles:
"""Возвращает загруженные файлы"""
kwargs = _get_kwargs(access_token=access_token)
response = await client.request(**kwargs)
return build_response(response, UploadedFiles)
42 changes: 42 additions & 0 deletions src/gigachat/api/post_files_delete.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from typing import Any, Dict, Optional

import httpx

from gigachat.api.utils import build_headers, build_response
from gigachat.models import DeletedFile


def _get_kwargs(
*,
file: str,
access_token: Optional[str] = None,
) -> Dict[str, Any]:
return {
"method": "POST",
"url": f"/files/{file}/delete",
"files": {"file": file},
"data": {},
"headers": build_headers(access_token),
}


def sync(
client: httpx.Client,
*,
file: str,
access_token: Optional[str] = None,
) -> DeletedFile:
kwargs = _get_kwargs(file=file, access_token=access_token)
response = client.request(**kwargs)
return build_response(response, DeletedFile)


async def asyncio(
client: httpx.AsyncClient,
*,
file: str,
access_token: Optional[str] = None,
) -> DeletedFile:
kwargs = _get_kwargs(file=file, access_token=access_token)
response = await client.request(**kwargs)
return build_response(response, DeletedFile)
50 changes: 49 additions & 1 deletion src/gigachat/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@
from gigachat._types import FileTypes
from gigachat.api import (
get_balance,
get_file,
get_files,
get_image,
get_model,
get_models,
post_auth,
post_chat,
post_embeddings,
post_files,
post_files_delete,
post_functions_convert,
post_token,
post_tokens_count,
Expand All @@ -42,6 +45,7 @@
Chat,
ChatCompletion,
ChatCompletionChunk,
DeletedFile,
Embeddings,
Image,
Messages,
Expand All @@ -52,6 +56,7 @@
Token,
TokensCount,
UploadedFile,
UploadedFiles,
)
from gigachat.settings import Settings
from gigachat.threads import ThreadsAsyncClient, ThreadsSyncClient
Expand Down Expand Up @@ -101,7 +106,8 @@ def _parse_chat(payload: Union[Chat, Dict[str, Any], str], settings: Settings) -
chat = Chat(messages=[Messages(role=MessagesRole.USER, content=payload)])
else:
chat = Chat.parse_obj(payload)
if chat.model is None:
using_assistant = chat.storage is not None and (chat.storage.assistant_id or chat.storage.thread_id)
if not using_assistant and chat.model is None:
chat.model = settings.model or GIGACHAT_MODEL
if chat.profanity_check is None:
chat.profanity_check = settings.profanity_check
Expand Down Expand Up @@ -289,6 +295,21 @@ def upload_file(
lambda: post_files.sync(self._client, file=file, purpose=purpose, access_token=self.token)
)

def get_file(self, file: str) -> UploadedFile:
"""Получает информацию о файле"""
return self._decorator(lambda: get_file.sync(self._client, file=file, access_token=self.token))

def get_files(self) -> UploadedFiles:
"""Получает загруженные файлы"""
return self._decorator(lambda: get_files.sync(self._client, access_token=self.token))

def delete_file(
self,
file: str,
) -> DeletedFile:
"""Удаляет файл"""
return self._decorator(lambda: post_files_delete.sync(self._client, file=file, access_token=self.token))

def chat(self, payload: Union[Chat, Dict[str, Any], str]) -> ChatCompletion:
"""Возвращает ответ модели с учетом переданных сообщений"""
chat = _parse_chat(payload, self._settings)
Expand Down Expand Up @@ -451,6 +472,33 @@ async def _acall() -> UploadedFile:

return await self._adecorator(_acall)

async def aget_file(self, file: str) -> UploadedFile:
"""Получает информацию о файле"""

async def _acall() -> UploadedFile:
return await get_file.asyncio(self._aclient, file=file, access_token=self.token)

return await self._adecorator(_acall)

async def aget_files(self) -> UploadedFiles:
"""Получает загруженные файлы"""

async def _acall() -> UploadedFiles:
return await get_files.asyncio(self._aclient, access_token=self.token)

return await self._adecorator(_acall)

async def adelete_file(
self,
file: str,
) -> DeletedFile:
"""Удаляет файл"""

async def _acall() -> DeletedFile:
return await post_files_delete.asyncio(self._aclient, file=file, access_token=self.token)

return await self._adecorator(_acall)

async def aget_balance(self) -> Balance:
"""Метод для получения баланса доступных для использования токенов.
Только для клиентов с предоплатой иначе http 403"""
Expand Down
6 changes: 6 additions & 0 deletions src/gigachat/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from gigachat.models.chat_completion_chunk import ChatCompletionChunk
from gigachat.models.choices import Choices
from gigachat.models.choices_chunk import ChoicesChunk
from gigachat.models.deleted_file import DeletedFile
from gigachat.models.embedding import Embedding
from gigachat.models.embeddings import Embeddings
from gigachat.models.embeddings_usage import EmbeddingsUsage
Expand All @@ -18,9 +19,11 @@
from gigachat.models.model import Model
from gigachat.models.models import Models
from gigachat.models.open_api_functions import OpenApiFunctions
from gigachat.models.storage import Storage
from gigachat.models.token import Token
from gigachat.models.tokens_count import TokensCount
from gigachat.models.uploaded_file import UploadedFile
from gigachat.models.uploaded_files import UploadedFiles
from gigachat.models.usage import Usage
from gigachat.models.with_x_headers import WithXHeaders

Expand All @@ -32,6 +35,7 @@
"ChatCompletionChunk",
"Choices",
"ChoicesChunk",
"DeletedFile",
"Embedding",
"Embeddings",
"EmbeddingsUsage",
Expand All @@ -44,10 +48,12 @@
"Model",
"Models",
"OpenApiFunctions",
"Storage",
"Token",
"TokensCount",
"Usage",
"UploadedFile",
"UploadedFiles",
"Image",
"threads",
"assistants",
Expand Down
3 changes: 3 additions & 0 deletions src/gigachat/models/chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from gigachat.models.chat_function_call import ChatFunctionCall
from gigachat.models.function import Function
from gigachat.models.messages import Messages
from gigachat.models.storage import Storage
from gigachat.pydantic_v1 import BaseModel


Expand Down Expand Up @@ -35,3 +36,5 @@ class Chat(BaseModel):
"""Набор функций, которые могут быть вызваны моделью"""
flags: Optional[List[str]] = None
"""Флаги, включающие особенные фичи"""
storage: Optional[Storage] = None
"""Данные для хранения контекста на стороне GigaChat"""
6 changes: 5 additions & 1 deletion src/gigachat/models/chat_completion.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List
from typing import List, Optional

from gigachat.models.choices import Choices
from gigachat.models.usage import Usage
Expand All @@ -15,6 +15,10 @@ class ChatCompletion(WithXHeaders):
"""Дата и время создания ответа в формате Unix time"""
model: str
"""Название модели, которая вернула ответ"""
thread_id: Optional[str] = None
"""Идентификатор треда"""
message_id: Optional[str] = None
"""Идентификатор сообщения. Для storage_mode - true"""
usage: Usage
"""Данные об использовании модели"""
object_: str = Field(alias="object")
Expand Down
7 changes: 5 additions & 2 deletions src/gigachat/models/chat_completion_chunk.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import List
from typing import List, Optional

from gigachat.models.choices_chunk import ChoicesChunk
from gigachat.models.usage import Usage
from gigachat.models.with_x_headers import WithXHeaders
from gigachat.pydantic_v1 import Field

Expand All @@ -15,4 +16,6 @@ class ChatCompletionChunk(WithXHeaders):
model: str
"""Название модели, которая вернула ответ"""
object_: str = Field(alias="object")
"""Название вызываемого метода"""
"""Наименование вызываемого метода"""
usage: Optional[Usage] = None
"""Данные о потребленных токенах"""
11 changes: 11 additions & 0 deletions src/gigachat/models/deleted_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from gigachat.models.with_x_headers import WithXHeaders
from gigachat.pydantic_v1 import Field


class DeletedFile(WithXHeaders):
"""Информация об удаленном файле"""

id_: str = Field(alias="id")
"""Идентификатор файла """
deleted: bool
"""Признак удаления файла"""
31 changes: 31 additions & 0 deletions src/gigachat/models/storage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from typing import Dict, Optional, Any

from gigachat.pydantic_v1 import BaseModel


class Storage(BaseModel):
"""Данные для хранения контекста на стороне GigaChat"""

is_stateful: bool
"""
Режим сохранения сообщений контекста.
При работе с данным режимом не требуется передавать сообщения контекста каждый раз.
Достаточно передать только новое сообщение
"""
limit: Optional[int] = None
"""
Максимальное количество сообщений исторического контекста, которые посылаются в модель в запросе.
Если пользователь передает limit на генерацию ответа от модели и у него есть system в истории или
инструкция у ассистента, то кол-во сообщений отправленных в модель = limit + 1,
т.е. к лимиту добавляется систем промпт.
Если параметр не передан, считаем что необходимо отправить весь контекст.
"""
assistant_id: Optional[str] = None
"""
Идентификатор ассистента при создании треда (только в первом сообщении).
При передаче идентификатора нельзя передавать поле model.
При передаче id треда этот идентификатор не передается
"""
thread_id: Optional[str] = None
"""Идентификатор треда. Не заполняется для первого сообщения"""
metadata: Optional[Dict[Any, Any]] = None
4 changes: 4 additions & 0 deletions src/gigachat/models/uploaded_file.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Optional

from gigachat.models.with_x_headers import WithXHeaders
from gigachat.pydantic_v1 import Field

Expand All @@ -17,3 +19,5 @@ class UploadedFile(WithXHeaders):
"""Имя файла"""
purpose: str
"""Предполагаемое назначение файла."""
access_policy: Optional[str] = None
"""Доступность файла"""
Loading