Skip to content

🦆 Python библиотека для взаимодействия с Duck.ai со встроенным API сервером

Notifications You must be signed in to change notification settings

paranoik1/duck-chat-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🦆 Duck Chat

Библиотека для программного взаимодействия с AI-моделями через DuckDuckGo AI Chat

Эта библиотека предоставляет Python API для работы с DuckDuckGo AI Chat и включает встроенный сервис для запуска локального HTTP-сервера. Теперь вы можете использовать мощные AI-модели напрямую в своем коде или через REST API.


🚀 Ключевые возможности

  • Прямой доступ к AI-моделям DuckDuckGo через Python API
  • Встроенный FastAPI-сервер для удобной интеграции с любыми приложениями
  • Автоматическое управление заголовками запросов (через Playwright)
  • Поддержка изображений в запросах
  • Web-поиск в ответах моделей
  • Совместимость с различными AI-моделями (GPT-4o, Claude, Llama и др.)

📦 Установка

Установка основной библиотеки:

pip install git+https://github.com/paranoik1/duck-chat-api

Установка с дополнительными зависимостями для API-сервиса:

pip install "duck-chat-api[api-service]"

Установка для разработки:

git clone https://github.com/paranoik1/duck-local-chat-api
cd duck-local-chat-api
poetry install --with api-service,dev

Важно: Для работы с API-сервисом необходимы системные зависимости:

sudo apt install xvfb

💻 Использование библиотеки

Базовое использование:

import asyncio
from duck_chat_api import DuckChat, ModelType
from duck_chat_api.utils.headers import get_headers

async def main():
    headers = await get_headers()
    async with DuckChat(headers, model=ModelType.Gpt4OMini) as chat:
        async for part in chat.ask_question("Привет! Кто ты?"):
            if hasattr(part, 'text'):
                print(part.text, end="", flush=True)
        print()

asyncio.run(main())

Расширенное использование с параметрами:

import asyncio
from duck_chat_api import DuckChat, PartText, PartImage
from duck_chat_api.utils.headers import get_headers
import base64


async def chat_with_image():
    headers = await get_headers()
    async with DuckChat(headers, model="gpt-4o-mini") as chat:
        # Подготовка изображения
        with open("image.jpg", "rb") as img_file:
            image_data = base64.b64encode(img_file.read()).decode()
        
        # Формирование запроса с изображением
        query = [
            PartText.create("Что изображено на картинке?"),
            PartImage.create(image_data)
        ]
        
        # Отправка запроса с включенным веб-поиском
        async for part in chat.ask_question(query, web_search=True):
            if hasattr(part, 'text'):
                print(part.text, end="", flush=True)
        print()

asyncio.run(chat_with_image())

Важно: Библиотека рассчитана на самостоятельное управление заголовками запросов. Пользователи должны самостоятельно получать (get_headers() или другими методами) и обновлять заголовки (chat.set_headers(headers)).


🌐 Запуск API-сервиса

Через CLI:

duck-api-service --host 0.0.0.0 --port 8000 --log-level info

Программно:

from duck_chat_api.service import app
import uvicorn

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

После запуска сервиса доступны эндпоинты:

  • POST /chat — отправка запроса к AI-модели
  • GET /docs — интерактивная документация Swagger UI
  • GET /redoc — альтернативная документация ReDoc

Пример запроса к API:

curl -X POST http://localhost:8000/chat \
  -F "content=Что на этой картинке?" \
  -F "model=gpt-4o-mini" \
  -F "web_search=true" \
  -F "file=@/path/to/image.jpg"

🖥️ Архитектура библиотеки

duck_chat_api/
├── __init__.py           # Основные импорты
├── api.py                # Класс DuckChat для взаимодействия с API
├── event.py              # Обработка событий от DuckDuckGo
├── exceptions.py         # Пользовательские исключения
├── model_type.py         # Типы поддерживаемых моделей
├── parts.py              # Структуры данных для частей сообщений
├── request_data.py       # Формирование запросов к API
├── service/              # Модуль для запуска API-сервиса
│   ├── __main__.py       # Точка входа для CLI
│   ├── headers_manager.py# Управление заголовками запросов
│   ├── service.py        # FastAPI приложение
│   └── utils.py          # Вспомогательные функции
└── utils/                # Утилиты для работы с заголовками и моделями
    ├── headers.py        # Получение валидных заголовков через Playwright
    └── models.py         # Парсинг доступных моделей

🔧 Доступные модели

Библиотека автоматически определяет доступные модели при запуске. Основные поддерживаемые модели:

  • gpt-4o-mini
  • gpt-5-mini
  • claude-3-5-haiku-latest
  • meta-llama/Llama-4-Scout-17B-16E-Instruct
  • mistralai/Mistral-Small-24B-Instruct-2501
  • openai/gpt-oss-120b

