Eklenti yazma¶
Eklentiler, çekirdeğe dokunmadan AdaptiveLearner'ı genişletir. Eklenti sistemi PluginForge (pluggy etrafında bir sarmalayıcı) kullanır. Her eklenti, bir giriş noktası aracılığıyla kayıtlı bağımsız bir Poetry paketidir.
Bu öğretici, bir rota ekleyen ve bir hook'u dinleyen bir "hello-world" eklentisi oluşturmayı anlatır.
1. Dizini iskelete dönüştür¶
mkdir -p plugins/adaptive-learner-plugin-hello/adaptive_learner_hello
mkdir -p plugins/adaptive-learner-plugin-hello/tests
cd plugins/adaptive-learner-plugin-hello
2. pyproject.toml¶
[tool.poetry]
name = "adaptive-learner-plugin-hello"
version = "1.0.0"
description = "Adaptive Learner: hello-world plugin"
authors = ["Your Name"]
license = "MIT"
[tool.poetry.dependencies]
python = "^3.11"
pluginforge = "^0.10.0"
fastapi = "^0.136.0"
[project.entry-points."adaptive_learner.plugins"]
hello = "adaptive_learner_hello.plugin:HelloPlugin"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
Giriş noktası adı (burada hello), eklenti kayıt defterinin
eklentiyi takip etmek için kullandığı şeydir. Sınıf yolu
(adaptive_learner_hello.plugin:HelloPlugin), eklenti sınıfına
Python içe aktarma yoludur.
3. plugin.py¶
from pluginforge import BasePlugin, hookimpl
from typing import Any
class HelloPlugin(BasePlugin):
name = "hello"
version = "1.0.0"
# pluginforge ^0.10.0 kimlik geçidiz. Bunu
# "adaptive_learner" olarak ayarlayın; böylece host'un
# PluginManager'ı (``app_id="adaptive_learner"``'ı geçen)
# eklentiyi bu uygulamayı hedeflediği olarak tanır.
target_application = "adaptive_learner"
depends_on: list[str] = []
@hookimpl
def on_session_complete(
self, session: dict[str, Any], rating: dict[str, Any]
) -> None:
print(f"Hello! Session {session['id']} ended.")
BasePlugin, PluginForge'dan temel sınıftır. @hookimpl
dekoratörü, bir yöntemi backend/app/hookspecs.py'de belirtilen
bir hook'u uyguladığı olarak işaretler.
4. routes.py¶
from fastapi import APIRouter
router = APIRouter(prefix="/api/plugins/hello", tags=["hello"])
@router.get("/greet")
def greet() -> dict:
return {"message": "Hello from the hello plugin!"}
5. plugin.py'de rotaları kaydet¶
from fastapi import FastAPI
from .routes import router
class HelloPlugin(BasePlugin):
...
def mount_routes(self, app: FastAPI) -> None:
app.include_router(router)
Eklenti yöneticisi, çekirdek uygulama başlatıldıktan sonra
bunu tanımlayan her eklenti için mount_routes() çağırır.
6. Testler¶
# tests/test_plugin.py
from adaptive_learner_hello.plugin import HelloPlugin
def test_hello_plugin_has_name():
plugin = HelloPlugin()
assert plugin.name == "hello"
7. Yükle + etkinleştir¶
Eklentiyi backend/pyproject.toml'a path-dep olarak ekleyin:
[tool.poetry.dependencies]
...
adaptive-learner-plugin-hello = {path = "../plugins/adaptive-learner-plugin-hello", develop = true}
Ardından:
cd backend && poetry lock && poetry install
make dev
curl http://localhost:18001/api/plugins/hello/greet
10 hookspec¶
Tüm hook spesifikasyonları backend/app/hookspecs.py'de yaşar:
get_assessment_questions(lang: str)— soru paketi döndür.calculate_profile(answers: list)— yöntem ağırlıklarını hesapla (firstresult).create_session_prompt(...)— sistem istemini oluştur (firstresult).ai_complete(messages, model, api_key, max_tokens)— AI'yi eş zamanlı olarak çağır (firstresult, sağlayıcı model önekine göre yönlendirir).ai_complete_async(...)— paralel döngü sınırı değerlendirmesi için async varyant (v1.5.0+, firstresult).ai_complete_stream(...)— SSE aracılığıyla metin deltalarını verimleyen akış varyantı (v1.6.0+, firstresult).recommend_method_switch(history, profile)— bir geçiş önerisi veya None döndür.on_session_complete(session, rating)— yayın yan etkisi; oyunlaştırma + takip dinler.get_progress_summary(project_id, db)— gösterge tablosu özetinin bir ad alanı dilimini döndür.get_tool_recommendations(profile, lang)— sıralı araçları döndür.
firstresult semantiği¶
firstresult=True ile işaretlenen hook'lar, None olmayan bir
değer döndüren ilk eklentide durur. "Tam olarak bir eklenti bunu
yönetmeli" durumları için yararlıdır — ai_complete gibi, eşleşen
sağlayıcının eklentisi metni döndürür ve diğerleri None döndürür.
firstresult=True olmayan hook'lar her eklentide çalışır (liste
modu). Arayan, bir sonuç listesi alır ve ne yapacağına karar verir
(birleştir, tercih et, vb.).