Udhëzues për thirrjen e funksionit të AI Edge për Android

SDK e thirrjes së funksionit AI Edge (FC SDK) është një bibliotekë që u mundëson zhvilluesve të përdorin thirrjet funksionale me LLM në pajisje. Thirrja e funksionit ju lejon të lidhni modelet me mjete të jashtme dhe API, duke u mundësuar modeleve të thërrasin funksione specifike me parametrat e nevojshëm për të ekzekutuar veprime në botën reale.

Në vend që të gjenerojë thjesht tekst, një LLM duke përdorur FC SDK mund të gjenerojë një thirrje të strukturuar për një funksion që ekzekuton një veprim, si kërkimi i informacionit të përditësuar, vendosja e alarmeve ose rezervimi.

Ky udhëzues ju udhëzon në një fillim të shpejtë bazë për të shtuar API-në e konkluzionit LLM me FC SDK në një aplikacion Android. Ky udhëzues fokusohet në shtimin e aftësive të thirrjes së funksionit në një LLM në pajisje. Për më shumë informacion mbi përdorimin e LLM Inference API, shihni udhëzuesin LLM Inference për Android .

Fillimi i shpejtë

Përdorni hapat e mëposhtëm për të përdorur FC SDK në aplikacionin tuaj Android. Ky fillim i shpejtë përdor LLM Inference API me Hammer 2.1 (1.5B) . LLM Inference API është optimizuar për pajisjet Android të nivelit të lartë, si Pixel 8 dhe Samsung S23 ose më të reja, dhe nuk mbështet me besueshmëri emuluesit e pajisjeve.

Shto varësi

FC SDK përdor bibliotekën com.google.ai.edge.localagents:localagents-fc dhe LLM Inference API përdor bibliotekën com.google.mediapipe:tasks-genai . Shtoni të dyja varësitë në skedarin build.gradle të aplikacionit tuaj Android:

dependencies {
    implementation 'com.google.mediapipe:tasks-genai:0.10.24'
    implementation 'com.google.ai.edge.localagents:localagents-fc:0.1.0'
}

Për pajisjet me Android 12 (API 31) ose më të lartë, shtoni varësinë origjinale të bibliotekës OpenCL. Për më shumë informacion, shihni dokumentacionin në etiketën uses-native-library .

Shtoni etiketat e mëposhtme uses-native-library në skedarin AndroidManifest.xml :

<uses-native-library android:name="libOpenCL.so" android:required="false"/>
<uses-native-library android:name="libOpenCL-car.so" android:required="false"/>
<uses-native-library android:name="libOpenCL-pixel.so" android:required="false"/>

Shkarkoni një model

Shkarkoni Hammer 1B në një format të kuantizuar 8-bit nga Hugging Face . Për më shumë informacion mbi modelet e disponueshme, shihni dokumentacionin e Modeleve .

Shtyni përmbajtjen e dosjes hammer2.1_1.5b_q8_ekv4096.task në pajisjen Android.

$ adb shell rm -r /data/local/tmp/llm/ # Remove any previously loaded models
$ adb shell mkdir -p /data/local/tmp/llm/
$ adb push hammer2.1_1.5b_q8_ekv4096.task /data/local/tmp/llm/hammer2.1_1.5b_q8_ekv4096.task

Deklaroni përkufizimet e funksioneve

Përcaktoni funksionet që do t'i vihen në dispozicion modelit. Për të ilustruar procesin, ky fillim i shpejtë përfshin dy funksione si metoda statike që kthejnë përgjigje të koduara. Një implementim më praktik do të përcaktonte funksione që thërrasin një API REST ose marrin informacion nga një bazë të dhënash.

Më poshtë përcakton funksionet getWeather dhe getTime :

class ToolsForLlm {
    public static String getWeather(String location) {
        return "Cloudy, 56°F";
    }

    public static String getTime(String timezone) {
        return "7:00 PM " + timezone;
    }

    private ToolsForLlm() {}
}

