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.5B) LLM Inference API ได้รับการปรับให้เหมาะกับอุปกรณ์ Android ระดับสูง เช่น Pixel 8 และ Samsung S23 ขึ้นไป และไม่รองรับโปรแกรมจำลองอุปกรณ์อย่างน่าเชื่อถือ
เพิ่มทรัพยากร Dependency
FC SDK ใช้ไลบรารี com.google.ai.edge.localagents:localagents-fc และ LLM Inference API ใช้ไลบรารี com.google.mediapipe:tasks-genai เพิ่มทั้ง 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();