AI Edge Function Calling SDK (FC SDK) คือไลบรารีที่ช่วยให้นักพัฒนาซอฟต์แวร์ ใช้การเรียกใช้ฟังก์ชันกับ LLM บนอุปกรณ์ได้ การเรียกใช้ฟังก์ชันช่วยให้คุณเชื่อมต่อโมเดลกับเครื่องมือและ API ภายนอกได้ ซึ่งจะช่วยให้โมเดลเรียกใช้ฟังก์ชันที่เฉพาะเจาะจงพร้อมพารามิเตอร์ที่จำเป็นเพื่อดำเนินการในโลกแห่งความจริงได้
LLM ที่ใช้ FC SDK ไม่ได้สร้างข้อความเท่านั้น แต่ยังสร้างการเรียกฟังก์ชันที่มีโครงสร้างซึ่งดำเนินการ เช่น ค้นหาข้อมูลล่าสุด ตั้งปลุก หรือจอง
คู่มือนี้จะแนะนำการเริ่มต้นใช้งานพื้นฐานอย่างรวดเร็วเพื่อเพิ่ม LLM Inference API ด้วย FC SDK ลงในแอปพลิเคชัน Android คู่มือนี้มุ่งเน้นที่การเพิ่มความสามารถในการเรียกใช้ฟังก์ชัน ไปยัง LLM ในอุปกรณ์ ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ LLM Inference API ได้ที่คู่มือ LLM Inference สำหรับ Android
คู่มือเริ่มใช้งานฉบับย่อ
ทำตามขั้นตอนต่อไปนี้เพื่อใช้ FC SDK ในแอปพลิเคชัน Android คู่มือฉบับย่อนี้ใช้ LLM Inference API กับ Hammer 2.1 (1.5 พันล้าน) API การอนุมาน LLM ได้รับการเพิ่มประสิทธิภาพสำหรับอุปกรณ์ Android ระดับไฮเอนด์ เช่น Pixel 8 และ Samsung S23 ขึ้นไป และไม่รองรับโปรแกรมจำลองอุปกรณ์อย่างน่าเชื่อถือ
เพิ่มทรัพยากร Dependency
FC SDK ใช้ไลบรารี com.google.ai.edge.localagents:localagents-fc และ
LLM Inference API ใช้ไลบรารี com.google.mediapipe:tasks-genai เพิ่มทรัพยากร Dependency ทั้ง 2 รายการลงในไฟล์ build.gradle ของแอป Android
dependencies {
implementation 'com.google.mediapipe:tasks-genai:0.10.24'
implementation 'com.google.ai.edge.localagents:localagents-fc:0.1.0'
}
สำหรับอุปกรณ์ที่ใช้ Android 12 (API 31) ขึ้นไป ให้เพิ่มการอ้างอิงไลบรารี OpenCL แบบเนทีฟ
ดูข้อมูลเพิ่มเติมได้ในเอกสารประกอบเกี่ยวกับแท็ก
uses-native-library
เพิ่มแท็ก uses-native-library ต่อไปนี้ลงในไฟล์ 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"/>
ดาวน์โหลดโมเดล
ดาวน์โหลด Hammer 1B ในรูปแบบควอนไทซ์ 8 บิตจาก Hugging Face ดูข้อมูลเพิ่มเติมเกี่ยวกับโมเดลที่มีอยู่ได้ที่เอกสารประกอบโมเดล
พุชเนื้อหาของโฟลเดอร์ hammer2.1_1.5b_q8_ekv4096.task ไปยังอุปกรณ์ 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
ประกาศคำจำกัดความฟังก์ชัน
กำหนดฟังก์ชันที่จะทำให้โมเดลใช้งานได้ เพื่อแสดงให้เห็นถึง กระบวนการนี้ คู่มือเริ่มต้นฉบับย่อนี้จึงมีฟังก์ชัน 2 ฟังก์ชันเป็นเมธอดแบบคงที่ซึ่งจะแสดงผล การตอบกลับที่ฮาร์ดโค้ด การใช้งานที่ใช้งานได้จริงมากกว่าคือการกำหนดฟังก์ชัน ที่เรียกใช้ REST API หรือดึงข้อมูลจากฐานข้อมูล
ต่อไปนี้คือคำจำกัดความของฟังก์ชัน getWeather และ 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() {}
}
ใช้ FunctionDeclaration เพื่ออธิบายแต่ละฟังก์ชัน โดยตั้งชื่อและ
คำอธิบายของแต่ละฟังก์ชัน และระบุประเภท ซึ่งจะแจ้งให้โมเดลทราบว่าฟังก์ชันทำอะไรและเมื่อใดควรเรียกใช้ฟังก์ชัน
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();
เพิ่มการประกาศฟังก์ชันไปยังออบเจ็กต์ Tool
var tool = Tool.newBuilder()
.addFunctionDeclarations(getWeather)
.addFunctionDeclarations(getTime)
.build();
สร้างแบ็กเอนด์การอนุมาน
สร้างแบ็กเอนด์การอนุมานโดยใช้ LLM Inference API และส่งออบเจ็กต์ตัวจัดรูปแบบ
สำหรับโมเดลของคุณ ตัวจัดรูปแบบ FC SDK (ModelFormatter) ทำหน้าที่เป็นทั้งตัวจัดรูปแบบและตัวแยกวิเคราะห์
เนื่องจากการเริ่มต้นอย่างรวดเร็วนี้ใช้ Gemma-3 1B เราจึงจะใช้
GemmaFormatter
var llmInferenceOptions = LlmInferenceOptions.builder()
.setModelPath(modelFile.getAbsolutePath())
.build();
var llmInference = LlmInference.createFromOptions(context, llmInferenceOptions);
var llmInferenceBackend = new llmInferenceBackend(llmInference, new GemmaFormatter());
ดูข้อมูลเพิ่มเติมได้ที่ตัวเลือกการกำหนดค่าการอนุมาน LLM
สร้างอินสแตนซ์ของโมเดล
ใช้ออบเจ็กต์ GenerativeModel เพื่อเชื่อมต่อแบ็กเอนด์การอนุมาน พรอมต์ของระบบ และเครื่องมือ เรามีแบ็กเอนด์และเครื่องมือการอนุมานอยู่แล้ว จึงต้องสร้างเฉพาะพรอมต์ของระบบเท่านั้น
var systemInstruction = Content.newBuilder()
.setRole("system")
.addParts(Part.newBuilder().setText("You are a helpful assistant."))
.build();
สร้างอินสแตนซ์โมเดลด้วย GenerativeModel
var generativeModel = new GenerativeModel(
llmInferenceBackend,
systemInstruction,
List.of(tool),
)
เริ่มเซสชันการแชท
คู่มือเริ่มต้นฉบับย่อนี้จะเริ่มเซสชันแชทเดียวเพื่อให้ง่ายต่อการใช้งาน นอกจากนี้ คุณยัง สร้างเซสชันหลายรายการแยกกันได้ด้วย
เริ่มเซสชันแชทโดยใช้อินสแตนซ์ใหม่ของ GenerativeModel โดยทำดังนี้
var chat = generativeModel.startChat();
ส่งพรอมต์ไปยังโมเดลผ่านเซสชันแชทโดยใช้เมธอด sendMessage
var response = chat.sendMessage("How's the weather in San Francisco?");
แยกวิเคราะห์คำตอบของโมเดล
หลังจากส่งพรอมต์ไปยังโมเดลแล้ว แอปพลิเคชันต้องตรวจสอบคำตอบ เพื่อพิจารณาว่าจะเรียกใช้ฟังก์ชันหรือแสดงข้อความภาษาธรรมชาติ
// 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 functionResponseContent = Content.newBuilder()
.setRole("user")
.addParts(Part.newBuilder().setFunctionResponse(functionResponse))
.build();
var response = chat.sendMessage(functionResponseContent);
} else if (message.hasText()) {
Log.i(message.getText());
}
โค้ดตัวอย่างเป็นการติดตั้งใช้งานที่ง่ายเกินไป ดูข้อมูลเพิ่มเติมเกี่ยวกับ วิธีที่แอปพลิเคชันจะตรวจสอบคำตอบของโมเดลได้ที่การจัดรูปแบบและการแยกวิเคราะห์
วิธีการทำงาน
ส่วนนี้จะให้ข้อมูลเชิงลึกเพิ่มเติมเกี่ยวกับแนวคิดหลักและ คอมโพเนนต์ของ Function Calling SDK สำหรับ Android
โมเดล
SDK การเรียกใช้ฟังก์ชันต้องใช้โมเดลที่มีตัวจัดรูปแบบและตัวแยกวิเคราะห์ FC SDK มีตัวจัดรูปแบบและตัวแยกวิเคราะห์ในตัวสำหรับโมเดลต่อไปนี้
หากต้องการใช้โมเดลอื่นกับ FC SDK คุณต้องพัฒนา เครื่องมือจัดรูปแบบและเครื่องมือแยกวิเคราะห์ของคุณเองที่เข้ากันได้กับ LLM Inference API
การจัดรูปแบบและการแยกวิเคราะห์
ส่วนสำคัญของการรองรับการเรียกใช้ฟังก์ชันคือการจัดรูปแบบพรอมต์และการแยกวิเคราะห์เอาต์พุตของโมเดล แม้ว่ากระบวนการทั้ง 2 จะแยกกัน แต่ FC SDK จะจัดการทั้งการจัดรูปแบบและการแยกวิเคราะห์ด้วยอินเทอร์เฟซ ModelFormatter
ตัวจัดรูปแบบมีหน้าที่แปลงการประกาศฟังก์ชันที่มีโครงสร้าง เป็นข้อความ จัดรูปแบบการตอบกลับของฟังก์ชัน และแทรกโทเค็นเพื่อระบุ จุดเริ่มต้นและจุดสิ้นสุดของเทิร์นการสนทนา รวมถึงบทบาทของเทิร์นเหล่านั้น (เช่น "ผู้ใช้" "โมเดล")
โดยตัวแยกวิเคราะห์มีหน้าที่ตรวจหาว่าการตอบกลับของโมเดลมี การเรียกใช้ฟังก์ชันหรือไม่ หากตัวแยกวิเคราะห์ตรวจพบการเรียกฟังก์ชัน ตัวแยกวิเคราะห์จะแยกวิเคราะห์การเรียกฟังก์ชันนั้นเป็น ประเภท Structured Data ไม่เช่นนั้น ระบบจะถือว่าข้อความดังกล่าวเป็นคำตอบในภาษาธรรมชาติ
การถอดรหัสที่จำกัด
การถอดรหัสแบบจำกัดเป็นเทคนิคที่ช่วยแนะนำการสร้างเอาต์พุตของ LLM เพื่อให้เป็นไปตามรูปแบบที่มีโครงสร้างที่กำหนดไว้ล่วงหน้า เช่น ออบเจ็กต์ JSON หรือการเรียกฟังก์ชัน Python การบังคับใช้ข้อจำกัดเหล่านี้ทำให้โมเดลจัดรูปแบบเอาต์พุต ในลักษณะที่สอดคล้องกับฟังก์ชันที่กำหนดไว้ล่วงหน้าและ ประเภทพารามิเตอร์ที่เกี่ยวข้อง
หากต้องการเปิดใช้การถอดรหัสแบบจำกัด ให้กำหนดข้อจำกัดในออบเจ็กต์ ConstraintOptions
และเรียกใช้เมธอด enableConstraint ของอินสแตนซ์ ChatSession
เมื่อเปิดใช้ ข้อจำกัดนี้จะจำกัดคำตอบให้มีเฉพาะเครื่องมือที่เชื่อมโยงกับ GenerativeModel เท่านั้น
ตัวอย่างต่อไปนี้แสดงวิธีกำหนดค่าการถอดรหัสแบบจำกัดเพื่อจำกัดการตอบกลับให้เป็นการเรียกใช้เครื่องมือ โดยจะจำกัดการเรียกใช้เครื่องมือให้เริ่มต้นด้วย
คำนำหน้า ```tool_code\n และลงท้ายด้วยคำต่อท้าย
\n```
ConstraintOptions constraintOptions = ConstraintOptions.newBuilder()
.setToolCallOnly( ConstraintOptions.ToolCallOnly.newBuilder()
.setConstraintPrefix("```tool_code\n")
.setConstraintSuffix("\n```"))
.build(); chatSession.enableConstraint(constraintOptions);
หากต้องการปิดใช้ข้อจํากัดที่ใช้งานอยู่ภายในเซสชันเดียวกัน ให้ใช้วิธี
disableConstraint
chatSession.disableConstraint();