Для получения актуального списка моделей используйте:

from duck_chat_api.utils.models import get_models_page_html, parse_models
from duck_chat_api.service.utils import generate_models
import asyncio
from pprint import pprint

async def print_models():
    html = await get_models_page_html()
    models = parse_models(html)
    pprint(models)
    # ИЛИ же
    models = await generate_models()
    pprint(models)

asyncio.run(print_models())

🧩 Работа с частями сообщений (Parts)

Библиотека duck_chat_api использует концепцию "частей сообщений" (parts) для гибкого формирования запросов и обработки ответов. Все части сообщений наследуются от базового класса Part и имеют специфическую структуру.

Доступные типы частей сообщений

Part (базовый класс)

  • Абстрактный базовый класс для всех типов частей
  • Содержит поле type для идентификации типа части
  • Атрибут IS_SAVE определяет, нужно ли сохранять часть в истории диалога

PartText

  • Представляет текстовую часть сообщения
  • Создание: PartText.create("Ваш текст здесь")
  • Поля:
    • text: содержимое текста

PartImage

  • Представляет изображение в запросе
  • Создание: PartImage.create(base64_encoded_image, mime_type="image/jpeg")
  • Поля:
    • mime_type: MIME-тип изображения (по умолчанию image/webp)
    • image: изображение в формате data URL (data:{mime_type};base64,{base64})

PartTool

  • Используется моделью для вызова инструментов (автоматически)
  • Не предназначен для ручного создания в запросах
  • Представляет либо вызов инструмента, либо результат его выполнения
  • Поля:
    • tool_call_id: идентификатор вызова
    • state: состояние (call или result)
    • tool_arguments, tool_name: параметры вызова (при state=call)
    • result: результат выполнения (при state=result)

PartSource

  • Представляет источники информации в ответах модели
  • Не сохраняется в истории диалога (IS_SAVE = False)
  • Поля:
    • source: объект с информацией об источнике

Правила использования

Тип части Можно использовать в запросе Может вернуться в ответе Примечание
PartText Основной тип для текстовых запросов и ответов
PartImage Только для отправки изображений в запросах
PartTool Автоматически обрабатывается моделью
PartSource Источники информации в результатах поиска

Примеры использования

import asyncio
from duck_chat_api import DuckChat, PartText, PartImage, PartSource
from duck_chat_api.utils.headers import get_headers
import base64

async def chat_with_image():
    # Получение валидных заголовков для запросов к API
    headers = await get_headers()
    
    async with DuckChat(headers, model="gpt-4o-mini") as chat:
        # Подготовка изображения
        with open("image.jpg", "rb") as img_file:
            image_data = base64.b64encode(img_file.read()).decode()
        
        # Формирование запроса с изображением
        query = [
            PartText.create("Что изображено на картинке?"),
            PartImage.create(image_data)
        ]
        
        # Отправка запроса с включенным веб-поиском
        async for part in chat.ask_question(query, web_search=True):
            if isinstance(part, PartText):
                print(part.text, end="", flush=True)
            elif isinstance(part, PartSource):
                print("\n" + part.source.title + ": " + part.source.url)
            elif isinstance(part, PartTool):
              if part.state == "call" and part.tool_name == "WebSearch":
                  print("\n[Выполняется поиск в интернете...]")
        print()

asyncio.run(chat_with_image())

Важно: при создании запросов вы можете использовать только PartText и PartImage. Все остальные типы частей (PartTool, PartSource) генерируются автоматически моделью при формировании ответа и не должны создаваться вручную в запросах.


⚠️ Ограничения и требования

  • Только Linux (если получение заголовков требуется в headless режиме) (из-за зависимости xvfbwrapper)
  • Python 3.13+ (требуется для всех функций библиотеки)
  • Chromium должен быть установлен в системе
  • Срок действия заголовков ограничен (обычно 5-10 запросов)
  • Не предназначен для массового использования (следуйте правилам duck.ai)
  • Некоторые модели могут требовать аккаунта DuckDuckGo Pro (не поддерживается проектом)

🙏 Благодарности

  • mrgick/duck_chat — за основу реализации
  • patchright — за решение по обходу проверок на ботов
  • FastAPI и Playwright — за отличные инструменты

🦆 Утки не возвращаются, но API — да.

Пользуйтесь с умом и соблюдайте правила использования DuckDuckGo AI.

About

🦆 Python библиотека для взаимодействия с Duck.ai со встроенным API сервером

Topics

Resources

Stars

Watchers

Forks

Languages