Use FunctionDeclaration to describe each function, giving each a name and description, and specifying the types. Kjo informon modelin se çfarë bëjnë funksionet dhe kur duhet bërë thirrje funksioni.

var getWeather = FunctionDeclaration.newBuilder()
    .setName("getWeather")
    .setDescription("Returns the weather conditions at a location.")
    .setParameters(
        Schema.newBuilder()
            .setType(Type.OBJECT)
            .putProperties(
                "location",
                Schema.newBuilder()
                    .setType(Type.STRING)
                    .setDescription("The location for the weather report.")
                    .build())
            .build())
    .build();
var getTime = FunctionDeclaration.newBuilder()
    .setName("getTime")
    .setDescription("Returns the current time in the given timezone.")

    .setParameters(
        Schema.newBuilder()
            .setType(Type.OBJECT)
            .putProperties(
                "timezone",
                Schema.newBuilder()
                    .setType(Type.STRING)
                    .setDescription("The timezone to get the time from.")
                    .build())
            .build())
    .build();

Shtoni deklaratat e funksionit në një objekt Tool :

var tool = Tool.newBuilder()
    .addFunctionDeclarations(getWeather)
    .addFunctionDeclarations(getTime)
    .build();

Krijo fundin e përfundimit

Krijoni një bazë konkluzionesh duke përdorur LLM Inference API dhe kaloni atë një objekt formatues për modelin tuaj. Formatuesi FC SDK ( ModelFormatter ) vepron edhe si formatues edhe si analizues. Meqenëse ky fillim i shpejtë përdor Gemma-3 1B, ne do të përdorim GemmaFormatter :

var llmInferenceOptions = LlmInferenceOptions.builder()
    .setModelPath(modelFile.getAbsolutePath())
    .build();
var llmInference = LlmInference.createFromOptions(context, llmInferenceOptions);
var llmInferenceBackend = new llmInferenceBackend(llmInference, new GemmaFormatter());

Për më shumë informacion, shihni opsionet e konfigurimit të LLM Inference .

Instantoni modelin

Përdorni objektin GenerativeModel për të lidhur fundin e përfundimit, kërkesën e sistemit dhe mjetet. Ne tashmë kemi fundin e përfundimit dhe mjetet, kështu që na duhet vetëm të krijojmë kërkesën e sistemit:

var systemInstruction = Content.newBuilder()
      .setRole("system")
      .addParts(Part.newBuilder().setText("You are a helpful assistant."))
      .build();

Instantoni modelin me GenerativeModel :

var generativeModel = new GenerativeModel(
    llmInferenceBackend,
    systemInstruction,
    List.of(tool),
)

Filloni një seancë bisede

Për thjeshtësi, ky fillim i shpejtë fillon një seancë të vetme bisede. Ju gjithashtu mund të krijoni seanca të shumta, të pavarura.

Duke përdorur shembullin e ri të GenerativeModel , filloni një seancë bisede:

var chat = generativeModel.startChat();

Dërgoni kërkesat tek modeli përmes seancës së bisedës, duke përdorur metodën sendMessage :

var response = chat.sendMessage("How's the weather in San Francisco?");

Analizoni përgjigjen e modelit

Pasi t'i kalojë një kërkesë modelit, aplikacioni duhet të ekzaminojë përgjigjen për të përcaktuar nëse do të bëjë një thirrje funksioni ose do të nxjerrë tekst në gjuhë natyrale.

// Extract the model's message from the response.
var message = response.getCandidates(0).getContent().getParts(0);

