Plugin tizimi¶
Qanot AI pluginlar orqali yangi toollar qo'shish, agentning shaxsini kengaytirish va tashqi servislar bilan integratsiya qilishni qo'llab-quvvatlaydi.
Plugin arxitekturasi¶
Plugin -- bu kamida plugin.py fayli bo'lgan papka, ichida Plugin klassidan voris olingan klass bo'lishi kerak:
plugins/
└── myplugin/
├── plugin.py # Majburiy: Plugin subclass
├── TOOLS.md # Ixtiyoriy: workspace TOOLS.md ga qo'shiladigan hujjat
└── helpers.py # Ixtiyoriy: qo'shimcha modullar
Pluginlar ikkita joydan yuklanadi (navbat bilan tekshiriladi):
- O'rnatilgan: paket ildizidagi
plugins/papkasi - Tashqi: configdagi
plugins_diryo'li (standart:/data/plugins)
Plugin yaratish¶
1-qadam: Plugin papkasini yarating¶
2-qadam: plugin.py yozing¶
from qanot.plugins.base import Plugin, ToolDef, tool
class QanotPlugin(Plugin):
"""Weather lookup plugin."""
name = "weather"
description = "Weather information for Uzbekistan cities"
# Ixtiyoriy: workspace TOOLS.md ga qo'shiladigan matn
tools_md = """
## Weather Tools
### weather_get
Get current weather for a city in Uzbekistan.
- **city**: City name (e.g., "Tashkent", "Samarkand")
"""
# Ixtiyoriy: workspace SOUL.md ga qo'shiladigan matn
soul_append = """
## Weather Behavior
When asked about weather, always use the weather_get tool.
Include temperature in both Celsius and Fahrenheit.
"""
async def setup(self, config: dict) -> None:
"""Plugin yuklanayotganda chaqiriladi. Resurslarni shu yerda tayyorlang."""
self.api_key = config.get("api_key", "")
self.base_url = config.get("base_url", "https://api.weather.example.com")
async def teardown(self) -> None:
"""Yopilayotganda chaqiriladi. Resurslarni tozalash shu yerda."""
pass
def get_tools(self) -> list[ToolDef]:
"""Tool definitionlarni qaytaradi. Dekoratorli metodlar uchun _collect_tools() ishlating."""
return self._collect_tools()
@tool(
name="weather_get",
description="Hozirgi ob-havo ma'lumotlari.",
parameters={
"type": "object",
"required": ["city"],
"properties": {
"city": {
"type": "string",
"description": "Shahar nomi (masalan: Tashkent)",
},
},
},
)
async def weather_get(self, params: dict) -> str:
import aiohttp
import json
city = params.get("city", "Tashkent")
async with aiohttp.ClientSession() as session:
async with session.get(
f"{self.base_url}/current",
params={"city": city, "key": self.api_key},
) as resp:
data = await resp.json()
return json.dumps(data, ensure_ascii=False)
3-qadam: Pluginni sozlang¶
config.json ga plugin qo'shing:
{
"plugins": [
{
"name": "weather",
"enabled": true,
"config": {
"api_key": "your-weather-api-key",
"base_url": "https://api.weather.example.com"
}
}
]
}
@tool dekoratori¶
@tool dekoratori metodga agent tomonidan chaqirilish imkonini beradi:
@tool(
name="tool_name", # Noyob tool nomi
description="What it does", # LLM ga ko'rsatiladi
parameters={ # Kirish uchun JSON Schema
"type": "object",
"required": ["param1"],
"properties": {
"param1": {"type": "string", "description": "..."},
"param2": {"type": "integer", "description": "...", "default": 10},
},
},
)
async def my_tool(self, params: dict) -> str:
# params -- JSON Schema ga mos dict
# String qaytaring (odatda JSON)
return json.dumps({"result": "value"})
Plugin klassidagi _collect_tools() metodi barcha @tool bilan belgilangan metodlarni topib, ToolDef obyektlarini qaytaradi.
Plugin hayot sikli¶
Yuklash¶
- Plugin nomi o'rnatilgan va tashqi papkalardan qidiriladi
plugin.pydinamik import qilinadiQanotPluginnomli klass qidiriladi; topilmasa, har qandayPluginsubklassi ishlatiladi- Klass yaratiladi va
setup(config)chaqiriladi get_tools()chaqirilib, har bir toolToolRegistryga ro'yxatdan o'tkaziladitools_mdmazmuniworkspace/TOOLS.mdga qo'shiladisoul_appendmazmuniworkspace/SOUL.mdga qo'shiladi
Ishlash vaqtida¶
- Toollar yuklangandan so'ng darhol ishga tayyor
- Plugin instansiyasi jarayon yashayotgan vaqt davomida saqlanadi
- Agent tool chaqirganda handler params dict bilan ishga tushadi
Yopilish¶
Jarayon tugaganda teardown() chaqiriladi. Ulanishlarni yopish, buferlarni flush qilish va h.k. uchun ishlating.
TOOLS.md integratsiyasi¶
Plugin tools_md o'rnatgan bo'lsa, bu mazmun workspace TOOLS.md fayliga qo'shiladi. Agent toollaringiz haqida aynan shu orqali bilib oladi -- mazmun system prompt da ko'rinadi.
Mazmun faqat bir marta qo'shiladi (plugin nomi bo'yicha tekshiriladi). Agentga toollaringizni qachon va qanday ishlatishni tushuntiruvchi Markdown yozing.
SOUL_APPEND integratsiyasi¶
Plugin soul_append o'rnatgan bo'lsa, bu mazmun workspace SOUL.md fayliga qo'shiladi. Pluginingizga oid shaxsiy xususiyatlar yoki xulq-atvor qoidalarini qo'shish uchun ishlating.
soul_append ning birinchi qatori takrorlanmaslik markeri sifatida ishlatiladi -- ikki marta qo'shilmaydi.
Plugin konfiguratsiyasi¶
setup() ga berilgan config dict to'g'ridan-to'g'ri config.json dagi plugin yozuvidan keladi. Istalgan kalit-qiymat juftlarini qo'yishingiz mumkin:
{
"name": "myplugin",
"enabled": true,
"config": {
"api_url": "https://api.example.com",
"db_host": "localhost",
"db_port": 3306,
"db_user": "admin",
"db_password": "secret",
"timeout": 30
}
}
setup() da foydalanish:
async def setup(self, config: dict) -> None:
self.api_url = config["api_url"]
self.timeout = config.get("timeout", 10)
To'g'ridan-to'g'ri tool ro'yxatdan o'tkazish¶
To'liq plugin kerak bo'lmagan hollarda, toollarni bevosita ToolRegistry ga ro'yxatdan o'tkazing:
async def my_handler(params: dict) -> str:
return json.dumps({"ok": True})
registry.register(
name="my_tool",
description="Does something useful.",
parameters={"type": "object", "properties": {}},
handler=my_handler,
)
Bu qanot/main.py da o'rnatilgan toollar uchun ishlatiladi va maxsus kirish nuqtalarida ham ishlatish mumkin.
Plugin topish mexanizmi¶
Pluginlar papka nomi bo'yicha topiladi. Loader quyidagilarni tekshiradi:
{package_root}/plugins/{name}/plugin.py-- Qanot bilan birga keladigan o'rnatilgan pluginlar{plugins_dir}/{name}/plugin.py-- config yo'lidagi tashqi pluginlar
Plugin papkasi yuklash vaqtida vaqtincha sys.path ga qo'shiladi, keyin olib tashlanadi. Shuning uchun pluginingiz o'z papkasidagi qo'shni modullardan import qilishi mumkin.
Plugin Manifest (plugin.json)¶
Pluginlar metadata va dependency boshqaruvi uchun plugin.json faylini o'z ichiga olishi mumkin:
{
"name": "weather",
"version": "1.0.0",
"description": "Weather information for Uzbekistan cities",
"author": "Your Name",
"dependencies": ["aiohttp>=3.9"],
"plugin_deps": ["cloud_reporter"],
"required_config": ["api_key"],
"min_qanot_version": "2.0.0",
"homepage": "https://github.com/example/weather-plugin",
"license": "MIT"
}
| Maydon | Turi | Tavsif |
|---|---|---|
name |
string | Plugin nomi (standart: papka nomi) |
version |
string | Semantik versiya (standart: "0.1.0") |
description |
string | Odam tushunadigan tavsif |
author |
string | Plugin muallifi |
dependencies |
list | Plugin uchun kerakli pip paketlar |
plugin_deps |
list | Bu plugin bog'liq bo'lgan boshqa Qanot pluginlar |
required_config |
list | Plugin configida bo'lishi shart bo'lgan kalitlar |
min_qanot_version |
string | Talab qilinadigan minimal Qanot versiyasi |
homepage |
string | Plugin hujjatlari yoki repozitoriya URL |
license |
string | Litsenziya identifikatori (standart: "MIT") |
Agar plugin.json bo'lmasa, papka nomidan standart manifest yaratiladi.
Xatolarni boshqarish¶
on_error() hook¶
Pluginlar tool bajarilish xatolarini boshqarish uchun on_error() metodini qayta yozishi mumkin:
async def on_error(self, tool_name: str, error: Exception) -> None:
"""Tool bajarilishi muvaffaqiyatsiz bo'lganda chaqiriladi."""
logger.error("Tool %s failed: %s", tool_name, error)
# Maxsus xato boshqaruvi: qayta urinish, xabar berish, zaxira variant va h.k.
Bu hook tool nomi va yuzaga kelgan istisno bilan chaqiriladi. Maxsus xato hisoboti, qayta urinish mantiqiy yoki muammosiz pasayish uchun uni qayta yozing.
validate_tool_params()¶
validate_tool_params() funksiyasi tool parametrlari uchun yengil JSON Schema validatsiyasini ta'minlaydi:
from qanot.plugins.base import validate_tool_params
errors = validate_tool_params(
params={"city": "Tashkent", "units": 42},
schema={
"type": "object",
"required": ["city"],
"properties": {
"city": {"type": "string"},
"units": {"type": "string"},
},
},
)
# errors: ["Parameter 'units' expected string, got int"]
Bu majburiy maydonlar va asosiy tur mosligini tekshiradi (string, integer, number, boolean, array, object). Barcha parametrlar to'g'ri bo'lsa bo'sh ro'yxat qaytaradi.
Mavjud pluginlar¶
| Plugin | Toollar | Tavsif |
|---|---|---|
| amoCRM | 20 | CRM integratsiya: leadlar, kontaktlar, pipelinelar, vazifalar, izohlar |
| Bitrix24 | 24 | CRM integratsiya: bitimlar, leadlar, kontaktlar, vazifalar, faoliyatlar |
| 1C Enterprise | 13 | Buxgalteriya: kontragentlar, mahsulotlar, sotuvlar, xaridlar, qoldiqlar |
| AbsMarket | 8 | POS tizimi: mahsulotlar, sotuvlar, inventar, hisobotlar |
| AbsVision | 3 | HR tizimi: xodimlar, davomat, ish haqi |
| iBox POS | 10 | POS tizimi: mahsulotlar, buyurtmalar, to'lovlar, qoldiqlar |
| Eskiz SMS | 4 | SMS yuborish, shablon boshqaruvi, yetkazish holati (Eskiz.uz orqali) |
| MySQL Query | 1 | Mustaqil faqat-SELECT SQL so'rov tooli |
| Cloud Reporter | 1 | Qanot Cloud platformasiga foydalanish hisoboti |
Ko'proq pluginlar QanotHub da mavjud -- jamoat va rasmiy pluginlar katalogi.