Jegyzet
Az oldalhoz való hozzáférés engedélyezést igényel. Próbálhatod be jelentkezni vagy könyvtárat váltani.
Az oldalhoz való hozzáférés engedélyezést igényel. Megpróbálhatod a könyvtár váltását.
Egy vállalatnál gyakran már rendelkezik olyan API-kkal, amelyek valós munkát végeznek. Ezeket más automatizálási szolgáltatások vagy az emberek által használt előtér-alkalmazások is használhatják. A Szemantic Kernelben pontosan ugyanazokat az API-kat veheti fel, mint a beépülő modulokat, így az ügynökök is használhatják őket.
Példa OpenAPI-specifikációra
Vegyünk például egy API-t, amely lehetővé teszi a villanykörte állapotának módosítását. Ennek az API-nak az OpenAPI-specifikációja( más néven Swagger Specification, vagy csak Swagger) a következőképpen nézhet ki:
{
"openapi": "3.0.1",
"info": {
"title": "Light API",
"version": "v1"
},
"paths": {
"/Light": {
"get": {
"summary": "Retrieves all lights in the system.",
"operationId": "get_all_lights",
"responses": {
"200": {
"description": "Returns a list of lights with their current state",
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/LightStateModel"
}
}
}
}
}
}
},
"/Light/{id}": {
"post": {
"summary": "Changes the state of a light.",
"operationId": "change_light_state",
"parameters": [
{
"name": "id",
"in": "path",
"description": "The ID of the light to change.",
"required": true,
"style": "simple",
"schema": {
"type": "string"
}
}
],
"requestBody": {
"description": "The new state of the light and change parameters.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ChangeStateRequest"
}
}
}
},
"responses": {
"200": {
"description": "Returns the updated light state",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LightStateModel"
}
}
}
},
"404": {
"description": "If the light is not found"
}
}
}
}
},
"components": {
"schemas": {
"ChangeStateRequest": {
"type": "object",
"properties": {
"isOn": {
"type": "boolean",
"description": "Specifies whether the light is turned on or off.",
"nullable": true
},
"hexColor": {
"type": "string",
"description": "The hex color code for the light.",
"nullable": true
},
"brightness": {
"type": "integer",
"description": "The brightness level of the light.",
"format": "int32",
"nullable": true
},
"fadeDurationInMilliseconds": {
"type": "integer",
"description": "Duration for the light to fade to the new state, in milliseconds.",
"format": "int32",
"nullable": true
},
"scheduledTime": {
"type": "string",
"description": "Use ScheduledTime to synchronize lights. It's recommended that you asynchronously create tasks for each light that's scheduled to avoid blocking the main thread.",
"format": "date-time",
"nullable": true
}
},
"additionalProperties": false,
"description": "Represents a request to change the state of the light."
},
"LightStateModel": {
"type": "object",
"properties": {
"id": {
"type": "string",
"nullable": true
},
"name": {
"type": "string",
"nullable": true
},
"on": {
"type": "boolean",
"nullable": true
},
"brightness": {
"type": "integer",
"format": "int32",
"nullable": true
},
"hexColor": {
"type": "string",
"nullable": true
}
},
"additionalProperties": false
}
}
}
}
Ez a specifikáció mindent biztosít, amire az AI-nek szüksége van az API megértéséhez és az azzal való interakcióhoz. Az API két végpontot tartalmaz: az egyiket az összes fény lekéréséhez, a másikat pedig a fény állapotának módosításához. Emellett a következőket is biztosítja:
- A végpontok és paramétereik szemantikai leírása
- A paraméterek típusai
- A várt válaszok
Mivel az AI-ügynök megérti ezt a specifikációt, beépülő modulként hozzáadhatja az ügynökhöz.
A Szemantic Kernel támogatja az OpenAPI 2.0-s és 3.0-s verzióját, és a 3.1-es verzió specifikációinak figyelembe adásával a 3.0-s verzióra szeretné visszaminősíteni.
Borravaló
Ha rendelkezik meglévő OpenAPI-specifikációkkal, előfordulhat, hogy módosítania kell őket, hogy megkönnyítse az AI számára azok megértését. Előfordulhat például, hogy útmutatást kell adnia a leírásokban. További tippek az OpenAPI-specifikációk AI-baráttá alakításához: Tippek és trükkök az OpenAPI beépülő modulok hozzáadásához.
Az OpenAPI beépülő modul hozzáadása
Néhány sor kód megírásával hozzáadhatja az OpenAPI beépülő modult az ügynökéhez. A következő kódrészlet bemutatja, hogyan adhatja hozzá a light beépülő modult a fenti OpenAPI-specifikációból:
await kernel.ImportPluginFromOpenApiAsync(
pluginName: "lights",
uri: new Uri("https://example.com/v1/swagger.json"),
executionParameters: new OpenApiFunctionExecutionParameters()
{
// Determines whether payload parameter names are augmented with namespaces.
// Namespaces prevent naming conflicts by adding the parent parameter name
// as a prefix, separated by dots
EnablePayloadNamespacing = true
}
);
A Szemantic Kernel használatával openAPI beépülő modulokat adhat hozzá különböző forrásokból, például URL-címből, fájlból vagy streamből. Emellett a beépülő modulok létrehozhatóak egyszer, és több kernelpéldányban vagy -ügynökben újra felhasználhatók.
// Create the OpenAPI plugin from a local file somewhere at the root of the application
KernelPlugin plugin = await OpenApiKernelPluginFactory.CreateFromOpenApiAsync(
pluginName: "lights",
filePath: "path/to/lights.json"
);
// Add the plugin to the kernel
Kernel kernel = new Kernel();
kernel.Plugins.Add(plugin);
await kernel.add_plugin_from_openapi(
plugin_name="lights",
openapi_document_path="https://example.com/v1/swagger.json",
execution_settings=OpenAPIFunctionExecutionParameters(
# Determines whether payload parameter names are augmented with namespaces.
# Namespaces prevent naming conflicts by adding the parent parameter name
# as a prefix, separated by dots
enable_payload_namespacing=True,
),
)
String yaml = EmbeddedResourceLoader.readFile("petstore.yaml", ExamplePetstoreImporter.class);
KernelPlugin plugin = SemanticKernelOpenAPIImporter
.builder()
.withPluginName("petstore")
.withSchema(yaml)
.withServer("http://localhost:8090/api/v3")
.build();
Kernel kernel = ExampleOpenAPIParent.kernelBuilder()
.withPlugin(plugin)
.build();
Ezt követően használhatja a beépülő modult az ügynökében, mintha az natív lenne.
OpenAPI beépülő modulparaméterek kezelése
A Szemantic Kernel automatikusan kinyeri a metaadatokat – például nevet, leírást, típust és sémát az OpenAPI-dokumentumokban definiált összes paraméterhez.
Ezeket a metaadatokat az egyes OpenAPI-műveletek KernelFunction.Metadata.Parameters tulajdonságában tárolja a rendszer, és a függvényhívások megfelelő argumentumainak létrehozására vonatkozó kéréssel együtt az LLM-nek is megadja.
Alapértelmezés szerint az eredeti paraméternév meg van adva az LLM-nek, és a Szemantikus Kernel használja a megfelelő argumentum megkereséséhez az LLM által megadott argumentumok listájában. Előfordulhat azonban, hogy az OpenAPI beépülő modul több azonos nevű paraméterrel rendelkezik. A paraméter metaadatainak az LLM-hez való megadása zavart okozhat, ami megakadályozhatja, hogy az LLM létrehozza a függvényhívások megfelelő argumentumait.
Emellett mivel minden OpenAPI-művelethez létrejön egy kernelfüggvény, amely nem teszi lehetővé a nem egyedi paraméterneveket, az ilyen beépülő modul hozzáadása egyes műveletek elérhetetlenné válását eredményezheti. A nem egyedi paraméternevekkel rendelkező műveletek kimaradnak, és a rendszer naplózza a megfelelő figyelmeztetést. Még ha több azonos nevű paraméter is szerepelhet a kernelfüggvényben, ez kétértelműséghez vezethet az argumentumválasztási folyamatban.
Mindezeket figyelembe véve a Szemantic Kernel megoldást kínál a nem egyedi paraméternevekkel rendelkező beépülő modulok kezelésére. Ez a megoldás különösen akkor hasznos, ha magát az API-t nem lehet módosítani, akár külső szolgáltatás, akár örökölt rendszer miatt.
Az alábbi kódrészlet bemutatja, hogyan kezelhetők az OpenAPI beépülő modul nem egyedi paraméternevei. Ha a change_light_state műveletnek volt egy olyan paramétere, amelynek neve megegyezik a meglévő "id" paraméter nevével – pontosabban azért, hogy a jelenlegi "azonosító" mellett egy munkamenet-azonosítót is képviseljen, amely a fény azonosítóját jelöli – az alábbi módon kezelhető:
OpenApiDocumentParser parser = new();
using FileStream stream = File.OpenRead("path/to/lights.json");
// Parse the OpenAPI document
RestApiSpecification specification = await parser.ParseAsync(stream);
// Get the change_light_state operation
RestApiOperation operation = specification.Operations.Single(o => o.Id == "change_light_state");
// Set the 'lightId' argument name to the 'id' path parameter that represents the ID of the light
RestApiParameter idPathParameter = operation.Parameters.Single(p => p.Location == RestApiParameterLocation.Path && p.Name == "id");
idPathParameter.ArgumentName = "lightId";
// Set the 'sessionId' argument name to the 'id' header parameter that represents the session ID
RestApiParameter idHeaderParameter = operation.Parameters.Single(p => p.Location == RestApiParameterLocation.Header && p.Name == "id");
idHeaderParameter.ArgumentName = "sessionId";
// Import the transformed OpenAPI plugin specification
kernel.ImportPluginFromOpenApi(pluginName: "lights", specification: specification);
Ez a kódrészlet a OpenApiDocumentParser osztály használatával elemzi az OpenAPI-dokumentumot, és hozzáfér a dokumentumot képviselő RestApiSpecification modellobjektumhoz. Argumentumneveket rendel a paraméterekhez, és importálja az átalakított OpenAPI beépülő modul specifikációját a kernelbe. A Szemantikus Kernel az eredeti nevek helyett az LLM-nek adja meg az argumentumneveket, és a megfelelő argumentumok keresésére használja őket az LLM által megadott listában.
Fontos megjegyezni, hogy az OpenAPI-művelet meghívásakor az argumentumnevek nem az eredeti nevek helyett lesznek használva. A fenti példában az elérési út "id" paraméterét az LLM által a lightId argumentumhoz visszaadott érték váltja fel. Ugyanez vonatkozik az "id" fejlécparaméterre is; a rendszer a sessionId argumentum LLM által visszaadott értékét használja az "id" fejléc értékeként.
OpenAPI beépülő modulok adatcsomagjainak kezelése
Az OpenAPI beépülő modulok POST, PUT vagy PATCH műveletekkel módosíthatják a rendszer állapotát. Ezek a műveletek gyakran megkövetelik, hogy a kérelem csatolt adatokat tartalmazzon.
A Szemantic Kernel az adott forgatókönyvtől és API-követelményektől függően kínál néhány lehetőséget az OpenAPI beépülő modulok hasznos adatainak kezelésére.
Dinamikus hasznos teher kialakítás
A dinamikus hasznos adatszerkezet lehetővé teszi az OpenAPI-műveletek hasznos adatainak dinamikus létrehozását az LLM által biztosított hasznos adatséma és argumentumok alapján.
Ez a funkció alapértelmezés szerint engedélyezve van, de a EnableDynamicPayload tulajdonságot úgy lehet letiltani, hogy false-re állítjuk az OpenApiFunctionExecutionParameters objektumban az OpenAPI beépülő modul hozzáadásakor.
Vegyük például a change_light_state műveletet, amelyhez az alábbiak szerint strukturált hasznos adatra van szükség:
{
"isOn": true,
"hexColor": "#FF0000",
"brightness": 100,
"fadeDurationInMilliseconds": 500,
"scheduledTime": "2023-07-12T12:00:00Z"
}
A fény állapotának módosításához és a hasznos adattulajdonságok értékeinek lekéréséhez a Szemantic Kernel metaadatokat biztosít az LLM-nek a művelethez, hogy az okokat meg tudja indokolni:
{
"name":"lights-change-light-state",
"description": "Changes the state of a light.",
"parameters":[
{ "name": "id", "schema": {"type":"string", "description": "The ID of the light to change.", "format":"uuid"}},
{ "name": "isOn", "schema": { "type": "boolean", "description": "Specifies whether the light is turned on or off."}},
{ "name": "hexColor", "schema": { "type": "string", "description": "Specifies whether the light is turned on or off."}},
{ "name": "brightness", "schema": { "type":"string", "description":"The brightness level of the light.", "enum":["Low","Medium","High"]}},
{ "name": "fadeDurationInMilliseconds", "schema": { "type":"integer", "description":"Duration for the light to fade to the new state, in milliseconds.", "format":"int32"}},
{ "name": "scheduledTime", "schema": {"type":"string", "description":"The time at which the change should occur.", "format":"date-time"}},
]
}
Az LLM-hez a művelet metaadatainak megadása mellett a Szemantikus Kernel a következő lépéseket hajtja végre:
- Kezelje az OpenAPI-művelethez érkező LLM-hívást, és hozza létre a terhelést a séma alapján az LLM tulajdonságértékek felhasználásával.
- Küldje el a HTTP-kérést az API-nak a hasznos adatokkal együtt.
A dinamikus terhek felépítésének korlátai
A dinamikus hasznos teher építése a viszonylag egyszerű hasznos teherstruktúrákkal rendelkező API-k esetében a leghatékonyabb. Lehet, hogy nem működik megbízhatóan, vagy egyáltalán nem működik az olyan API-k hasznos adatai esetében, amelyek a következő jellemzőket mutatják:
- Nem egyedi tulajdonságnevekkel rendelkező adathelyek, a tulajdonságok helyétől függetlenül. Például két tulajdonság neve
id, az egyik a feladó objektum, a másik pedig a fogadó objektum -json { "sender": { "id": ... }, "receiver": { "id": ... }} - Azokat a hasznos adatsémákat, amelyek bármelyik kompozit kulcsszót használják:
oneOf,anyOf,allOf. - Hasznos adatséma rekurzív hivatkozásokkal. Például
json { "parent": { "child": { "$ref": "#parent" } } }
A nem egyedi tulajdonságnevekkel rendelkező hasznos adatok kezeléséhez fontolja meg a következő alternatívákat:
- Adjon meg egy egyedi argumentumnevet minden nem egyedi tulajdonsághoz az OpenAPI beépülő modulparaméterek kezelése szakaszban leírtakhoz hasonló módszerrel.
- Névterek használata az elnevezési ütközések elkerülése érdekében, amint az a hasznos adatnévterezéskövetkező szakaszában látható.
- Tiltsa le a dinamikus hasznos adatszerkezetet, és engedélyezze, hogy az LLM a sémája alapján hozza létre a hasznos adatokat a A hasznos adat paraméter szakaszban leírtak szerint.
Ha a hasznos adatok sémái a oneOf, anyOf, allOf összetett kulcsszavakat vagy rekurzív hivatkozásokat használnak, fontolja meg a dinamikus hasznos adatszerkezet letiltását, és engedélyezze az LLM számára, hogy a sémája alapján hozza létre a hasznos adatokat, amint az a A hasznos adat paraméter szakaszban található.
Megjegyzés a oneOf és anyOf kulcsszavakról
A anyOf és oneOf kulcsszavak feltételezik, hogy egy hasznos adat több séma által meghatározott tulajdonságokból állhat.
A anyOf kulcsszó lehetővé teszi, hogy a hasznos adatok egy vagy több sémában meghatározott tulajdonságokat tartalmazzanak, míg oneOf a hasznos adatok csak egy sémából származó tulajdonságokat tartalmazhatnak a sok megadott közül.
További információkért tekintse meg a Swagger dokumentációját a oneOf-on és az anyOf-on.
Mind a anyOf, mind a oneOf kulcsszavak alternatívákat kínálnak a hasznos teher szerkezetéhez, így lehetetlen megjósolni, hogy a hívó melyik alternatívát választja, amikor olyan műveleteket hív meg, amelyek ezeket a kulcsszavakat használják. Például nem állapítható meg előre, hogy a hívó egy Dog vagy Cat objektummal vagy egy Olyan objektummal indít-e műveletet, amely a anyOf és oneOf a példákban leírt PetByAge- és PetByType-sémák néhány vagy talán összes tulajdonságából áll.
Ennek eredményeképpen, mivel a Szemantikai Kernel nem tud előre ismert paramétereket használni egy beépülő modulfüggvény létrehozásához az ilyen műveletekhez, a Szemantikai Kernel létrehoz egy függvényt, amelynek csak egy hasznos adat paramétere van, egy sémával az adott műveletből, amely számos lehetséges alternatívát ír le, és a hasznos adat létrehozását átruházza a művelet hívójára: az LLM-re vagy a hívási kódra, amelynek minden szükséges környezeti adattal rendelkeznie kell ahhoz, hogy tudja, melyik elérhető alternatívával hívja meg a függvényt.
Hasznos teher névtérképzés
A payload namespacing segít megelőzni az elnevezési ütközéseket, amelyek az OpenAPI plugin payloadok nem egyedi tulajdonságnevei miatt fordulhatnak elő.
Ha engedélyezve van a névkészítés, a Szemantic Kernel openAPI-művelet metaadatokat biztosít az LLM-nek, amelyek kiterjesztett tulajdonságneveket tartalmaznak. Ezek a kiterjesztett nevek úgy jönnek létre, hogy a szülőtulajdonság nevét egy ponttal elválasztott előtagként hozzáadják a gyermektulajdonságok neveihez.
Ha például a change_light_state művelet beágyazott offTimer objektumot tartalmazott egy scheduledTime tulajdonsággal:
{
"isOn": true,
"hexColor": "#FF0000",
"brightness": 100,
"fadeDurationInMilliseconds": 500,
"scheduledTime": "2023-07-12T12:00:00Z",
"offTimer": {
"scheduledTime": "2023-07-12T12:00:00Z"
}
}
A Szemantikus Kernel metaadatokat adott volna meg az LLM-nek a művelethez, amely a következő tulajdonságneveket tartalmazza:
{
"name":"lights-change-light-state",
"description": "Changes the state of a light.",
"parameters":[
{ "name": "id", "schema": {"type":"string", "description": "The ID of the light to change.", "format":"uuid"}},
{ "name": "isOn", "schema": { "type": "boolean", "description": "Specifies whether the light is turned on or off."}},
{ "name": "hexColor", "schema": { "type": "string", "description": "Specifies whether the light is turned on or off."}},
{ "name": "brightness", "schema": { "type":"string", "description":"The brightness level of the light.", "enum":["Low","Medium","High"]}},
{ "name": "fadeDurationInMilliseconds", "schema": { "type":"integer", "description":"Duration for the light to fade to the new state, in milliseconds.", "format":"int32"}},
{ "name": "scheduledTime", "schema": {"type":"string", "description":"The time at which the change should occur.", "format":"date-time"}},
{ "name": "offTimer.scheduledTime", "schema": {"type":"string", "description":"The time at which the device will be turned off.", "format":"date-time"}},
]
}
Amellett, hogy kiterjesztett tulajdonságnevekkel rendelkező műveleti metaadatokat ad meg az LLM-nek, a Szemantic Kernel a következő lépéseket hajtja végre:
- Kezelje az OpenAPI-műveletet kezdeményező LLM-hívást, és keresse meg a megfelelő argumentumokat az LLM által a hasznos adatban szereplő összes tulajdonsághoz, használja a bővített tulajdonságneveket, és szükség esetén térjen vissza az eredeti tulajdonságnevekre.
- Alkossa meg az adatcsomagot az eredeti tulajdonságnevek kulcsként való felhasználásával és a feloldott argumentumok értékként való megadásával.
- Küldje el az API-nak a HTTP-kérést a létrehozott adatcsomaggal.
Alapértelmezés szerint a csomag névterezési opció le van tiltva. Ha OpenAPI beépülő modult adunk hozzá, a EnablePayloadNamespacing tulajdonságot úgy engedélyezhetjük, hogy true értéket állítunk be az OpenApiFunctionExecutionParameters objektumban.
await kernel.ImportPluginFromOpenApiAsync(
pluginName: "lights",
uri: new Uri("https://example.com/v1/swagger.json"),
executionParameters: new OpenApiFunctionExecutionParameters()
{
EnableDynamicPayload = true, // Enable dynamic payload construction. This is enabled by default.
EnablePayloadNamespacing = true // Enable payload namespacing
});
Jegyzet
A EnablePayloadNamespace opció csak akkor érvényesül, ha a dinamikus adatcsomag felépítés is engedélyezve van; egyébként nincs hatása.
A teher paraméter
A szemantikus kernel képes dolgozni az LLM által a payload paraméterrel létrehozott adatcsomagokkal. Ez akkor hasznos, ha a hasznos adatséma összetett, és nem egyedi tulajdonságneveket tartalmaz, ezért a Szemantic Kernel nem teszi lehetővé a hasznos adatok dinamikus összeállítását.
Ilyen esetekben Ön az LLM képességeire fog támaszkodni, hogy megértse a sémát, és érvényes adatcsomagot hozzon létre. A legutóbbi modellek, például a gpt-4o hatékonyak az érvényes JSON-hasznos adatok létrehozásában.
A payload paraméter engedélyezéséhez állítsa a EnableDynamicPayload tulajdonságot false-re az OpenApiFunctionExecutionParameters objektumban, amikor OpenAPI beépülő modult ad hozzá.
await kernel.ImportPluginFromOpenApiAsync(
pluginName: "lights",
uri: new Uri("https://example.com/v1/swagger.json"),
executionParameters: new OpenApiFunctionExecutionParameters()
{
EnableDynamicPayload = false, // Disable dynamic payload construction
});
Ha a hasznos adat paraméter engedélyezve van, a Szemantic Kernel metaadatokat biztosít az LLM számára a művelethez, amely sémákat tartalmaz a hasznos adatokhoz és content_type paraméterekhez, lehetővé téve, hogy az LLM megértse a hasznos adatstruktúrát, és ennek megfelelően hozza létre:
{
"name": "payload",
"schema":
{
"type": "object",
"properties": {
"isOn": {
"type": "boolean",
"description": "Specifies whether the light is turned on or off."
},
"hexColor": {
"type": "string",
"description": "The hex color code for the light.",
},
"brightness": {
"enum": ["Low", "Medium", "High"],
"type": "string",
"description": "The brightness level of the light."
},
"fadeDurationInMilliseconds": {
"type": "integer",
"description": "Duration for the light to fade to the new state, in milliseconds.",
"format": "int32"
},
"scheduledTime": {
"type": "string",
"description": "The time at which the change should occur.",
"format": "date-time"
}
},
"additionalProperties": false,
"description": "Represents a request to change the state of the light."
},
{
"name": "content_type",
"schema":
{
"type": "string",
"description": "Content type of REST API request body."
}
}
}
A szemantikus kernel amellett, hogy az LLM-nek megadja a művelet metaadatait a payload és a tartalomtípus paraméterek sémájával, a következő lépéseket hajtja végre:
- Kezelje az OpenAPI-műveletet kezdeményező LLM-hívást, és az LLM által megadott argumentumokat használja a terhelési adatokhoz és a content_type paraméterekhez.
- Küldje el a HTTP-kérést az API-nak a megadott hasznos adatokkal és tartalomtípussal.
Kiszolgáló alap URL-címe
A szemantikus Kernel OpenAPI beépülő moduljai alap URL-címet igényelnek, amely az API-kérések készítésekor a végpont elérési útjainak előpendítésére szolgál. Ez az alap URL-cím megadható az OpenAPI-dokumentumban, implicit módon lekérte a dokumentumot egy URL-címről, vagy megadható, amikor hozzáadja a beépülő modult a kernelhez.
OpenAPI-dokumentumban megadott URL-cím
Az OpenAPI v2-dokumentumok a kiszolgáló URL-címét a schemes, hostés basePath mezők használatával határozzák meg:
{
"swagger": "2.0",
"host": "example.com",
"basePath": "/v1",
"schemes": ["https"]
...
}
A Szemantikus Kernel összeállítja a kiszolgáló URL-címét https://example.com/v1formában.
Ezzel szemben az OpenAPI v3-dokumentumok a servers mező használatával határozzák meg a kiszolgáló URL-címét:
{
"openapi": "3.0.1",
"servers": [
{
"url": "https://example.com/v1"
}
],
...
}
A szemantikus kernel a dokumentumban megadott első kiszolgálói URL-címet használja alap URL-címként: https://example.com/v1.
Az OpenAPI v3 paraméteres kiszolgálói URL-címeket is lehetővé tesz a kapcsos zárójelek által jelzett változók használatával:
{
"openapi": "3.0.1",
"servers": [
{
"url": "https://{environment}.example.com/v1",
"variables": {
"environment": {
"default": "prod"
}
}
}
],
...
}
Ebben az esetben a Szemantikus kernel a változó helyőrzője helyett vagy a változó argumentumaként megadott értéket, vagy az alapértelmezett értéket adja meg, ha nincs megadva argumentum, ami az URL-címet eredményezi: https://prod.example.com/v1.
Ha az OpenAPI-dokumentum nem ad meg kiszolgálói URL-címet, a Szemantic Kernel annak a kiszolgálónak az alap URL-címét fogja használni, amelyből az OpenAPI-dokumentum betöltődött:
await kernel.ImportPluginFromOpenApiAsync(pluginName: "lights", uri: new Uri("https://api-host.com/swagger.json"));
Az alap URL-cím https://api-host.comlesz.
A kiszolgáló URL-címének felülírása
Bizonyos esetekben előfordulhat, hogy az OpenAPI-dokumentumban megadott kiszolgálói URL-cím vagy a kiszolgáló, amelyről a dokumentumot betöltötték, nem feltétlenül alkalmas az OpenAPI beépülő modult érintő használati esetekre.
A Szemantic Kernel lehetővé teszi a kiszolgáló URL-címének felülbírálását egy egyéni alap URL-cím megadásával, amikor hozzáadja az OpenAPI beépülő modult a kernelhez:
await kernel.ImportPluginFromOpenApiAsync(
pluginName: "lights",
uri: new Uri("https://example.com/v1/swagger.json"),
executionParameters: new OpenApiFunctionExecutionParameters()
{
ServerUrlOverride = new Uri("https://custom-server.com/v1")
});
Ebben a példában az alap URL-cím https://custom-server.com/v1lesz, felülírva az OpenAPI-dokumentumban megadott kiszolgálói URL-címet, valamint azt a kiszolgálói URL-címet, amelyből a dokumentum betöltődött.
Hitelesítés
A REST API-k többsége hitelesítést igényel az erőforrások eléréséhez. A Szemantic Kernel olyan mechanizmust biztosít, amely lehetővé teszi az OpenAPI beépülő modulok által megkövetelt különböző hitelesítési módszerek integrálását.
Ez a mechanizmus egy hitelesítési visszahívási függvényre támaszkodik, amelyet az egyes API-kérések előtt hívunk meg. Ez a visszahívási függvény hozzáfér a HttpRequestMessage objektumhoz, amely az API-nak küldött HTTP-kérést jelöli. Ezzel az objektummal hitelesítési hitelesítő adatokat adhat a kéréshez. A hitelesítő adatok fejlécként, lekérdezési paraméterként vagy a kérelem törzsében is hozzáadhatók az API által használt hitelesítési módszertől függően.
Ezt a visszahívási függvényt regisztrálnia kell, amikor hozzáadja az OpenAPI beépülő modult a kernelhez. Az alábbi kódrészlet bemutatja, hogyan regisztrálhatja a kérések hitelesítéséhez:
static Task AuthenticateRequestAsyncCallback(HttpRequestMessage request, CancellationToken cancellationToken = default)
{
// Best Practices:
// * Store sensitive information securely, using environment variables or secure configuration management systems.
// * Avoid hardcoding sensitive information directly in your source code.
// * Regularly rotate tokens and API keys, and revoke any that are no longer in use.
// * Use HTTPS to encrypt the transmission of any sensitive information to prevent interception.
// Example of Bearer Token Authentication
// string token = "your_access_token";
// request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
// Example of API Key Authentication
// string apiKey = "your_api_key";
// request.Headers.Add("X-API-Key", apiKey);
return Task.CompletedTask;
}
await kernel.ImportPluginFromOpenApiAsync(
pluginName: "lights",
uri: new Uri("https://example.com/v1/swagger.json"),
executionParameters: new OpenApiFunctionExecutionParameters()
{
AuthCallback = AuthenticateRequestAsyncCallback
});
Az API által támogatott hitelesítési sémák részleteihez dinamikus hozzáférést igénylő összetettebb hitelesítési forgatókönyvek esetén dokumentum- és műveleti metaadatokkal szerezheti be ezeket az információkat. További információ: Dokumentum- és művelet metaadatai.
Választartalmak olvasásának testreszabása
A Szemantic Kernel beépített mechanizmussal rendelkezik az OpenAPI beépülő modulokBÓL érkező HTTP-válaszok tartalmának olvasásához és a megfelelő .NET-adattípusokká alakításához. A képválaszok például bájttömbként olvashatók, míg egy JSON- vagy XML-válasz sztringként olvasható.
Lehetnek azonban olyan esetek, amikor a beépített mechanizmus nem elegendő az igényeinek. Ha például a válasz egy nagy JSON-objektum vagy kép, amelyet streamként kell olvasni ahhoz, hogy egy másik API bemeneteként lehessen megadni. Ilyen esetekben a választartalmak sztringként vagy bájttömbként való olvasása, majd streamké alakítása nem hatékony lehet, és teljesítményproblémákhoz vezethet. Ennek megoldásához a Szemantic Kernel egyéni tartalomolvasóval teszi lehetővé a választartalmak olvasásának testreszabását:
private static async Task<object?> ReadHttpResponseContentAsync(HttpResponseContentReaderContext context, CancellationToken cancellationToken)
{
// Read JSON content as a stream instead of as a string, which is the default behavior.
if (context.Response.Content.Headers.ContentType?.MediaType == "application/json")
{
return await context.Response.Content.ReadAsStreamAsync(cancellationToken);
}
// HTTP request and response properties can be used to determine how to read the content.
if (context.Request.Headers.Contains("x-stream"))
{
return await context.Response.Content.ReadAsStreamAsync(cancellationToken);
}
// Return null to indicate that any other HTTP content not handled above should be read by the default reader.
return null;
}
await kernel.ImportPluginFromOpenApiAsync(
pluginName: "lights",
uri: new Uri("https://example.com/v1/swagger.json"),
executionParameters: new OpenApiFunctionExecutionParameters()
{
HttpResponseContentReader = ReadHttpResponseContentAsync
});
Ebben a példában a ReadHttpResponseContentAsync metódus streamként olvassa be a HTTP-választartalmat, ha a tartalomtípus application/json, vagy ha a kérelem egyéni fejlécet x-streamtartalmaz. A metódus minden más tartalomtípushoz null ad vissza, ami azt jelzi, hogy az alapértelmezett tartalomolvasót kell használni.
Dokumentum- és művelet metaadatai
A Szemantic Kernel kinyeri az OpenAPI dokumentum- és művelet metaadatait, beleértve az API-információkat, a biztonsági sémákat, a műveletazonosítót, a leírást, a paraméter metaadatait és még sok mást.
A KernelFunction.Metadata.AdditionalParameters tulajdonságon keresztül biztosít hozzáférést ezekhez az információkhoz. Ezek a metaadatok olyan esetekben lehetnek hasznosak, amikor további információkra van szükség az API-ról vagy a műveletről, például hitelesítési célokra:
static async Task AuthenticateRequestAsyncCallbackAsync(HttpRequestMessage request, CancellationToken cancellationToken = default)
{
// Get the function context
if (request.Options.TryGetValue(OpenApiKernelFunctionContext.KernelFunctionContextKey, out OpenApiKernelFunctionContext? functionContext))
{
// Get the operation metadata
if (functionContext!.Function!.Metadata.AdditionalProperties["operation"] is RestApiOperation operation)
{
// Handle API key-based authentication
IEnumerable<KeyValuePair<RestApiSecurityScheme, IList<string>>> apiKeySchemes = operation.SecurityRequirements.Select(requirement => requirement.FirstOrDefault(schema => schema.Key.SecuritySchemeType == "apiKey"));
if (apiKeySchemes.Any())
{
(RestApiSecurityScheme scheme, IList<string> scopes) = apiKeySchemes.First();
// Get the API key for the scheme and scopes from your app identity provider
var apiKey = await this.identityProvider.GetApiKeyAsync(scheme, scopes);
// Add the API key to the request headers
if (scheme.In == RestApiParameterLocation.Header)
{
request.Headers.Add(scheme.Name, apiKey);
}
else if (scheme.In == RestApiParameterLocation.Query)
{
request.RequestUri = new Uri($"{request.RequestUri}?{scheme.Name}={apiKey}");
}
else
{
throw new NotSupportedException($"API key location '{scheme.In}' is not supported.");
}
}
// Handle other authentication types like Basic, Bearer, OAuth2, etc. For more information, see https://swagger.io/docs/specification/v3_0/authentication/
}
}
}
// Import the transformed OpenAPI plugin specification
var plugin = kernel.ImportPluginFromOpenApi(
pluginName: "lights",
uri: new Uri("https://example.com/v1/swagger.json"),
new OpenApiFunctionExecutionParameters()
{
AuthCallback = AuthenticateRequestAsyncCallbackAsync
});
await kernel.InvokePromptAsync("Test");
Ebben a példában a AuthenticateRequestAsyncCallbackAsync metódus beolvassa a művelet metaadatait a függvénykörnyezetből, és kinyeri a művelet biztonsági követelményeit a hitelesítési séma meghatározásához. Ezután lekéri a sémához és a hatókörökhöz tartozó API-kulcsot az alkalmazás-identitásszolgáltatótól, és hozzáadja a kérés fejlécekhez vagy lekérdezési paraméterekhez.
Az alábbi táblázat a KernelFunction.Metadata.AdditionalParameters szótárban elérhető metaadatokat sorolja fel:
| Kulcs | Típus | Leírás |
|---|---|---|
| információ | RestApiInfo |
API-információk, beleértve a címet, a leírást és a verziót. |
| művelet | RestApiOperation |
API-műveletek részletei, például azonosító, leírás, elérési út, metódus stb. |
| biztonság | IList<RestApiSecurityRequirement> |
API biztonsági követelmények – típus, név, be stb. |
Tippek és trükkök OpenAPI beépülő modulok hozzáadásához
Mivel az OpenAPI-specifikációk általában emberek számára vannak kialakítva, előfordulhat, hogy módosítania kell őket, hogy könnyebben megérthesse az AI-t. Az alábbiakban néhány tippet és trükköt talál, amelyek segítenek ebben:
| Ajánlás | Leírás |
|---|---|
| Verziókezelje az API-specifikációkat | Ahelyett, hogy élő API-specifikációra mutatna, fontolja meg a Swagger-fájl rögzítését és verziókezelését. Ez lehetővé teszi az AI-kutatók számára az AI-ügynök által használt API-specifikáció tesztelését (és módosítását) anélkül, hogy az hatással van az élő API-ra, és fordítva. |
| Végpontok számának korlátozása | Próbálja meg korlátozni a végpontok számát az API-ban. A hasonló funkciók összevonása egyetlen végpontba opcionális paraméterekkel az összetettség csökkentése érdekében. |
| Leíró nevek használata végpontokhoz és paraméterekhez | Győződjön meg arról, hogy a végpontok és paraméterek neve leíró és magától értetődő. Ez segít az AI-nek megérteni a céljukat anélkül, hogy alapos magyarázatra van szüksége. |
| Konzisztens elnevezési konvenciók használata | Tartsa fenn az API-ban a konzisztens elnevezési szabályokat. Ez csökkenti a félreértéseket, és segít az AI-nek könnyebben elsajátítani és előrejelezni az API szerkezetét. |
| Az API-specifikációk egyszerűsítése | Az OpenAPI-specifikációk gyakran nagyon részletesek, és sok olyan információt tartalmaznak, amelyek nem szükségesek ahhoz, hogy az AI-ügynök segítse a felhasználót. Minél egyszerűbb az API, annál kevesebb token szükséges a leírásához, és annál kevesebb token szükséges az AI általi kérésküldéshez. |
| Sztringparaméterek elkerülése | Ha lehetséges, kerülje a sztringparaméterek használatát az API-ban. Ehelyett használjon konkrétabb típusokat, például egész számokat, logikai értékeket vagy enumerációkat. Ez segít az AI-nek jobban megérteni az API-t. |
| Példák megadása a leírásokban | Amikor az emberek Swagger-fájlokat használnak, általában a Swagger felhasználói felületén tesztelhetik az API-t, amely mintakéréseket és válaszokat tartalmaz. Mivel az AI-ügynök ezt nem tudja megtenni, érdemes lehet példákat megadni a paraméterek leírásában. |
| Leírások egyéb végpontjaira való hivatkozás | Az AI-k gyakran összekeverik a hasonló végpontokat. Annak érdekében, hogy az AI különbséget tegyen a végpontok között, érdemes lehet más végpontokra hivatkozni a leírásokban. Tegyük fel például, hogy "Ez a végpont hasonló a get_all_lights végponthoz, de csak egyetlen fényt ad vissza." |
| Adjon meg hasznos hibaüzeneteket | Bár nem tartozik az OpenAPI specifikációjához, érdemes lehet olyan hibaüzeneteket küldeni, amelyek segítenek az AI önhibájának javításában. Ha például egy felhasználó érvénytelen azonosítót ad meg, adjon meg egy hibaüzenetet, amely arra utal, hogy az AI-ügynök a megfelelő azonosítót kéri le a get_all_lights végpontról. |
Következő lépések
Most, hogy már tudja, hogyan hozhat létre beépülő modult, megtanulhatja, hogyan használhatja őket az AI-ügynökével. A beépülő modulokhoz hozzáadott függvények típusától függően különböző mintákat kell követnie. A lekérési függvényekhez lásd a a lekérési függvények cikket. Feladatautomatizálási függvények esetén tekintse meg a a feladatautomatizálási függvények használatával cikket.
Tudnivalók a lekérési függvények használatáról