// If the message contains a function call, execute the function.
if (message.hasFunctionCall()) {
  var functionCall = message.getFunctionCall();
  var args = functionCall.getArgs().getFieldsMap();
  var result = null;

  // Call the appropriate function.
  switch (functionCall.getName()) {
    case "getWeather":
      result = ToolsForLlm.getWeather(args.get("location").getStringValue());
      break;
    case "getTime":
      result = ToolsForLlm.getWeather(args.get("timezone").getStringValue());
      break;
    default:
      throw new Exception("Function does not exist:" + functionCall.getName());
  }
  // Return the result of the function call to the model.
  var functionResponse =
      FunctionResponse.newBuilder()
          .setName(functionCall.getName())
          .setResponse(
              Struct.newBuilder()
                  .putFields("result", Value.newBuilder().setStringValue(result).build()))
          .build();
  var response = chat.sendMessage(functionResponse);
} else if (message.hasText()) {
  Log.i(message.getText());
}

Kodi i mostrës është një zbatim tepër i thjeshtuar. Për më shumë informacion se si një aplikacion mund të shqyrtojë përgjigjet e modelit, shihni Formatimi dhe analizimi .

Si funksionon

Ky seksion ofron më shumë informacion të thelluar mbi konceptet dhe komponentët thelbësorë të SDK-së së thirrjes së funksionit për Android.

Modelet

Funksioni i thirrjes SDK kërkon një model me një formatues dhe analizues. FC SDK përmban një formatues dhe analizues të integruar për modelet e mëposhtme:

  • Gemma : përdorni GemmaFormatter .
  • Llama : përdorni LlamaFormatter .
  • Hammer : përdorni HammerFormatter .

Për të përdorur një model tjetër me FC SDK, duhet të zhvilloni formatuesin dhe analizuesin tuaj që është në përputhje me API-në e konkluzionit LLM.

Formatimi dhe analizimi

Një pjesë kryesore e mbështetjes për thirrjen e funksionit është formatimi i kërkesave dhe analizimi i daljes së modelit. Ndërsa këto janë dy procese të veçanta, FC SDK trajton si formatimin ashtu edhe analizimin me ndërfaqen ModelFormatter .

Formatuesi është përgjegjës për konvertimin e deklaratave të funksioneve të strukturuara në tekst, formatimin e përgjigjeve të funksionit dhe futjen e shenjave për të treguar fillimin dhe fundin e kthesave të bisedës, si dhe rolet e atyre kthesave (p.sh. "përdorues", "model").

Analizuesi është përgjegjës për zbulimin nëse përgjigja e modelit përmban një thirrje funksioni. Nëse analizuesi zbulon një thirrje funksioni, ai e analizon atë në një lloj të dhënash të strukturuar. Përndryshe, ai e trajton tekstin si përgjigje të gjuhës natyrore.

Dekodim i kufizuar

Dekodimi i kufizuar është një teknikë që drejton gjenerimin e prodhimit të LLM-ve për t'u siguruar që ai t'i përmbahet një formati të strukturuar të paracaktuar, siç janë objektet JSON ose thirrjet e funksionit Python. Duke zbatuar këto kufizime, modeli formaton rezultatet e tij në një mënyrë që përputhet me funksionet e paracaktuara dhe llojet e tyre përkatëse të parametrave.

Për të aktivizuar dekodimin e kufizuar, përcaktoni kufizimet në një objekt ConstraintOptions dhe thirrni metodën enableConstraint të një shembulli ChatSession . Kur aktivizohet, ky kufizim do të kufizojë përgjigjen që të përfshijë vetëm mjetet e lidhura me GenerativeModel .

Shembulli i mëposhtëm tregon se si të konfiguroni dekodimin e kufizuar për të kufizuar përgjigjen ndaj thirrjeve të veglave. Ai kufizon thirrjen e veglës që të fillojë me parashtesën ```tool_code\n dhe të përfundojë me prapashtesën \n``` .

ConstraintOptions constraintOptions = ConstraintOptions.newBuilder()
  .setToolCallOnly( ConstraintOptions.ToolCallOnly.newBuilder()
  .setConstraintPrefix("```tool_code\n")
  .setConstraintSuffix("\n```"))
  .build();
chatSession.enableConstraint(constraintOptions);

Për të çaktivizuar kufizimin aktiv brenda të njëjtit sesion, përdorni metodën disableConstraint :

chatSession.disableConstraint();