1. Gemini destekli Flutter uygulaması geliştirme
Ne oluşturacaksınız?
Bu codelab'de, Gemini API'nin gücünü doğrudan Flutter uygulamanıza getiren etkileşimli bir Flutter uygulaması olan Colorist'i oluşturacaksınız. Kullanıcıların uygulamanızı doğal dilde kontrol etmesini hiç istediniz mi ancak nereden başlayacağınızı mı bilmiyorsunuz? Bu codelab'de nasıl yapılacağı gösterilmektedir.
Colorist, kullanıcıların renkleri doğal dilde (ör. "gün batımının turuncusu" veya "derin okyanus mavisi") tanımlamasına olanak tanır. Uygulama:
- Bu açıklamaları Google'ın Gemini API'sini kullanarak işler.
- Açıklamaları hassas RGB renk değerlerine dönüştürür.
- Ekranda rengi gerçek zamanlı olarak gösterir.
- Renk hakkında teknik ayrıntılar ve ilginç bilgiler sağlar.
- Son oluşturulan renklerin geçmişini tutar.
Uygulamada, bir tarafta renkli ekran alanı ve etkileşimli sohbet sistemi, diğer tarafta ise ham LLM etkileşimlerini gösteren ayrıntılı bir günlük paneli içeren bölünmüş ekran arayüzü bulunur. Bu günlük, bir LLM entegrasyonunun arka planda nasıl çalıştığını daha iyi anlamanızı sağlar.
Bu, Flutter geliştiricileri için neden önemli?
LLM'ler, kullanıcıların uygulamalarla etkileşim kurma şeklini değiştiriyor ancak bunları mobil ve masaüstü uygulamalarına etkili bir şekilde entegre etmek benzersiz zorluklar ortaya çıkarıyor. Bu codelab'de, yalnızca ham API çağrılarının ötesine geçen pratik kalıplar öğretilmektedir.
Öğrenme yolculuğunuz
Bu codelab'de Colorist'i adım adım oluşturma süreci açıklanır:
- Proje kurulumu: Temel bir Flutter uygulama yapısı ve
colorist_ui
paketiyle başlayacaksınız. - Temel Gemini entegrasyonu: Uygulamanızı Firebase AI Logic'e bağlayın ve LLM iletişimi uygulayın
- Etkili istem: LLM'nin renk açıklamalarını anlamasına yardımcı olacak bir sistem istemi oluşturun.
- İşlev beyanları: LLM'nin uygulamanızda renkleri ayarlamak için kullanabileceği araçları tanımlar.
- Araç işleme: LLM'den gelen işlev çağrılarını işleme ve bunları uygulamanızın durumuna bağlama
- Akış yanıtları: Gerçek zamanlı akış LLM yanıtlarıyla kullanıcı deneyimini iyileştirin.
- LLM İçerik Senkronizasyonu: LLM'yi kullanıcı işlemleri hakkında bilgilendirerek tutarlı bir deneyim oluşturun.
Öğrenecekleriniz
- Flutter uygulamaları için Firebase AI Logic'i yapılandırma
- LLM davranışını yönlendirmek için etkili sistem istemleri oluşturma
- Doğal dil ile uygulama özellikleri arasında köprü kuran işlev bildirimleri uygulayın.
- Duyarlı bir kullanıcı deneyimi için akış yanıtlarını işleme
- Kullanıcı arayüzü etkinlikleri ile LLM arasındaki durumu senkronize etme
- Riverpod kullanarak LLM etkileşim durumunu yönetme
- LLM destekli uygulamalarda hataları düzgün şekilde ele alma
Kod önizlemesi: Uygulayacağınız kodun bir önizlemesi
LLM'nin uygulamanızda renkleri ayarlamasına izin vermek için oluşturacağınız işlev bildirimine dair bir önizlemeyi aşağıda bulabilirsiniz:
FunctionDeclaration get setColorFuncDecl => FunctionDeclaration(
'set_color',
'Set the color of the display square based on red, green, and blue values.',
parameters: {
'red': Schema.number(description: 'Red component value (0.0 - 1.0)'),
'green': Schema.number(description: 'Green component value (0.0 - 1.0)'),
'blue': Schema.number(description: 'Blue component value (0.0 - 1.0)'),
},
);
Bu codelab'e genel bakış videosu
Craig Labenz ve Andrew Brogdon'ın Observable Flutter bölümü #59'da bu codelab'i tartıştığı videoyu izleyin:
Ön koşullar
Bu codelab'den en iyi şekilde yararlanmak için şunlara sahip olmanız gerekir:
- Flutter geliştirme deneyimi: Flutter'ın temelleri ve Dart söz dizimi hakkında bilgi sahibi olma
- Asenkron programlama bilgisi: Gelecekler, async/await ve akışlar hakkında bilgi sahibi olma
- Firebase hesabı: Firebase'i ayarlamak için Google Hesabı'na ihtiyacınız vardır.
İlk LLM destekli Flutter uygulamanızı oluşturmaya başlayalım.
2. Proje kurulumu ve yankı hizmeti
Bu ilk adımda proje yapısını ayarlayacak ve daha sonra Gemini API entegrasyonuyla değiştirilecek bir echo hizmeti uygulayacaksınız. Bu, uygulama mimarisini oluşturur ve LLM çağrılarının karmaşıklığını eklemeden önce kullanıcı arayüzünüzün doğru çalıştığından emin olmanızı sağlar.
Bu adımda öğrenecekleriniz
- Gerekli bağımlılıkları içeren bir Flutter projesi oluşturma
- Kullanıcı arayüzü bileşenleri için
colorist_ui
paketiyle çalışma - Yankı mesajı hizmeti uygulama ve kullanıcı arayüzüne bağlama
Yeni bir Flutter projesi oluşturma
Aşağıdaki komutla yeni bir Flutter projesi oluşturarak başlayın:
flutter create -e colorist --platforms=android,ios,macos,web,windows
-e
işareti, varsayılan counter
uygulaması olmadan boş bir proje istediğinizi gösterir. Bu uygulama masaüstü, mobil ve web'de çalışacak şekilde tasarlanmıştır. Ancak flutterfire
şu anda Linux'u desteklememektedir.
Bağımlılık ekleme
Proje dizininize gidin ve gerekli bağımlılıkları ekleyin:
cd colorist
flutter pub add colorist_ui flutter_riverpod riverpod_annotation
flutter pub add --dev build_runner riverpod_generator riverpod_lint json_serializable
Bu işlem aşağıdaki anahtar paketlerini ekler:
colorist_ui
: Colorist uygulaması için kullanıcı arayüzü bileşenlerini sağlayan özel bir paketflutter_riverpod
veriverpod_annotation
: Durum yönetimi içinlogging
: Yapılandırılmış günlük kaydı için- Kod oluşturma ve linting için geliştirme bağımlılıkları
pubspec.yaml
simgeniz aşağıdaki gibi görünür:
pubspec.yaml
name: colorist
description: "A new Flutter project."
publish_to: 'none'
version: 0.1.0
environment:
sdk: ^3.9.2
dependencies:
flutter:
sdk: flutter
colorist_ui: ^0.3.0
flutter_riverpod: ^3.0.0
riverpod_annotation: ^3.0.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^6.0.0
build_runner: ^2.7.1
riverpod_generator: ^3.0.0
riverpod_lint: ^3.0.0
json_serializable: ^6.11.1
flutter:
uses-material-design: true
main.dart
dosyasını uygulama
lib/main.dart
içeriğini aşağıdakiyle değiştirin:
lib/main.dart
import 'package:colorist_ui/colorist_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() async {
runApp(ProviderScope(child: MainApp()));
}
class MainApp extends ConsumerWidget {
const MainApp({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: MainScreen(
sendMessage: (message) {
sendMessage(message, ref);
},
),
);
}
// A fake LLM that just echoes back what it receives.
void sendMessage(String message, WidgetRef ref) {
final chatStateNotifier = ref.read(chatStateProvider.notifier);
final logStateNotifier = ref.read(logStateProvider.notifier);
chatStateNotifier.addUserMessage(message);
logStateNotifier.logUserText(message);
chatStateNotifier.addLlmMessage(message, MessageState.complete);
logStateNotifier.logLlmText(message);
}
}
Bu, kullanıcının mesajını döndürerek bir LLM'nin davranışını taklit eden bir yankı hizmeti uygulayan bir Flutter uygulaması oluşturur.
Mimariyi anlama
colorist
uygulamasının mimarisini anlamak için bir dakikanızı ayıralım:
colorist_ui
paketi
colorist_ui
paketi, önceden oluşturulmuş kullanıcı arayüzü bileşenleri ve durum yönetimi araçları sağlar:
- MainScreen: Aşağıdakileri gösteren ana kullanıcı arayüzü bileşeni:
- Masaüstünde bölünmüş ekran düzeni (etkileşim alanı ve günlük paneli)
- Mobil cihazlarda sekmeli arayüz
- Renk gösterimi, sohbet arayüzü ve geçmiş küçük resimleri
- Durum yönetimi: Uygulamada çeşitli durum bildiriciler kullanılır:
- ChatStateNotifier: Sohbet mesajlarını yönetir.
- ColorStateNotifier: Geçerli rengi ve geçmişi yönetir.
- LogStateNotifier: Hata ayıklama için günlük girişlerini yönetir.
- İleti İşleme: Uygulama, farklı durumlara sahip bir ileti modeli kullanır:
- Kullanıcı mesajları: Kullanıcı tarafından girilir.
- LLM mesajları: LLM (veya şimdilik yankı hizmetiniz) tarafından oluşturulur.
- MessageState: LLM mesajlarının tamamlanıp tamamlanmadığını veya yayınlanmaya devam edip etmediğini izler.
Uygulama mimarisi
Uygulama aşağıdaki mimariyi kullanıyor:
- Kullanıcı arayüzü katmanı:
colorist_ui
paketi tarafından sağlanır. - Durum Yönetimi: Reaktif durum yönetimi için Riverpod'u kullanır.
- Hizmet Katmanı: Şu anda basit yankı hizmetinizi içerir. Bu katman, Gemini Chat Hizmeti ile değiştirilecektir.
- LLM Entegrasyonu: Sonraki adımlarda eklenecektir.
Bu ayrım, kullanıcı arayüzü bileşenleri zaten halledilmişken LLM entegrasyonunu uygulamaya odaklanmanıza olanak tanır.
Uygulamayı çalıştırma
Uygulamayı aşağıdaki komutla çalıştırın:
flutter run -d DEVICE
DEVICE
yerine hedef cihazınızı (ör. macos
, windows
, chrome
veya bir cihaz kimliği) girin.
Artık Colorist uygulamasını şu özelliklerle birlikte görmelisiniz:
- Varsayılan renge sahip bir renk görüntüleme alanı
- Mesaj yazabileceğiniz bir sohbet arayüzü
- Sohbet etkileşimlerini gösteren bir günlük paneli
"Koyu mavi bir renk istiyorum" gibi bir mesaj yazıp Gönder'e basın. Yankı hizmeti, mesajınızı tekrarlar. Sonraki adımlarda, bunu Firebase AI Logic kullanarak gerçek renk yorumlamasıyla değiştireceksiniz.
Sırada ne var?
Bir sonraki adımda Firebase'i yapılandıracak ve temel Gemini API entegrasyonunu uygulayarak yankı hizmetinizi Gemini sohbet hizmetiyle değiştireceksiniz. Bu sayede uygulama, renk açıklamalarını yorumlayabilir ve akıllı yanıtlar verebilir.
Sorun giderme
Kullanıcı arayüzü paketi sorunları
colorist_ui
paketiyle ilgili sorun yaşarsanız:
- En son sürümü kullandığınızdan emin olun.
- Bağımlılığı doğru şekilde eklediğinizi doğrulayın.
- Çakışan paket sürümleri olup olmadığını kontrol edin.
Derleme hataları
Derleme hataları görürseniz:
- En son kararlı kanal Flutter SDK'sının yüklü olduğundan emin olun.
flutter clean
ve ardındanflutter pub get
komutunu çalıştırın.- Belirli hata mesajları için konsol çıkışını kontrol edin.
Öğrenilen temel kavramlar
- Gerekli bağımlılıkları içeren bir Flutter projesi oluşturma
- Uygulamanın mimarisini ve bileşen sorumluluklarını anlama
- LLM'nin davranışını taklit eden basit bir hizmet uygulama
- Hizmeti kullanıcı arayüzü bileşenlerine bağlama
- Durum yönetimi için Riverpod'u kullanma
3. Temel Gemini Chat entegrasyonu
Bu adımda, önceki adımdaki echo hizmetini Firebase AI Logic'i kullanarak Gemini API entegrasyonuyla değiştireceksiniz. Firebase'i yapılandıracak, gerekli sağlayıcıları ayarlayacak ve Gemini API ile iletişim kuran temel bir sohbet hizmeti uygulayacaksınız.
Bu adımda öğrenecekleriniz
- Flutter uygulamasında Firebase'i ayarlama
- Gemini erişimi için Firebase AI Logic'i yapılandırma
- Firebase ve Gemini hizmetleri için Riverpod sağlayıcıları oluşturma
- Gemini API ile temel bir sohbet hizmeti uygulama
- Eşzamansız API yanıtlarını ve hata durumlarını işleme
Firebase'i ayarlama
Öncelikle Flutter projeniz için Firebase'i ayarlamanız gerekir. Bu işlem için Firebase projesi oluşturmanız, uygulamanızı bu projeye eklemeniz ve gerekli Firebase AI Logic ayarlarını yapılandırmanız gerekir.
Firebase projesi oluşturma
- Firebase Console'a gidip Google Hesabınızla oturum açın.
- Firebase projesi oluştur'u tıklayın veya mevcut bir projeyi seçin.
- Projenizi oluşturmak için kurulum sihirbazını izleyin.
Firebase projenizde Firebase AI Logic'i ayarlama
- Firebase konsolunda projenize gidin.
- Soldaki kenar çubuğunda Yapay Zeka'yı seçin.
- Yapay zeka açılır menüsünde Yapay Zeka Mantığı'nı seçin.
- Firebase AI Logic kartında Başlayın'ı seçin.
- Projenizde Gemini Developer API'yi etkinleştirmek için istemleri uygulayın.
FlutterFire CLI'yı yükleme
FlutterFire CLI, Flutter uygulamalarında Firebase kurulumunu basitleştirir:
dart pub global activate flutterfire_cli
Firebase'i Flutter uygulamanıza ekleyin
- Firebase Core ve Firebase AI Logic paketlerini projenize ekleyin:
flutter pub add firebase_core firebase_ai
- FlutterFire yapılandırma komutunu çalıştırın:
flutterfire configure
Bu komut:
- Yeni oluşturduğunuz Firebase projesini seçmenizi ister.
- Flutter uygulamalarınızı Firebase'e kaydetme
- Proje yapılandırmanızla bir
firebase_options.dart
dosyası oluşturun
Komut, seçtiğiniz platformları (iOS, Android, macOS, Windows, web) otomatik olarak algılar ve uygun şekilde yapılandırır.
Platforma özgü yapılandırma
Firebase, Flutter'da varsayılan olarak kullanılanlardan daha yüksek minimum sürümler gerektirir. Firebase AI Logic sunucularıyla iletişim kurmak için ağ erişimi de gerekir.
macOS izinlerini yapılandırma
macOS'te, uygulamanızın yetkilerinde ağ erişimini etkinleştirmeniz gerekir:
macos/Runner/DebugProfile.entitlements
uygulamasını açın ve şunu ekleyin:
macos/Runner/DebugProfile.entitlements
<key>com.apple.security.network.client</key>
<true/>
- Ayrıca
macos/Runner/Release.entitlements
simgesini açıp aynı girişi ekleyin.
iOS ayarlarını yapılandırma
iOS için ios/Podfile
bölümünün üst kısmındaki minimum sürümü güncelleyin:
ios/Podfile
# Firebase requires at least iOS 15.0
platform :ios, '15.0'
Gemini modeli sağlayıcıları oluşturma
Şimdi Firebase ve Gemini için Riverpod sağlayıcılarını oluşturacaksınız. Yeni dosya oluşturma lib/providers/gemini.dart
:
lib/providers/gemini.dart
import 'dart:async';
import 'package:firebase_ai/firebase_ai.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../firebase_options.dart';
part 'gemini.g.dart';
@riverpod
Future<FirebaseApp> firebaseApp(Ref ref) =>
Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
@riverpod
Future<GenerativeModel> geminiModel(Ref ref) async {
await ref.watch(firebaseAppProvider.future);
final model = FirebaseAI.googleAI().generativeModel(
model: 'gemini-2.0-flash',
);
return model;
}
@Riverpod(keepAlive: true)
Future<ChatSession> chatSession(Ref ref) async {
final model = await ref.watch(geminiModelProvider.future);
return model.startChat();
}
Bu dosya, üç temel sağlayıcının temelini tanımlar. Bu sağlayıcılar, Riverpod kod oluşturucular tarafından dart run build_runner
çalıştırıldığında oluşturulur.
firebaseAppProvider
: Firebase'i proje yapılandırmanızla başlatır.geminiModelProvider
: Gemini üretken model örneği oluşturur.chatSessionProvider
: Gemini modeliyle sohbet oturumu oluşturur ve bu oturumu sürdürür.
Sohbet oturumundaki keepAlive: true
ek açıklaması, uygulamanın yaşam döngüsü boyunca oturumun devam etmesini sağlayarak görüşme bağlamını korur.
Gemini Chat hizmetini uygulama
Sohbet hizmetini uygulamak için yeni bir dosya lib/services/gemini_chat_service.dart
oluşturun:
lib/services/gemini_chat_service.dart
import 'dart:async';
import 'package:colorist_ui/colorist_ui.dart';
import 'package:firebase_ai/firebase_ai.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../providers/gemini.dart';
part 'gemini_chat_service.g.dart';
class GeminiChatService {
GeminiChatService(this.ref);
final Ref ref;
Future<void> sendMessage(String message) async {
final chatSession = await ref.read(chatSessionProvider.future);
final chatStateNotifier = ref.read(chatStateProvider.notifier);
final logStateNotifier = ref.read(logStateProvider.notifier);
chatStateNotifier.addUserMessage(message);
logStateNotifier.logUserText(message);
final llmMessage = chatStateNotifier.createLlmMessage();
try {
final response = await chatSession.sendMessage(Content.text(message));
final responseText = response.text;
if (responseText != null) {
logStateNotifier.logLlmText(responseText);
chatStateNotifier.appendToMessage(llmMessage.id, responseText);
}
} catch (e, st) {
logStateNotifier.logError(e, st: st);
chatStateNotifier.appendToMessage(
llmMessage.id,
"\nI'm sorry, I encountered an error processing your request. "
"Please try again.",
);
} finally {
chatStateNotifier.finalizeMessage(llmMessage.id);
}
}
}
@riverpod
GeminiChatService geminiChatService(Ref ref) => GeminiChatService(ref);
Bu hizmet:
- Kullanıcı mesajlarını kabul eder ve Gemini API'ye gönderir.
- Sohbet arayüzünü modelden gelen yanıtlarla günceller.
- Gerçek LLM akışını anlamayı kolaylaştırmak için tüm iletişimi kaydeder.
- Hataları uygun kullanıcı geri bildirimiyle ele alır.
Not: Günlük penceresi bu noktada sohbet penceresiyle neredeyse aynı görünür. İşlev çağrılarını ve ardından akış yanıtlarını tanıttığınızda günlük daha ilginç hale gelir.
Riverpod kodu oluşturma
Gerekli Riverpod kodunu oluşturmak için build_runner komutunu çalıştırın:
dart run build_runner build --delete-conflicting-outputs
Bu işlem, Riverpod'un çalışması için gereken .g.dart
dosyalarını oluşturur.
main.dart dosyasını güncelleme
Yeni Gemini sohbet hizmetini kullanmak için lib/main.dart
dosyanızı güncelleyin:
lib/main.dart
import 'package:colorist_ui/colorist_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'providers/gemini.dart';
import 'services/gemini_chat_service.dart';
void main() async {
runApp(ProviderScope(child: MainApp()));
}
class MainApp extends ConsumerWidget {
const MainApp({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final model = ref.watch(geminiModelProvider);
return MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: model.when(
data: (data) => MainScreen(
sendMessage: (text) {
ref.read(geminiChatServiceProvider).sendMessage(text);
},
),
loading: () => LoadingScreen(message: 'Initializing Gemini Model'),
error: (err, st) => ErrorScreen(error: err),
),
);
}
}
Bu güncellemedeki temel değişiklikler şunlardır:
- Yankı hizmetinin Gemini API tabanlı sohbet hizmetiyle değiştirilmesi
when
yöntemiyle Riverpod'unAsyncValue
kalıbını kullanarak yükleme ve hata ekranları eklemesendMessage
geri çağırma işleviyle kullanıcı arayüzünü yeni sohbet hizmetinize bağlama
Uygulamayı çalıştırma
Uygulamayı aşağıdaki komutla çalıştırın:
flutter run -d DEVICE
DEVICE
yerine hedef cihazınızı (ör. macos
, windows
, chrome
veya bir cihaz kimliği) girin.
Artık mesaj yazdığınızda bu mesaj Gemini API'ye gönderilir ve yankı yerine LLM'den yanıt alırsınız. Günlük panelinde API ile etkileşimler gösterilir.
LLM iletişimini anlama
Gemini API ile iletişim kurduğunuzda neler olduğunu anlamak için bir an duralım:
İletişim akışı
- Kullanıcı girişi: Kullanıcı, sohbet arayüzüne metin girer.
- İstek Biçimlendirmesi: Uygulama, metni Gemini API için
Content
nesnesi olarak biçimlendirir. - API İletişimi: Metin, Firebase AI Logic aracılığıyla Gemini API'ye gönderilir.
- LLM İşleme: Gemini modeli, metni işleyip yanıt oluşturur.
- Yanıt İşleme: Uygulama, yanıtı alır ve kullanıcı arayüzünü günceller.
- Günlük kaydı: Şeffaflık için tüm iletişimler günlüğe kaydedilir.
Sohbet oturumları ve ileti dizisi bağlamı
Gemini sohbet oturumunda mesajlar arasındaki bağlam korunur ve etkileşimli sohbetler yapılabilir. Bu sayede LLM, mevcut oturumdaki önceki etkileşimleri "hatırlayarak" daha tutarlı sohbetler yapabilir.
Sohbet oturumu sağlayıcınızdaki keepAlive: true
ek açıklaması, bu bağlamın uygulamanın yaşam döngüsü boyunca devam etmesini sağlar. Bu kalıcı bağlam, LLM ile doğal bir sohbet akışı sürdürmek için çok önemlidir.
Sırada ne var?
Bu noktada, Gemini API'ye istediğiniz soruyu sorabilirsiniz. Yanıtlayacağı sorularla ilgili herhangi bir kısıtlama yoktur. Örneğin, renk uygulamanızın amacı ile ilgili olmayan Güller Savaşı'nın özetini isteyebilirsiniz.
Sonraki adımda, Gemini'a renk açıklamalarını daha etkili bir şekilde yorumlaması için yol gösterecek bir sistem istemi oluşturacaksınız. Bu kılavuzda, bir LLM'nin davranışının uygulamaya özel ihtiyaçlara göre nasıl özelleştirileceği ve yeteneklerinin uygulamanızın alanına nasıl odaklanacağı gösterilmektedir.
Sorun giderme
Firebase yapılandırma sorunları
Firebase başlatma ile ilgili hatalarla karşılaşırsanız:
firebase_options.dart
dosyanızın doğru şekilde oluşturulduğundan emin olun.- Firebase AI Logic'e erişmek için Blaze planına geçtiğinizi doğrulayın.
API erişim hataları
Gemini API'ye erişirken hata alırsanız:
- Firebase projenizde faturalandırmanın doğru şekilde ayarlandığını onaylayın.
- Firebase projenizde Firebase AI Logic ve Cloud AI API'nin etkinleştirildiğini kontrol edin.
- Ağ bağlantınızı ve güvenlik duvarı ayarlarınızı kontrol edin
- Model adının (
gemini-2.0-flash
) doğru ve kullanılabilir olduğunu doğrulayın.
Görüşme bağlamı sorunları
Gemini'ın sohbetteki önceki bağlamı hatırlamadığını fark ederseniz:
chatSession
işlevinin@Riverpod(keepAlive: true)
ile açıklama eklenmiş olduğunu doğrulayın.- Tüm mesaj alışverişleri için aynı sohbet oturumunu yeniden kullandığınızdan emin olun.
- İleti göndermeden önce sohbet oturumunun düzgün şekilde başlatıldığını doğrulayın.
Platforma özgü sorunlar
Platforma özgü sorunlar için:
- iOS/macOS: Uygun yetkilerin ayarlandığından ve minimum sürümlerin yapılandırıldığından emin olun.
- Android: Minimum SDK sürümünün doğru ayarlandığını doğrulayın
- Konsoldaki platforma özgü hata mesajlarını kontrol etme
Öğrenilen temel kavramlar
- Flutter uygulamasında Firebase'i ayarlama
- Gemini'a erişim için Firebase AI Logic'i yapılandırma
- Eşzamansız hizmetler için Riverpod sağlayıcıları oluşturma
- LLM ile iletişim kuran bir sohbet hizmeti uygulama
- Eşzamansız API durumlarını (yükleme, hata, veri) işleme
- LLM iletişim akışını ve sohbet oturumlarını anlama
4. Renk açıklamaları için etkili istemler
Bu adımda, Gemini'a renk açıklamalarını yorumlama konusunda yol gösteren bir sistem istemi oluşturup uygulayacaksınız. Sistem istemleri, kodunuzu değiştirmeden belirli görevler için LLM davranışını özelleştirmenin etkili bir yoludur.
Bu adımda öğrenecekleriniz
- Sistem istemlerini ve LLM uygulamalarındaki önemini anlama
- Alana özgü görevler için etkili istemler oluşturma
- Flutter uygulamasında sistem istemlerini yükleme ve kullanma
- LLM'yi tutarlı biçimde yanıtlar vermeye yönlendirme
- Sistem istemlerinin LLM davranışını nasıl etkilediğini test etme
Sistem istemlerini anlama
Uygulamaya geçmeden önce sistem istemlerinin ne olduğunu ve neden önemli olduğunu anlayalım:
Sistem istemleri nedir?
Sistem istemi, LLM'ye verilen ve yanıtları için bağlamı, davranış yönergelerini ve beklentileri belirleyen özel bir talimat türüdür. Kullanıcı mesajlarının aksine, sistem istemleri:
- LLM'nin rolünü ve kişiliğini belirleme
- Uzmanlık bilgisi veya yetenekleri tanımlama
- Biçimlendirme talimatları sağlama
- Yanıtlarla ilgili kısıtlamalar belirleme
- Çeşitli senaryoların nasıl ele alınacağını açıklama
Sistem istemini, LLM'ye "iş tanımını" vermek gibi düşünebilirsiniz. Bu istem, modelin görüşme boyunca nasıl davranacağını söyler.
Sistem istemlerinin önemi
Sistem istemleri, tutarlı ve faydalı LLM etkileşimleri oluşturmak için çok önemlidir. Bunun nedeni:
- Tutarlılığı sağlama: Modele, yanıtları tutarlı bir biçimde vermesi için yol gösterin.
- Alaka düzeyini artırma: Modeli belirli alanınıza (örneğimizde renkler) odaklayın.
- Sınırları belirleme: Modelin ne yapması ve ne yapmaması gerektiğini tanımlayın.
- Kullanıcı deneyimini iyileştirme: Daha doğal ve faydalı bir etkileşim kalıbı oluşturma
- İşlem sonrası süresini kısaltma: Yanıtları ayrıştırılması veya görüntülenmesi daha kolay olan biçimlerde alma
Colorist uygulamanız için LLM'nin renk açıklamalarını tutarlı bir şekilde yorumlaması ve RGB değerlerini belirli bir biçimde sağlaması gerekiyor.
Sistem istemi öğesi oluşturma
İlk olarak, çalışma zamanında yüklenecek bir sistem istemi dosyası oluşturursunuz. Bu yaklaşım, uygulamanızı yeniden derlemeden istemi değiştirmenize olanak tanır.
Aşağıdaki içeriğe sahip yeni bir assets/system_prompt.md
dosyası oluşturun:
assets/system_prompt.md
# Colorist System Prompt
You are a color expert assistant integrated into a desktop app called Colorist. Your job is to interpret natural language color descriptions and provide the appropriate RGB values that best represent that description.
## Your Capabilities
You are knowledgeable about colors, color theory, and how to translate natural language descriptions into specific RGB values. When users describe a color, you should:
1. Analyze their description to understand the color they are trying to convey
2. Determine the appropriate RGB values (values should be between 0.0 and 1.0)
3. Respond with a conversational explanation and explicitly state the RGB values
## How to Respond to User Inputs
When users describe a color:
1. First, acknowledge their color description with a brief, friendly response
2. Interpret what RGB values would best represent that color description
3. Always include the RGB values clearly in your response, formatted as: `RGB: (red=X.X, green=X.X, blue=X.X)`
4. Provide a brief explanation of your interpretation
Example:
User: "I want a sunset orange"
You: "Sunset orange is a warm, vibrant color that captures the golden-red hues of the setting sun. It combines a strong red component with moderate orange tones.
RGB: (red=1.0, green=0.5, blue=0.25)
I've selected values with high red, moderate green, and low blue to capture that beautiful sunset glow. This creates a warm orange with a slightly reddish tint, reminiscent of the sun low on the horizon."
## When Descriptions are Unclear
If a color description is ambiguous or unclear, please ask the user clarifying questions, one at a time.
## Important Guidelines
- Always keep RGB values between 0.0 and 1.0
- Always format RGB values as: `RGB: (red=X.X, green=X.X, blue=X.X)` for easy parsing
- Provide thoughtful, knowledgeable responses about colors
- When possible, include color psychology, associations, or interesting facts about colors
- Be conversational and engaging in your responses
- Focus on being helpful and accurate with your color interpretations
Sistem istemi yapısını anlama
Bu istemin ne yaptığını inceleyelim:
- Rolün tanımı: LLM'yi "renk uzmanı asistanı" olarak tanımlar.
- Görev açıklaması: Birincil görevi, renk açıklamalarını RGB değerlerine dönüştürmek olarak tanımlar.
- Yanıt biçimi: Tutarlılık için RGB değerlerinin tam olarak nasıl biçimlendirilmesi gerektiğini belirtir.
- Örnek alışveriş: Beklenen etkileşim kalıbıyla ilgili somut bir örnek sağlar.
- Uç durum işleme: Net olmayan açıklamaların nasıl işleneceği konusunda talimat verir.
- Kısıtlamalar ve yönergeler: RGB değerlerini 0,0 ile 1,0 arasında tutma gibi sınırlar belirler.
Bu yapılandırılmış yaklaşım, LLM'nin yanıtlarının tutarlı ve bilgilendirici olmasını sağlar. Ayrıca, RGB değerlerini programatik olarak çıkarmak isterseniz yanıtlar kolayca ayrıştırılabilecek şekilde biçimlendirilir.
pubspec.yaml dosyasını güncelleme
Şimdi pubspec.yaml
dosyanızın alt kısmını öğeler dizinini içerecek şekilde güncelleyin:
pubspec.yaml
flutter:
uses-material-design: true
assets:
- assets/
Öğe paketini yenilemek için flutter pub get
komutunu çalıştırın.
Sistem istemi sağlayıcı oluşturma
Sistem istemini yüklemek için yeni bir dosya lib/providers/system_prompt.dart
oluşturun:
lib/providers/system_prompt.dart
import 'package:flutter/services.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'system_prompt.g.dart';
@riverpod
Future<String> systemPrompt(Ref ref) =>
rootBundle.loadString('assets/system_prompt.md');
Bu sağlayıcı, istem dosyasını çalışma zamanında okumak için Flutter'ın öğe yükleme sistemini kullanır.
Gemini model sağlayıcısını güncelleme
Şimdi lib/providers/gemini.dart
dosyanızı sistem istemini içerecek şekilde değiştirin:
lib/providers/gemini.dart
import 'dart:async';
import 'package:firebase_ai/firebase_ai.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../firebase_options.dart';
import 'system_prompt.dart'; // Add this import
part 'gemini.g.dart';
@riverpod
Future<FirebaseApp> firebaseApp(Ref ref) =>
Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
@riverpod
Future<GenerativeModel> geminiModel(Ref ref) async {
await ref.watch(firebaseAppProvider.future);
final systemPrompt = await ref.watch(systemPromptProvider.future); // Add this line
final model = FirebaseAI.googleAI().generativeModel(
model: 'gemini-2.0-flash',
systemInstruction: Content.system(systemPrompt), // And this line
);
return model;
}
@Riverpod(keepAlive: true)
Future<ChatSession> chatSession(Ref ref) async {
final model = await ref.watch(geminiModelProvider.future);
return model.startChat();
}
Temel değişiklik, üretken model oluşturulurken systemInstruction: Content.system(systemPrompt)
eklenmesidir. Bu işlem, Gemini'a bu sohbet oturumundaki tüm etkileşimler için talimatlarınızı sistem istemi olarak kullanmasını söyler.
Riverpod kodu oluşturma
Gerekli Riverpod kodunu oluşturmak için derleme çalıştırıcı komutunu çalıştırın:
dart run build_runner build --delete-conflicting-outputs
Uygulamayı çalıştırma ve test etme
Şimdi uygulamanızı çalıştırın:
flutter run -d DEVICE
Çeşitli renk açıklamalarıyla test etmeyi deneyin:
- "Gökyüzü mavisi istiyorum"
- "Orman yeşili rengini göster"
- "Canlı bir gün batımı turuncusu yap"
- "Taze lavanta rengini istiyorum"
- "Show me something like a deep ocean blue" (Bana okyanus mavisi gibi bir renk göster)
Gemini'ın artık renklerle ilgili sohbet tarzında açıklamalar ve tutarlı biçimde RGB değerleri vererek yanıt verdiğini göreceksiniz. Sistem istemi, LLM'yi ihtiyacınız olan yanıt türlerini vermesi için etkili bir şekilde yönlendirdi.
Ayrıca, renkler bağlamı dışında içerik istemeyi de deneyin. Örneğin, Güller Savaşı'nın başlıca nedenleri. Önceki adıma kıyasla bir fark olduğunu göreceksiniz.
İstem mühendisliğinin uzmanlık gerektiren görevlerdeki önemi
Sistem istemleri hem sanat hem de bilimdir. Bunlar, LLM entegrasyonunun kritik bir parçasıdır ve modelin belirli uygulamanız için ne kadar faydalı olduğunu önemli ölçüde etkileyebilir. Burada yaptığınız işlem, istem mühendisliğinin bir biçimidir. İstem mühendisliği, modeli uygulamanızın ihtiyaçlarına uygun şekilde davranmaya yönlendirmek için talimatları uyarlamayı ifade eder.
Etkili istem mühendisliği şunları içerir:
- Net rol tanımı: LLM'nin amacını belirleme
- Açık talimatlar: LLM'nin tam olarak nasıl yanıt vermesi gerektiğini ayrıntılı olarak açıklama
- Somut örnekler: İyi yanıtların nasıl göründüğünü yalnızca söylemek yerine gösterme
- Sıra dışı durumları ele alma: LLM'ye belirsiz senaryolarla nasıl başa çıkılacağı konusunda talimat verme
- Biçimlendirme özellikleri: Yanıtların tutarlı ve kullanılabilir bir şekilde yapılandırılmasını sağlama
Oluşturduğunuz sistem istemi, Gemini'ın genel özelliklerini, uygulamanızın ihtiyaçlarına göre biçimlendirilmiş yanıtlar sağlayan özel bir renk yorumlama asistanına dönüştürür. Bu, birçok farklı alan ve görevde uygulayabileceğiniz güçlü bir kalıptır.
Sırada ne var?
Bir sonraki adımda, bu temeli işlev bildirimleri ekleyerek geliştireceksiniz. Bu bildirimler, LLM'nin yalnızca RGB değerleri önermesine değil, aynı zamanda rengi doğrudan ayarlamak için uygulamanızdaki işlevleri çağırmasına da olanak tanır. Bu, LLM'lerin doğal dil ile somut uygulama özellikleri arasındaki boşluğu nasıl doldurabileceğini gösterir.
Sorun giderme
Öğe yükleme sorunları
Sistem istemi yüklenirken hatalarla karşılaşırsanız:
pubspec.yaml
dosyanızın, öğeler dizinini doğru şekilde listelediğini doğrulayın.rootBundle.loadString()
içindeki yolun dosya konumunuzla eşleştiğini kontrol edin.- Öğe paketini yenilemek için
flutter clean
komutunu, ardındanflutter pub get
komutunu çalıştırın.
Tutarsız yanıtlar
LLM, biçim talimatlarınıza tutarlı bir şekilde uymuyorsa:
- Sistem isteminde biçim şartlarını daha açık bir şekilde belirtmeyi deneyin.
- Beklenen kalıbı göstermek için daha fazla örnek ekleyin.
- İstediğiniz biçimin model için uygun olduğundan emin olun.
API hız sınırlaması
Sıklık sınırlamasıyla ilgili hatalarla karşılaşırsanız:
- Firebase AI Logic hizmetinin kullanım sınırları olduğunu unutmayın.
- Eksponansiyel geri yükleme ile yeniden deneme mantığı uygulamayı düşünün
- Kota sorunları olup olmadığını görmek için Firebase konsolunuzu kontrol edin.
Öğrenilen temel kavramlar
- LLM uygulamalarında sistem istemlerinin rolünü ve önemini anlama
- Net talimatlar, örnekler ve kısıtlamalar içeren etkili istemler oluşturma
- Flutter uygulamasında sistem istemlerini yükleme ve kullanma
- Alana özgü görevler için LLM davranışını yönlendirme
- LLM yanıtlarını şekillendirmek için istem mühendisliğini kullanma
Bu adımda, sistem istemine net talimatlar vererek kodunuzu değiştirmeden LLM davranışını nasıl önemli ölçüde özelleştirebileceğiniz gösterilmektedir.
5. LLM araçları için işlev beyanları
Bu adımda, işlev bildirimlerini uygulayarak Gemini'ın uygulamanızda işlem yapmasını sağlama çalışmalarına başlayacaksınız. Bu güçlü özellik, LLM'nin yalnızca RGB değerleri önermesine değil, aynı zamanda özel araç çağrıları aracılığıyla bunları uygulamanızın kullanıcı arayüzünde ayarlamasına da olanak tanır. Ancak Flutter uygulamasında LLM isteklerinin yürütüldüğünü görmek için bir sonraki adımın tamamlanması gerekir.
Bu adımda öğrenecekleriniz
- LLM işlev çağrısını ve Flutter uygulamaları için avantajlarını anlama
- Gemini için şemaya dayalı işlev bildirimlerini tanımlama
- İşlev bildirimlerini Gemini modelinizle entegre etme
- Araç özelliklerinden yararlanmak için sistem istemini güncelleme
İşlev çağrısını anlama
İşlev bildirimlerini uygulamadan önce ne olduklarını ve neden değerli olduklarını anlayalım:
İşlev çağırma nedir?
İşlev çağırma (bazen "araç kullanımı" olarak da adlandırılır), bir LLM'nin aşağıdakileri yapmasına olanak tanıyan bir özelliktir:
- Kullanıcı isteğinin belirli bir işlevin çağrılmasından yararlanacağını anlama
- İşlev için gereken parametreleri içeren yapılandırılmış bir JSON nesnesi oluşturun.
- Uygulamanızın işlevi bu parametrelerle yürütmesine izin verin.
- İşlevin sonucunu alıp yanıtına dahil etme
İşlev çağrısı, LLM'nin yalnızca ne yapılması gerektiğini açıklamak yerine uygulamanızda somut işlemler başlatmasını sağlar.
Flutter uygulamaları için işlev çağrısının önemi
İşlev çağrısı, doğal dil ile uygulama özellikleri arasında güçlü bir köprü oluşturur:
- Doğrudan işlem: Kullanıcılar istediklerini doğal dilde açıklayabilir ve uygulama, somut işlemlerle yanıt verir.
- Yapılandırılmış çıkış: LLM, ayrıştırılması gereken metin yerine temiz ve yapılandırılmış veriler üretir.
- Karmaşık işlemler: LLM'nin harici verilere erişmesine, hesaplamalar yapmasına veya uygulama durumunu değiştirmesine olanak tanır.
- Daha iyi kullanıcı deneyimi: Sohbet ile işlevsellik arasında sorunsuz entegrasyon sağlar.
Colorist uygulamanızda, işlev çağrısı özelliği sayesinde kullanıcılar "Orman yeşili istiyorum" diyebiliyor ve kullanıcı arayüzü, metindeki RGB değerlerini ayrıştırmaya gerek kalmadan bu renkle anında güncelleniyor.
İşlev bildirimlerini tanımlama
İşlev bildirimlerinizi tanımlamak için yeni bir dosya lib/services/gemini_tools.dart
oluşturun:
lib/services/gemini_tools.dart
import 'package:firebase_ai/firebase_ai.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'gemini_tools.g.dart';
class GeminiTools {
GeminiTools(this.ref);
final Ref ref;
FunctionDeclaration get setColorFuncDecl => FunctionDeclaration(
'set_color',
'Set the color of the display square based on red, green, and blue values.',
parameters: {
'red': Schema.number(description: 'Red component value (0.0 - 1.0)'),
'green': Schema.number(description: 'Green component value (0.0 - 1.0)'),
'blue': Schema.number(description: 'Blue component value (0.0 - 1.0)'),
},
);
List<Tool> get tools => [
Tool.functionDeclarations([setColorFuncDecl]),
];
}
@riverpod
GeminiTools geminiTools(Ref ref) => GeminiTools(ref);
İşlev bildirimlerini anlama
Bu kodun ne yaptığını inceleyelim:
- İşlev adlandırma: İşlevinizi amacını net bir şekilde belirtmek için
set_color
olarak adlandırırsınız. - İşlev açıklaması: LLM'nin işlevi ne zaman kullanacağını anlamasına yardımcı olan net bir açıklama sağlarsınız.
- Parametre tanımları: Yapılandırılmış parametreleri kendi açıklamalarıyla tanımlarsınız:
red
: RGB'nin kırmızı bileşeni, 0,0 ile 1,0 arasında bir sayı olarak belirtilir.green
: RGB'nin yeşil bileşeni, 0,0 ile 1,0 arasında bir sayı olarak belirtilir.blue
: RGB'nin mavi bileşeni, 0,0 ile 1,0 arasında bir sayı olarak belirtilir.
- Şema türleri: Bunların sayısal değerler olduğunu belirtmek için
Schema.number()
kullanırsınız. - Araç koleksiyonu: İşlev bildiriminizi içeren bir araç listesi oluşturursunuz.
Bu yapılandırılmış yaklaşım, Gemini LLM'nin aşağıdakileri anlamasına yardımcı olur:
- Bu işlevin ne zaman çağrılması gerektiği
- Hangi parametreleri sağlaması gerektiği
- Bu parametreler için hangi kısıtlamalar geçerlidir (ör. değer aralığı)
Gemini model sağlayıcısını güncelleme
Şimdi, Gemini modelini başlatırken işlev bildirimlerini içerecek şekilde lib/providers/gemini.dart
dosyanızı değiştirin:
lib/providers/gemini.dart
import 'dart:async';
import 'package:firebase_ai/firebase_ai.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../firebase_options.dart';
import '../services/gemini_tools.dart'; // Add this import
import 'system_prompt.dart';
part 'gemini.g.dart';
@riverpod
Future<FirebaseApp> firebaseApp(Ref ref) =>
Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
@riverpod
Future<GenerativeModel> geminiModel(Ref ref) async {
await ref.watch(firebaseAppProvider.future);
final systemPrompt = await ref.watch(systemPromptProvider.future);
final geminiTools = ref.watch(geminiToolsProvider); // Add this line
final model = FirebaseAI.googleAI().generativeModel(
model: 'gemini-2.0-flash',
systemInstruction: Content.system(systemPrompt),
tools: geminiTools.tools, // And this line
);
return model;
}
@Riverpod(keepAlive: true)
Future<ChatSession> chatSession(Ref ref) async {
final model = await ref.watch(geminiModelProvider.future);
return model.startChat();
}
Temel değişiklik, üretken model oluşturulurken tools: geminiTools.tools
parametresinin eklenmesidir. Bu sayede Gemini, çağırabileceği işlevlerin farkında olur.
Sistem istemini güncelleme
Şimdi sistem isteminizi değiştirerek LLM'ye yeni set_color
aracını kullanma talimatı vermeniz gerekiyor. assets/system_prompt.md
adresini güncelleyin:
assets/system_prompt.md
# Colorist System Prompt
You are a color expert assistant integrated into a desktop app called Colorist. Your job is to interpret natural language color descriptions and set the appropriate color values using a specialized tool.
## Your Capabilities
You are knowledgeable about colors, color theory, and how to translate natural language descriptions into specific RGB values. You have access to the following tool:
`set_color` - Sets the RGB values for the color display based on a description
## How to Respond to User Inputs
When users describe a color:
1. First, acknowledge their color description with a brief, friendly response
2. Interpret what RGB values would best represent that color description
3. Use the `set_color` tool to set those values (all values should be between 0.0 and 1.0)
4. After setting the color, provide a brief explanation of your interpretation
Example:
User: "I want a sunset orange"
You: "Sunset orange is a warm, vibrant color that captures the golden-red hues of the setting sun. It combines a strong red component with moderate orange tones."
[Then you would call the set_color tool with approximately: red=1.0, green=0.5, blue=0.25]
After the tool call: "I've set a warm orange with strong red, moderate green, and minimal blue components that is reminiscent of the sun low on the horizon."
## When Descriptions are Unclear
If a color description is ambiguous or unclear, please ask the user clarifying questions, one at a time.
## Important Guidelines
- Always keep RGB values between 0.0 and 1.0
- Provide thoughtful, knowledgeable responses about colors
- When possible, include color psychology, associations, or interesting facts about colors
- Be conversational and engaging in your responses
- Focus on being helpful and accurate with your color interpretations
Sistem istemindeki temel değişiklikler şunlardır:
- Aracın tanıtımı: Biçimlendirilmiş RGB değerleri istemek yerine artık LLM'ye
set_color
aracı hakkında bilgi veriyorsunuz. - Değiştirilmiş süreç: 3. adımı "Yanıtı değerleri biçimlendirme"den "Değerleri ayarlamak için aracı kullanma"ya değiştiriyorsunuz.
- Güncellenen örnek: Yanıtın biçimlendirilmiş metin yerine bir araç çağrısı içermesi gerektiğini gösteriyorsunuz.
- Biçimlendirme koşulu kaldırıldı: Yapılandırılmış işlev çağrıları kullandığınız için artık belirli bir metin biçimine ihtiyacınız yok.
Bu güncellenmiş istem, LLM'yi yalnızca metin biçiminde RGB değerleri sağlamak yerine işlev çağrısını kullanmaya yönlendirir.
Riverpod kodu oluşturma
Gerekli Riverpod kodunu oluşturmak için derleme çalıştırıcı komutunu çalıştırın:
dart run build_runner build --delete-conflicting-outputs
Uygulamayı çalıştırın
Bu noktada Gemini, işlev çağrısını kullanmaya çalışan içerikler oluşturur ancak işlev çağrıları için henüz işleyiciler uygulamadınız. Uygulamayı çalıştırıp bir rengi tarif ettiğinizde Gemini'ın bir araç çağırmış gibi yanıt verdiğini görürsünüz ancak bir sonraki adıma kadar kullanıcı arayüzünde herhangi bir renk değişikliği görmezsiniz.
Uygulamanızı çalıştırın:
flutter run -d DEVICE
"Derin okyanus mavisi" veya "orman yeşili" gibi bir rengi tanımlamayı deneyin ve yanıtları inceleyin. LLM, yukarıda tanımlanan işlevleri çağırmaya çalışıyor ancak kodunuz henüz işlev çağrılarını algılamıyor.
İşlev çağırma süreci
Gemini işlev çağrısını kullandığında ne olduğunu anlayalım:
- İşlev seçimi: LLM, kullanıcının isteğine göre işlev çağrısının faydalı olup olmayacağına karar verir.
- Parametre oluşturma: LLM, işlevin şemasına uygun parametre değerleri oluşturur.
- İşlev çağrısı biçimi: LLM, yanıtında yapılandırılmış bir işlev çağrısı nesnesi gönderir.
- Uygulama işleme: Uygulamanız bu çağrıyı alır ve ilgili işlevi (sonraki adımda uygulanır) yürütür.
- Yanıt entegrasyonu: Çok turlu sohbetlerde LLM, işlevin sonucunun döndürülmesini bekler.
Uygulamanızın mevcut durumunda ilk üç adım gerçekleşiyor ancak sonraki adımda yapacağınız 4. veya 5. adımı (işlev çağrılarını işleme) henüz uygulamadınız.
Teknik ayrıntılar: Gemini, işlevleri ne zaman kullanacağına nasıl karar verir?
Gemini, işlevleri ne zaman kullanacağı konusunda aşağıdaki bilgilere dayanarak akıllı kararlar verir:
- Kullanıcı amacı: Kullanıcının isteğine en iyi şekilde bir işlevle yanıt verilip verilmeyeceği
- İşlev alaka düzeyi: Kullanılabilir işlevlerin görevle ne kadar iyi eşleştiği
- Parametre kullanılabilirliği: Parametre değerlerinin güvenle belirlenip belirlenemediği
- Sistem talimatları: İşlev kullanımıyla ilgili sistem isteminizden gelen yönlendirme
Net işlev bildirimleri ve sistem talimatları sağlayarak Gemini'ı, renk açıklaması isteklerini set_color
işlevini çağırma fırsatı olarak tanıyacak şekilde ayarladınız.
Sırada ne var?
Bir sonraki adımda, Gemini'dan gelen işlev çağrıları için işleyiciler uygulayacaksınız. Bu işlem, daireyi tamamlayarak kullanıcı açıklamalarının LLM'nin işlev çağrıları aracılığıyla kullanıcı arayüzünde gerçek renk değişikliklerini tetiklemesine olanak tanır.
Sorun giderme
İşlev bildirimiyle ilgili sorunlar
İşlev bildirimleriyle ilgili hatalarla karşılaşırsanız:
- Parametre adlarının ve türlerinin beklentilerle eşleştiğinden emin olun.
- İşlev adının net ve açıklayıcı olduğunu doğrulayın.
- İşlev açıklamasının amacını doğru şekilde açıkladığından emin olun.
Sistem istemi sorunları
LLM işlevi kullanmaya çalışmıyorsa:
- Sistem isteminizin, LLM'ye
set_color
aracını kullanması için net bir şekilde talimat verdiğini doğrulayın. - Sistem istemindeki örneğin işlev kullanımını gösterdiğini kontrol edin.
- Aracı kullanma talimatını daha net bir şekilde vermeyi deneyin.
Genel sorunlar
Başka sorunlarla karşılaşırsanız:
- İşlev bildirimleriyle ilgili hatalar için konsolu kontrol edin.
- Araçların modele doğru şekilde iletildiğini doğrulayın.
- Riverpod tarafından oluşturulan tüm kodların güncel olduğundan emin olun.
Öğrenilen temel kavramlar
- Flutter uygulamalarında LLM özelliklerini genişletmek için işlev bildirimlerini tanımlama
- Yapılandırılmış veri toplama için parametre şemaları oluşturma
- Fonksiyon bildirimlerini Gemini modeline entegre etme
- İşlev kullanımını teşvik etmek için sistem istemlerini güncelleme
- LLM'lerin işlevleri nasıl seçip çağırdığını anlama
Bu adımda, LLM'lerin doğal dil girişi ile yapılandırılmış işlev çağrıları arasındaki boşluğu nasıl doldurabileceği gösterilmektedir. Bu sayede, sohbet ve uygulama özellikleri arasında sorunsuz entegrasyonun temelleri atılır.
6. Araç kullanımını uygulama
Bu adımda, Gemini'dan gelen işlev çağrıları için işleyiciler uygulayacaksınız. Bu sayede, doğal dil girişleri ile somut uygulama özellikleri arasındaki iletişim döngüsü tamamlanır ve LLM'nin kullanıcı açıklamalarına göre kullanıcı arayüzünüzü doğrudan değiştirmesine olanak tanınır.
Bu adımda öğrenecekleriniz
- LLM uygulamalarındaki işlev çağrısı işlem hattının tamamını anlama
- Flutter uygulamasında Gemini'dan gelen işlev çağrılarını işleme
- Uygulama durumunu değiştiren işlev işleyicilerini uygulama
- İşlev yanıtlarını işleme ve sonuçları LLM'ye döndürme
- LLM ile kullanıcı arayüzü arasında eksiksiz bir iletişim akışı oluşturma
- Şeffaflık için işlev çağrılarını ve yanıtlarını günlüğe kaydetme
İşlev çağrısı işlem hattını anlama
Uygulamaya geçmeden önce, işlev çağrısı işlem hattının tamamını anlayalım:
Uçtan uca akış
- Kullanıcı girişi: Kullanıcı, doğal dilde bir rengi tanımlar (ör. "orman yeşili")
- LLM işleme: Gemini, açıklamayı analiz eder ve
set_color
işlevini çağırmaya karar verir. - İşlev çağrısı oluşturma: Gemini, parametrelerle (kırmızı, yeşil, mavi değerleri) yapılandırılmış bir JSON oluşturur.
- İşlev çağrısı yanıtı: Uygulamanız, Gemini'dan bu yapılandırılmış verileri alır.
- İşlev yürütme: Uygulamanız, sağlanan parametrelerle işlevi yürütür.
- Durum güncelleme: İşlev, uygulamanızın durumunu günceller (görüntülenen rengi değiştirir).
- Yanıt oluşturma: İşleviniz sonuçları LLM'ye geri döndürür.
- Yanıt oluşturma: LLM, bu sonuçları nihai yanıtına dahil eder.
- Kullanıcı arayüzü güncellemesi: Kullanıcı arayüzünüz durum değişikliğine tepki vererek yeni rengi gösterir.
Büyük dil modelinin düzgün bir şekilde entegre edilmesi için iletişim döngüsünün tamamlanması gerekir. Bir LLM, işlev çağrısı yaptığında isteği gönderip devam etmez. Bunun yerine, uygulamanızın işlevi yürütmesini ve sonuçları döndürmesini bekler. LLM daha sonra bu sonuçları kullanarak nihai yanıtını oluşturur ve gerçekleştirilen işlemleri onaylayan doğal bir sohbet akışı oluşturur.
İşlev işleyicileri uygulama
İşlev çağrıları için işleyiciler eklemek üzere lib/services/gemini_tools.dart
dosyanızı güncelleyelim:
lib/services/gemini_tools.dart
import 'package:colorist_ui/colorist_ui.dart';
import 'package:firebase_ai/firebase_ai.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'gemini_tools.g.dart';
class GeminiTools {
GeminiTools(this.ref);
final Ref ref;
FunctionDeclaration get setColorFuncDecl => FunctionDeclaration(
'set_color',
'Set the color of the display square based on red, green, and blue values.',
parameters: {
'red': Schema.number(description: 'Red component value (0.0 - 1.0)'),
'green': Schema.number(description: 'Green component value (0.0 - 1.0)'),
'blue': Schema.number(description: 'Blue component value (0.0 - 1.0)'),
},
);
List<Tool> get tools => [
Tool.functionDeclarations([setColorFuncDecl]),
];
Map<String, Object?> handleFunctionCall( // Add from here
String functionName,
Map<String, Object?> arguments,
) {
final logStateNotifier = ref.read(logStateProvider.notifier);
logStateNotifier.logFunctionCall(functionName, arguments);
return switch (functionName) {
'set_color' => handleSetColor(arguments),
_ => handleUnknownFunction(functionName),
};
}
Map<String, Object?> handleSetColor(Map<String, Object?> arguments) {
final colorStateNotifier = ref.read(colorStateProvider.notifier);
final red = (arguments['red'] as num).toDouble();
final green = (arguments['green'] as num).toDouble();
final blue = (arguments['blue'] as num).toDouble();
final functionResults = {
'success': true,
'current_color': colorStateNotifier
.updateColor(red: red, green: green, blue: blue)
.toLLMContextMap(),
};
final logStateNotifier = ref.read(logStateProvider.notifier);
logStateNotifier.logFunctionResults(functionResults);
return functionResults;
}
Map<String, Object?> handleUnknownFunction(String functionName) {
final logStateNotifier = ref.read(logStateProvider.notifier);
logStateNotifier.logWarning('Unsupported function call $functionName');
return {
'success': false,
'reason': 'Unsupported function call $functionName',
};
} // To here.
}
@riverpod
GeminiTools geminiTools(Ref ref) => GeminiTools(ref);
İşlev işleyicilerini anlama
Bu işlev işleyicilerin ne işe yaradığını inceleyelim:
handleFunctionCall
: Şunları yapan merkezi bir dağıtıcı:- Günlük panelinde şeffaflık için işlev çağrısını günlüğe kaydeder.
- İşlev adına göre uygun işleyiciye yönlendirir.
- LLM'ye geri gönderilecek yapılandırılmış bir yanıt döndürür.
handleSetColor
:set_color
işleviniz için şu özellikleri içeren işleyici:- Bağımsız değişkenler haritasından RGB değerlerini çıkarır.
- Bunları beklenen türlere (çift) dönüştürür.
colorStateNotifier
kullanarak uygulamanın renk durumunu günceller.- Başarı durumu ve mevcut renk bilgileriyle yapılandırılmış bir yanıt oluşturur.
- Hata ayıklama için işlev sonuçlarını günlüğe kaydeder.
handleUnknownFunction
: Bilinmeyen işlevler için yedek işleyici:- Desteklenmeyen işlevle ilgili uyarıyı günlüğe kaydeder.
- LLM'ye hata yanıtı döndürür.
handleSetColor
işlevi, LLM'nin doğal dil anlayışı ile somut kullanıcı arayüzü değişiklikleri arasındaki boşluğu doldurduğu için özellikle önemlidir.
İşlev çağrılarını ve yanıtlarını işlemek için Gemini sohbet hizmetini güncelleme
Şimdi, LLM yanıtlarındaki işlev çağrılarını işlemek ve sonuçları LLM'ye geri göndermek için lib/services/gemini_chat_service.dart
dosyasını güncelleyelim:
lib/services/gemini_chat_service.dart
import 'dart:async';
import 'package:colorist_ui/colorist_ui.dart';
import 'package:firebase_ai/firebase_ai.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../providers/gemini.dart';
import 'gemini_tools.dart'; // Add this import
part 'gemini_chat_service.g.dart';
class GeminiChatService {
GeminiChatService(this.ref);
final Ref ref;
Future<void> sendMessage(String message) async {
final chatSession = await ref.read(chatSessionProvider.future);
final chatStateNotifier = ref.read(chatStateProvider.notifier);
final logStateNotifier = ref.read(logStateProvider.notifier);
chatStateNotifier.addUserMessage(message);
logStateNotifier.logUserText(message);
final llmMessage = chatStateNotifier.createLlmMessage();
try {
final response = await chatSession.sendMessage(Content.text(message));
final responseText = response.text;
if (responseText != null) {
logStateNotifier.logLlmText(responseText);
chatStateNotifier.appendToMessage(llmMessage.id, responseText);
}
if (response.functionCalls.isNotEmpty) { // Add from here
final geminiTools = ref.read(geminiToolsProvider);
final functionResultResponse = await chatSession.sendMessage(
Content.functionResponses([
for (final functionCall in response.functionCalls)
FunctionResponse(
functionCall.name,
geminiTools.handleFunctionCall(
functionCall.name,
functionCall.args,
),
),
]),
);
final responseText = functionResultResponse.text;
if (responseText != null) {
logStateNotifier.logLlmText(responseText);
chatStateNotifier.appendToMessage(llmMessage.id, responseText);
}
} // To here.
} catch (e, st) {
logStateNotifier.logError(e, st: st);
chatStateNotifier.appendToMessage(
llmMessage.id,
"\nI'm sorry, I encountered an error processing your request. "
"Please try again.",
);
} finally {
chatStateNotifier.finalizeMessage(llmMessage.id);
}
}
}
@riverpod
GeminiChatService geminiChatService(Ref ref) => GeminiChatService(ref);
İletişim akışını anlama
Buradaki temel yenilik, işlev çağrıları ve yanıtlarının eksiksiz şekilde işlenmesidir:
if (response.functionCalls.isNotEmpty) {
final geminiTools = ref.read(geminiToolsProvider);
final functionResultResponse = await chatSession.sendMessage(
Content.functionResponses([
for (final functionCall in response.functionCalls)
FunctionResponse(
functionCall.name,
geminiTools.handleFunctionCall(
functionCall.name,
functionCall.args,
),
),
]),
);
final responseText = functionResultResponse.text;
if (responseText != null) {
logStateNotifier.logLlmText(responseText);
chatStateNotifier.appendToMessage(llmMessage.id, responseText);
}
}
Bu kod:
- LLM yanıtının herhangi bir işlev çağrısı içerip içermediğini kontrol eder.
- Her işlev çağrısı için
handleFunctionCall
yönteminizi işlev adı ve bağımsız değişkenlerle çağırır. - Her işlev çağrısının sonuçlarını toplar.
- Bu sonuçları
Content.functionResponses
kullanarak LLM'ye geri gönderir. - LLM'nin işlev sonuçlarına verdiği yanıtı işler.
- Kullanıcı arayüzünü nihai yanıt metniyle günceller.
Bu işlem, gidiş-dönüş akışı oluşturur:
- Kullanıcı → LLM: Renk istiyor
- LLM → Uygulama: Parametrelerle işlev çağrıları
- Uygulama → Kullanıcı: Yeni renk gösteriliyor
- Uygulama → LLM: İşlev sonuçları
- LLM → Kullanıcı: İşlev sonuçlarını içeren nihai yanıt
Riverpod kodu oluşturma
Gerekli Riverpod kodunu oluşturmak için derleme çalıştırıcı komutunu çalıştırın:
dart run build_runner build --delete-conflicting-outputs
Akışın tamamını çalıştırma ve test etme
Şimdi uygulamanızı çalıştırın:
flutter run -d DEVICE
Çeşitli renk açıklamaları girmeyi deneyin:
- "Koyu kırmızı istiyorum"
- "Sakinleştirici bir gökyüzü mavisi göster"
- "Taze nane yapraklarının rengini söyle"
- "Sıcak bir gün batımı turuncusu görmek istiyorum"
- "Make it a rich royal purple" (Rengini zengin bir kraliyet moru yap)
Şimdi şunları görmelisiniz:
- Mesajınızın sohbet arayüzünde görünmesi
- Gemini'ın sohbetteki yanıtı
- Günlük panelinde kaydedilen işlev çağrıları
- İşlev sonuçları hemen günlüğe kaydedilir.
- Açıklanan rengi göstermek için güncellenen renk dikdörtgeni
- RGB değerleri, yeni rengin bileşenlerini gösterecek şekilde güncellenir.
- Gemini'ın son yanıtı gösterilir. Bu yanıtta genellikle ayarlanan renk hakkında yorum yapılır.
Günlük paneli, arka planda neler olup bittiğine dair bilgi sağlar. Şunları görürsünüz:
- Gemini'ın yaptığı tam işlev çağrıları
- Her RGB değeri için seçtiği parametreler
- İşlevinizin döndürdüğü sonuçlar
- Gemini'dan gelen ek yanıtlar
Renk durumu bildiricisi
Renkleri güncellemek için kullandığınız colorStateNotifier
, colorist_ui
paketinin bir parçasıdır. Şunları yönetir:
- Kullanıcı arayüzünde gösterilen mevcut renk
- Renk geçmişi (son 10 renk)
- Kullanıcı arayüzü bileşenlerindeki durum değişiklikleriyle ilgili bildirim
updateColor
işlevini yeni RGB değerleriyle çağırdığınızda:
- Belirtilen değerlerle yeni bir
ColorData
nesnesi oluşturur. - Uygulama durumundaki mevcut rengi günceller.
- Rengi geçmişe ekler.
- Riverpod'un durum yönetimi aracılığıyla kullanıcı arayüzü güncellemelerini tetikler.
colorist_ui
paketindeki kullanıcı arayüzü bileşenleri bu durumu izler ve değiştiğinde otomatik olarak güncellenerek tepkisel bir deneyim oluşturur.
Hata işlemeyi anlama
Uygulamanızda güçlü hata işleme özelliği bulunuyor:
- Try-catch bloğu: Tüm LLM etkileşimlerini sararak istisnaları yakalar.
- Hata günlüğü: Hataları yığın izleriyle birlikte günlük panelinde kaydeder.
- Kullanıcı geri bildirimi: Chat'te kullanıcı dostu bir hata mesajı gösterir.
- Durum temizleme: Hata oluşsa bile mesaj durumunu sonlandırır.
Bu sayede, LLM hizmetinde veya işlev yürütmede sorunlar oluşsa bile uygulama kararlı kalır ve uygun geri bildirimler sağlar.
Kullanıcı deneyimi için işlev çağrısının gücü
Burada yaptığınız işlemler, LLM'lerin nasıl güçlü doğal arayüzler oluşturabileceğini gösteriyor:
- Doğal dil arayüzü: Kullanıcılar, amaçlarını günlük dilde ifade eder.
- Akıllı yorumlama: LLM, belirsiz açıklamaları kesin değerlere çevirir.
- Doğrudan manipülasyon: Kullanıcı arayüzü, doğal dile yanıt olarak güncellenir.
- Bağlamsal yanıtlar: LLM, değişikliklerle ilgili sohbet bağlamı sağlar.
- Düşük bilişsel yük: Kullanıcıların RGB değerlerini veya renk teorisini anlaması gerekmez.
Doğal dil ile kullanıcı arayüzü işlemleri arasında köprü kurmak için LLM işlev çağrısı kullanma modeli, renk seçimi dışındaki sayısız alana genişletilebilir.
Sırada ne var?
Bir sonraki adımda, akış yanıtlarını uygulayarak kullanıcı deneyimini iyileştireceksiniz. Tam yanıtı beklemek yerine, metin parçalarını ve işlev çağrılarını alındıkça işleyerek daha hızlı yanıt veren ve ilgi çekici bir uygulama oluşturursunuz.
Sorun giderme
İşlev çağrısıyla ilgili sorunlar
Gemini, işlevlerinizi çağırmıyorsa veya parametreleriniz yanlışsa:
- İşlev beyanınızın, sistem isteminde açıklananlarla eşleştiğini doğrulayın.
- Parametre adlarının ve türlerinin tutarlı olup olmadığını kontrol edin.
- Sistem isteminizin, LLM'ye aracı kullanması için açıkça talimat verdiğinden emin olun.
- İşleyicinizdeki işlev adının, bildirimdeki adla tam olarak eşleştiğini doğrulayın.
- İşlev çağrılarıyla ilgili ayrıntılı bilgi için günlük panelini inceleyin.
İşlev yanıtı sorunları
İşlev sonuçları LLM'ye düzgün şekilde geri gönderilmiyorsa:
- İşlevinizin doğru biçimlendirilmiş bir Harita döndürdüğünden emin olun.
- Content.functionResponses'ın doğru şekilde oluşturulduğunu doğrulayın.
- Günlükte işlev yanıtlarıyla ilgili hataları arayın.
- Yanıt için aynı sohbet oturumunu kullandığınızdan emin olun.
Renk görüntüleme sorunları
Renkler doğru şekilde gösterilmiyorsa:
- RGB değerlerinin düzgün şekilde çift sayıya dönüştürüldüğünden emin olun (LLM bunları tam sayı olarak gönderebilir).
- Değerlerin beklenen aralıkta (0,0 ile 1,0 arasında) olduğunu doğrulayın.
- Renk durumu bildirimcisinin doğru şekilde çağrıldığını kontrol edin.
- İşleve iletilen tam değerler için günlüğü inceleyin.
Genel sorunlar
Genel sorunlar için:
- Günlüklerde hata veya uyarı olup olmadığını inceleyin.
- Firebase AI Logic bağlantısını doğrulama
- İşlev parametrelerinde tür uyuşmazlığı olup olmadığını kontrol edin.
- Riverpod tarafından oluşturulan tüm kodların güncel olduğundan emin olun.
Öğrenilen temel kavramlar
- Flutter'da tam bir işlev çağrısı ardışık düzeni uygulama
- Bir LLM ile uygulamanız arasında tam iletişim oluşturma
- LLM yanıtlarındaki yapılandırılmış verileri işleme
- İşlev sonuçlarını, yanıtlara dahil edilmek üzere LLM'ye geri gönderme
- LLM-uygulama etkileşimlerini görünür hale getirmek için günlük panelini kullanma
- Doğal dil girişlerini somut kullanıcı arayüzü değişikliklerine bağlama
Bu adım tamamlandığında uygulamanız artık LLM entegrasyonu için en güçlü kalıplardan birini gösteriyor: doğal dil girişlerini somut kullanıcı arayüzü işlemlerine çevirirken bu işlemleri kabul eden tutarlı bir sohbet sürdürüyor. Bu sayede, kullanıcılar için sezgisel ve sihirli bir deneyim sunan bir sohbet arayüzü oluşturulur.
7. Daha iyi bir kullanıcı deneyimi için akış yanıtları
Bu adımda, Gemini'dan gelen akış yanıtlarını uygulayarak kullanıcı deneyimini iyileştireceksiniz. Yanıtın tamamının oluşturulmasını beklemek yerine, metin parçalarını ve işlev çağrılarını alındıkça işleyerek daha hızlı yanıt veren ve ilgi çekici bir uygulama oluşturursunuz.
Bu adımda ele alacağınız konular
- LLM destekli uygulamalarda akışın önemi
- Flutter uygulamasında akış şeklinde LLM yanıtları uygulama
- API'den gelen kısmi metin parçalarını işleme
- İleti çakışmalarını önlemek için görüşme durumunu yönetme
- Akış yanıtlarında işlev çağrılarını işleme
- Devam eden yanıtlar için görsel göstergeler oluşturma
Akış, LLM uygulamaları için neden önemlidir?
Uygulamadan önce, akış yanıtlarının LLM'lerle mükemmel kullanıcı deneyimleri oluşturmak için neden çok önemli olduğunu anlayalım:
Geliştirilmiş kullanıcı deneyimi
Yayın yanıtları, kullanıcı deneyimi açısından çeşitli önemli avantajlar sunar:
- Algılanan gecikme süresinde azalma: Kullanıcılar, tam yanıt için birkaç saniye beklemek yerine metnin hemen (genellikle 100-300 milisaniye içinde) görünmeye başladığını görür. Bu anında yanıt verme algısı, kullanıcı memnuniyetini önemli ölçüde artırır.
- Doğal konuşma ritmi: Metnin yavaş yavaş görünmesi, insanların iletişim kurma şeklini taklit ederek daha doğal bir diyalog deneyimi oluşturur.
- Aşamalı bilgi işleme: Kullanıcılar, bilgileri geldiği anda işlemeye başlayabilir. Böylece, tek seferde büyük bir metin bloğuyla karşılaşmazlar.
- Erken kesme fırsatı: Tam bir uygulamada, kullanıcılar LLM'nin faydalı olmayan bir yöne gittiğini görürlerse onu kesebilir veya yönlendirebilir.
- Etkinliğin görsel olarak onaylanması: Akış metni, sistemin çalıştığına dair anında geri bildirim vererek belirsizliği azaltır.
Teknik avantajlar
Akış, kullanıcı deneyimi iyileştirmelerinin yanı sıra teknik avantajlar da sunar:
- Erken işlev yürütme: İşlev çağrıları, akışta göründükleri anda yanıtın tamamlanmasını beklemeden algılanıp yürütülebilir.
- Artımlı kullanıcı arayüzü güncellemeleri: Yeni bilgiler geldikçe kullanıcı arayüzünüzü aşamalı olarak güncelleyebilir ve daha dinamik bir deneyim oluşturabilirsiniz.
- Sohbet durumu yönetimi: Akış, yanıtların ne zaman tamamlandığına ve ne zaman devam ettiğine dair net sinyaller vererek daha iyi bir durum yönetimi sağlar.
- Daha az zaman aşımı riski: Akış olmayan yanıtlarda, uzun süren oluşturma işlemleri bağlantı zaman aşımı riskine yol açar. Yayın, bağlantıyı erken kurar ve sürdürür.
Colorist uygulamanızda akış özelliğini uyguladığınızda kullanıcılar hem metin yanıtlarını hem de renk değişikliklerini daha hızlı görür. Bu da çok daha hızlı yanıt veren bir deneyim sunar.
Sohbet durumu yönetimi ekleme
İlk olarak, uygulamanın şu anda bir yayın yanıtı işleyip işlemediğini izlemek için bir durum sağlayıcı ekleyelim. lib/services/gemini_chat_service.dart
dosyanızı güncelleyin:
lib/services/gemini_chat_service.dart
import 'dart:async';
import 'package:colorist_ui/colorist_ui.dart';
import 'package:firebase_ai/firebase_ai.dart';
import 'package:flutter_riverpod/legacy.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../providers/gemini.dart';
import 'gemini_tools.dart';
part 'gemini_chat_service.g.dart';
final conversationStateProvider = StateProvider( // Add from here...
(ref) => ConversationState.idle,
); // To here.
class GeminiChatService {
GeminiChatService(this.ref);
final Ref ref;
Future<void> sendMessage(String message) async {
final chatSession = await ref.read(chatSessionProvider.future);
final conversationState = ref.read(conversationStateProvider); // Add this line
final chatStateNotifier = ref.read(chatStateProvider.notifier);
final logStateNotifier = ref.read(logStateProvider.notifier);
if (conversationState == ConversationState.busy) { // Add from here...
logStateNotifier.logWarning(
"Can't send a message while a conversation is in progress",
);
throw Exception(
"Can't send a message while a conversation is in progress",
);
}
final conversationStateNotifier = ref.read(
conversationStateProvider.notifier,
);
conversationStateNotifier.state = ConversationState.busy; // To here.
chatStateNotifier.addUserMessage(message);
logStateNotifier.logUserText(message);
final llmMessage = chatStateNotifier.createLlmMessage();
try { // Modify from here...
final responseStream = chatSession.sendMessageStream(
Content.text(message),
);
await for (final block in responseStream) {
await _processBlock(block, llmMessage.id);
} // To here.
} catch (e, st) {
logStateNotifier.logError(e, st: st);
chatStateNotifier.appendToMessage(
llmMessage.id,
"\nI'm sorry, I encountered an error processing your request. "
"Please try again.",
);
} finally {
chatStateNotifier.finalizeMessage(llmMessage.id);
conversationStateNotifier.state = ConversationState.idle; // Add this line.
}
}
Future<void> _processBlock( // Add from here...
GenerateContentResponse block,
String llmMessageId,
) async {
final chatSession = await ref.read(chatSessionProvider.future);
final chatStateNotifier = ref.read(chatStateProvider.notifier);
final logStateNotifier = ref.read(logStateProvider.notifier);
final blockText = block.text;
if (blockText != null) {
logStateNotifier.logLlmText(blockText);
chatStateNotifier.appendToMessage(llmMessageId, blockText);
}
if (block.functionCalls.isNotEmpty) {
final geminiTools = ref.read(geminiToolsProvider);
final responseStream = chatSession.sendMessageStream(
Content.functionResponses([
for (final functionCall in block.functionCalls)
FunctionResponse(
functionCall.name,
geminiTools.handleFunctionCall(
functionCall.name,
functionCall.args,
),
),
]),
);
await for (final response in responseStream) {
final responseText = response.text;
if (responseText != null) {
logStateNotifier.logLlmText(responseText);
chatStateNotifier.appendToMessage(llmMessageId, responseText);
}
}
}
} // To here.
}
@riverpod
GeminiChatService geminiChatService(Ref ref) => GeminiChatService(ref);
Yayın uygulamasını anlama
Bu kodun ne yaptığını inceleyelim:
- İleti dizisi durumu izleme:
conversationStateProvider
, uygulamanın şu anda bir yanıtı işleyip işlemediğini izler.- İşleme sırasında durum
idle
→busy
olarak değişir, ardından tekraridle
olur. - Bu, çakışabilecek birden fazla eşzamanlı isteği önler.
- Akış başlatma:
sendMessageStream()
, tam yanıtı içeren birFuture
yerine yanıt parçaları Akışı döndürür.- Her parça metin, işlev çağrıları veya her ikisini de içerebilir.
- Aşamalı işleme:
await for
, her parçayı gerçek zamanlı olarak işler.- Metin, akış efekti oluşturularak hemen kullanıcı arayüzüne eklenir.
- İşlev çağrıları algılandığı anda yürütülür.
- İşlev çağrısı işleme:
- Bir parçada işlev çağrısı algılandığında hemen yürütülür.
- Sonuçlar, başka bir akış aramasıyla LLM'ye geri gönderilir.
- LLM'nin bu sonuçlara verdiği yanıt da akış şeklinde işlenir.
- Hata işleme ve temizleme:
try
/catch
, güçlü hata işleme özelliği sunarfinally
bloğu, görüşme durumunun düzgün şekilde sıfırlanmasını sağlar.- Hata oluşsa bile mesaj her zaman sonlandırılır.
Bu uygulama, uygun sohbet durumunu korurken duyarlı ve güvenilir bir akış deneyimi oluşturur.
Görüşme durumunu bağlamak için ana ekranı güncelleme
Konuşma durumunu ana ekrana iletmek için lib/main.dart
dosyanızı değiştirin:
lib/main.dart
import 'package:colorist_ui/colorist_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'providers/gemini.dart';
import 'services/gemini_chat_service.dart';
void main() async {
runApp(ProviderScope(child: MainApp()));
}
class MainApp extends ConsumerWidget {
const MainApp({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final model = ref.watch(geminiModelProvider);
final conversationState = ref.watch(conversationStateProvider); // Add this line
return MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: model.when(
data: (data) => MainScreen(
conversationState: conversationState, // And this line
sendMessage: (text) {
ref.read(geminiChatServiceProvider).sendMessage(text);
},
),
loading: () => LoadingScreen(message: 'Initializing Gemini Model'),
error: (err, st) => ErrorScreen(error: err),
),
);
}
}
Buradaki temel değişiklik, conversationState
değerinin MainScreen
widget'ına aktarılmasıdır. MainScreen
(colorist_ui
paketi tarafından sağlanır), yanıt işlenirken metin girişini devre dışı bırakmak için bu durumu kullanır.
Bu sayede, kullanıcı arayüzünün görüşmenin mevcut durumunu yansıttığı tutarlı bir kullanıcı deneyimi oluşturulur.
Riverpod kodu oluşturma
Gerekli Riverpod kodunu oluşturmak için derleme çalıştırıcı komutunu çalıştırın:
dart run build_runner build --delete-conflicting-outputs
Akış yanıtlarını çalıştırma ve test etme
Uygulamanızı çalıştırın:
flutter run -d DEVICE
Şimdi de çeşitli renk açıklamalarıyla yayın davranışını test etmeyi deneyin. Şu gibi açıklamaları deneyin:
- "Alacakaranlıkta okyanusun koyu turkuaz rengini göster"
- "Tropik çiçekleri hatırlatan canlı bir mercan görmek istiyorum"
- "Eski askeri kamuflaj gibi soluk zeytin yeşili oluştur"
Ayrıntılı olarak yayın teknik akışı
Bir yanıt yayınlandığında tam olarak ne olduğuna bakalım:
Bağlantı oluşturma
sendMessageStream()
numarasını aradığınızda şunlar olur:
- Uygulama, Firebase AI Logic hizmetiyle bağlantı kurar.
- Kullanıcı isteği hizmete gönderilir.
- Sunucu, isteği işlemeye başlar.
- Akış bağlantısı açık kalır ve parçaları iletmeye hazır olur.
Parça aktarımı
Gemini içerik oluştururken parçalar akış üzerinden gönderilir:
- Sunucu, oluşturuldukça metin parçaları gönderir (genellikle birkaç kelime veya cümle).
- Gemini bir işlev çağrısı yapmaya karar verdiğinde işlev çağrısı bilgilerini gönderir.
- İşlev çağrılarının ardından ek metin parçaları gelebilir.
- Oluşturma işlemi tamamlanana kadar yayın devam eder.
Aşamalı işleme
Uygulamanız her parçayı artımlı olarak işler:
- Her metin parçası mevcut yanıta eklenir.
- İşlev çağrıları algılandığı anda yürütülür.
- Kullanıcı arayüzü hem metin hem de işlev sonuçlarıyla anlık olarak güncellenir.
- Durum, yanıtın hâlâ yayınlandığını göstermek için izlenir.
Yayın tamamlama
Oluşturma işlemi tamamlandığında:
- Akış, sunucu tarafından kapatıldı
await for
döngünüz doğal bir şekilde sonlanır.- İleti tamamlandı olarak işaretlenir.
- Görüşme durumu tekrar boşta olarak ayarlanır.
- Kullanıcı arayüzü, tamamlandı durumunu yansıtacak şekilde güncellenir.
Akış ve akış dışı karşılaştırması
Yayın yapmanın avantajlarını daha iyi anlamak için yayın yapma ve yapmama yaklaşımlarını karşılaştıralım:
En Boy Oranı | Yayın Dışı | Canlı Yayın |
Algılanan gecikme | Kullanıcı, yanıt tamamlanana kadar hiçbir şey görmez. | Kullanıcı, ilk kelimeleri milisaniyeler içinde görür. |
Kullanıcı deneyimi | Uzun bekleme süresinin ardından metnin aniden görünmesi | Doğal ve kademeli metin görünümü |
Durum yönetimi | Daha basit (mesajlar bekliyor veya tamamlandı) | Daha karmaşık (mesajlar akış durumunda olabilir) |
İşlev yürütme | Yalnızca yanıt tamamlandıktan sonra gerçekleşir. | Yanıt üretme sırasında oluşur. |
Uygulama karmaşıklığı | Daha kolay uygulanır | Ek durum yönetimi gerektirir |
Hatadan kurtarma | Ya hep ya hiç yanıtı | Kısmi yanıtlar yine de faydalı olabilir |
Kod karmaşıklığı | Daha az karmaşık | Akış işleme nedeniyle daha karmaşıktır. |
Colorist gibi bir uygulamada, özellikle oluşturulması birkaç saniye sürebilecek renk yorumları için akışın kullanıcı deneyimi avantajları, uygulama karmaşıklığından daha ağır basar.
Yayın kullanıcı deneyimiyle ilgili en iyi uygulamalar
Kendi LLM uygulamalarınızda akışı uygularken aşağıdaki en iyi uygulamaları göz önünde bulundurun:
- Net görsel göstergeler: Akış mesajlarını tamamlanmış mesajlardan ayıran net görsel işaretler sunun.
- Giriş engelleme: Birden fazla çakışan isteği önlemek için yayın sırasında kullanıcı girişini devre dışı bırakın.
- Hata kurtarma: Yayın kesintiye uğrarsa sorunsuz kurtarma sağlayacak şekilde kullanıcı arayüzünüzü tasarlayın.
- Durum geçişleri: Boşta, yayın ve tamamlandı durumları arasında sorunsuz geçişler sağlayın.
- İlerleme görselleştirme: Etkin işlemeyi gösteren küçük animasyonlar veya göstergeler kullanabilirsiniz.
- İptal seçenekleri: Tam bir uygulamada, kullanıcıların devam eden oluşturma işlemlerini iptal etmelerine olanak tanıyın.
- İşlev sonucu entegrasyonu: Kullanıcı arayüzünüzü, akışın ortasında görünen işlev sonuçlarını işleyecek şekilde tasarlayın.
- Performans optimizasyonu: Hızlı akış güncellemeleri sırasında kullanıcı arayüzünün yeniden oluşturulmasını en aza indirme
colorist_ui
paketi, bu en iyi uygulamaların çoğunu sizin için uygular ancak bunlar, herhangi bir akışlı LLM uygulaması için önemli hususlardır.
Sırada ne var?
Bir sonraki adımda, kullanıcılar geçmişten renk seçtiğinde Gemini'ı bilgilendirerek LLM senkronizasyonunu uygulayacaksınız. Bu sayede, LLM'nin uygulama durumunda kullanıcı tarafından başlatılan değişikliklerden haberdar olduğu daha tutarlı bir deneyim oluşturulur.
Sorun giderme
Akış işleme sorunları
Yayın işleme ile ilgili sorunlarla karşılaşırsanız:
- Belirtiler: Kısmi yanıtlar, eksik metin veya akışın aniden sonlanması
- Çözüm: Ağ bağlantısını kontrol edin ve kodunuzda uygun async/await kalıpları olduğundan emin olun.
- Teşhis: Yayın işleme ile ilgili hata mesajları veya uyarılar için günlük panelini inceleyin.
- Düzeltme: Tüm akış işlemlerinde
try
/catch
bloklarıyla uygun hata işleme kullanıldığından emin olun.
Eksik işlev çağrıları
Akışta işlev çağrıları algılanmıyorsa:
- Belirtiler: Metin görünüyor ancak renkler güncellenmiyor veya günlükte işlev çağrıları gösterilmiyor
- Çözüm: İşlev çağrılarını kullanmayla ilgili sistem istemi talimatlarını doğrulayın.
- Teşhis: İşlev çağrılarının alınıp alınmadığını görmek için günlük panelini kontrol edin.
- Düzeltme: Sistem isteminizi, LLM'ye
set_color
aracını kullanması için daha açık bir şekilde talimat verecek şekilde ayarlayın.
Genel hata işleme
Diğer sorunlar için:
- 1. adım: Hata mesajı olup olmadığını görmek için günlük panelini kontrol edin
- 2. adım: Firebase AI Logic bağlantısını doğrulayın
- 3. adım: Riverpod tarafından oluşturulan tüm kodların güncel olduğundan emin olun.
- 4. adım: Yayın uygulamasında eksik "await" ifadeleri olup olmadığını inceleyin
Öğrenilen temel kavramlar
- Daha hızlı yanıt veren bir kullanıcı deneyimi için Gemini API ile akış yanıtlarını uygulama
- Yayın etkileşimlerini düzgün şekilde işlemek için görüşme durumunu yönetme
- Gerçek zamanlı metin ve işlev çağrılarını geldikçe işleme
- Yayın sırasında artımlı olarak güncellenen duyarlı kullanıcı arayüzleri oluşturma
- Eşzamanlı akışları uygun eşzamansız kalıplarla işleme
- Yayın yanıtları sırasında uygun görsel geri bildirim sağlama
Yayın özelliğini uygulayarak Colorist uygulamanızın kullanıcı deneyimini önemli ölçüde iyileştirdiniz. Bu sayede, gerçekten etkileşimli bir arayüz oluşturarak daha duyarlı ve ilgi çekici bir deneyim sundunuz.
8. LLM Bağlam Senkronizasyonu
Bu bonus adımda, kullanıcılar geçmişten renk seçtiğinde Gemini'ı bilgilendirerek LLM bağlam senkronizasyonunu uygulayacaksınız. Bu sayede, LLM'nin yalnızca açık mesajları değil, arayüzdeki kullanıcı işlemlerini de bildiği daha tutarlı bir deneyim oluşturulur.
Bu adımda ele alacağınız konular
- Kullanıcı arayüzünüz ile LLM arasında LLM bağlamı senkronizasyonu oluşturma
- Kullanıcı arayüzü etkinliklerini LLM'nin anlayabileceği bağlama dönüştürme
- Kullanıcı işlemlerine göre sohbet bağlamını güncelleme
- Farklı etkileşim yöntemlerinde tutarlı bir deneyim oluşturma
- LLM'nin bağlam farkındalığını açık sohbet mesajlarının ötesine taşıma
LLM Bağlam Senkronizasyonunu Anlama
Geleneksel chatbot'lar yalnızca açık kullanıcı mesajlarına yanıt verir. Bu nedenle, kullanıcılar uygulamayla başka yollarla etkileşim kurduğunda bağlantı kesilir. LLM Bağlam Senkronizasyonu bu sınırlamayı giderir:
LLM Bağlam Senkronizasyonu neden önemlidir?
Kullanıcılar, kullanıcı arayüzü öğeleri (ör. geçmişten bir renk seçme) aracılığıyla uygulamanızla etkileşime girdiğinde, siz açıkça belirtmediğiniz sürece LLM ne olduğunu bilemez. LLM Bağlam Senkronizasyonu:
- Bağlamı korur: LLM'yi tüm alakalı kullanıcı işlemleri hakkında bilgilendirir.
- Tutarlılık oluşturur: LLM'nin kullanıcı arayüzü etkileşimlerini kabul ettiği tutarlı bir deneyim sunar.
- Zekayı geliştirir: LLM'nin tüm kullanıcı işlemlerine uygun şekilde yanıt vermesini sağlar.
- Kullanıcı deneyimini iyileştirir: Uygulamanın tamamının daha entegre ve duyarlı olmasını sağlar.
- Kullanıcıların çabasını azaltır: Kullanıcıların kullanıcı arayüzü işlemlerini manuel olarak açıklamasına gerek kalmaz.
Colorist uygulamanızda kullanıcılar geçmişten bir renk seçtiğinde Gemini'ın bu işlemi onaylamasını ve seçilen renk hakkında akıllıca yorumlar yapmasını istiyorsunuz. Böylece, sorunsuz ve farkında bir asistan yanılsaması korunacak.
Renk seçimi bildirimleri için Gemini sohbet hizmetini güncelleyin
İlk olarak, kullanıcı geçmişten bir renk seçtiğinde LLM'yi bilgilendirmek için GeminiChatService
öğesine bir yöntem eklersiniz. lib/services/gemini_chat_service.dart
dosyanızı güncelleyin:
lib/services/gemini_chat_service.dart
import 'dart:async';
import 'dart:convert'; // Add this import
import 'package:colorist_ui/colorist_ui.dart';
import 'package:firebase_ai/firebase_ai.dart';
import 'package:flutter_riverpod/legacy.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../providers/gemini.dart';
import 'gemini_tools.dart';
part 'gemini_chat_service.g.dart';
final conversationStateProvider = StateProvider(
(ref) => ConversationState.idle,
);
class GeminiChatService {
GeminiChatService(this.ref);
final Ref ref;
Future<void> notifyColorSelection(ColorData color) => sendMessage( // Add from here...
'User selected color from history: ${json.encode(color.toLLMContextMap())}',
); // To here.
Future<void> sendMessage(String message) async {
final chatSession = await ref.read(chatSessionProvider.future);
final conversationState = ref.read(conversationStateProvider);
final chatStateNotifier = ref.read(chatStateProvider.notifier);
final logStateNotifier = ref.read(logStateProvider.notifier);
if (conversationState == ConversationState.busy) {
logStateNotifier.logWarning(
"Can't send a message while a conversation is in progress",
);
throw Exception(
"Can't send a message while a conversation is in progress",
);
}
final conversationStateNotifier = ref.read(
conversationStateProvider.notifier,
);
conversationStateNotifier.state = ConversationState.busy;
chatStateNotifier.addUserMessage(message);
logStateNotifier.logUserText(message);
final llmMessage = chatStateNotifier.createLlmMessage();
try {
final responseStream = chatSession.sendMessageStream(
Content.text(message),
);
await for (final block in responseStream) {
await _processBlock(block, llmMessage.id);
}
} catch (e, st) {
logStateNotifier.logError(e, st: st);
chatStateNotifier.appendToMessage(
llmMessage.id,
"\nI'm sorry, I encountered an error processing your request. "
"Please try again.",
);
} finally {
chatStateNotifier.finalizeMessage(llmMessage.id);
conversationStateNotifier.state = ConversationState.idle;
}
}
Future<void> _processBlock(
GenerateContentResponse block,
String llmMessageId,
) async {
final chatSession = await ref.read(chatSessionProvider.future);
final chatStateNotifier = ref.read(chatStateProvider.notifier);
final logStateNotifier = ref.read(logStateProvider.notifier);
final blockText = block.text;
if (blockText != null) {
logStateNotifier.logLlmText(blockText);
chatStateNotifier.appendToMessage(llmMessageId, blockText);
}
if (block.functionCalls.isNotEmpty) {
final geminiTools = ref.read(geminiToolsProvider);
final responseStream = chatSession.sendMessageStream(
Content.functionResponses([
for (final functionCall in block.functionCalls)
FunctionResponse(
functionCall.name,
geminiTools.handleFunctionCall(
functionCall.name,
functionCall.args,
),
),
]),
);
await for (final response in responseStream) {
final responseText = response.text;
if (responseText != null) {
logStateNotifier.logLlmText(responseText);
chatStateNotifier.appendToMessage(llmMessageId, responseText);
}
}
}
}
}
@riverpod
GeminiChatService geminiChatService(Ref ref) => GeminiChatService(ref);
Önemli ekleme, notifyColorSelection
yöntemidir. Bu yöntem:
- Seçili rengi temsil eden bir
ColorData
nesnesi alır. - İletiye eklenebilecek bir JSON biçimine kodlar.
- Kullanıcı seçimini gösteren, özel olarak biçimlendirilmiş bir mesajı LLM'ye gönderir.
- Bildirimi işlemek için mevcut
sendMessage
yöntemini yeniden kullanır.
Bu yaklaşım, mevcut ileti işleme altyapınızı kullanarak ileti tekrarını önler.
Renk seçimi bildirimlerini bağlamak için ana uygulamayı güncelleyin
Şimdi, renk seçimi bildirimi işlevini ana ekrana iletmek için lib/main.dart
dosyanızı değiştirin:
lib/main.dart
import 'package:colorist_ui/colorist_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'providers/gemini.dart';
import 'services/gemini_chat_service.dart';
void main() async {
runApp(ProviderScope(child: MainApp()));
}
class MainApp extends ConsumerWidget {
const MainApp({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final model = ref.watch(geminiModelProvider);
final conversationState = ref.watch(conversationStateProvider);
return MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: model.when(
data: (data) => MainScreen(
conversationState: conversationState,
notifyColorSelection: (color) { // Add from here...
ref.read(geminiChatServiceProvider).notifyColorSelection(color);
}, // To here.
sendMessage: (text) {
ref.read(geminiChatServiceProvider).sendMessage(text);
},
),
loading: () => LoadingScreen(message: 'Initializing Gemini Model'),
error: (err, st) => ErrorScreen(error: err),
),
);
}
}
Temel değişiklik, kullanıcı arayüzü etkinliğini (geçmişten renk seçme) LLM bildirim sistemine bağlayan notifyColorSelection
geri çağırmanın eklenmesidir.
Sistem istemini güncelleme
Şimdi, LLM'ye renk seçimi bildirimlerine nasıl yanıt vereceğini bildirmek için sistem isteminizi güncellemeniz gerekiyor. assets/system_prompt.md
dosyanızı değiştirin:
assets/system_prompt.md
# Colorist System Prompt
You are a color expert assistant integrated into a desktop app called Colorist. Your job is to interpret natural language color descriptions and set the appropriate color values using a specialized tool.
## Your Capabilities
You are knowledgeable about colors, color theory, and how to translate natural language descriptions into specific RGB values. You have access to the following tool:
`set_color` - Sets the RGB values for the color display based on a description
## How to Respond to User Inputs
When users describe a color:
1. First, acknowledge their color description with a brief, friendly response
2. Interpret what RGB values would best represent that color description
3. Use the `set_color` tool to set those values (all values should be between 0.0 and 1.0)
4. After setting the color, provide a brief explanation of your interpretation
Example:
User: "I want a sunset orange"
You: "Sunset orange is a warm, vibrant color that captures the golden-red hues of the setting sun. It combines a strong red component with moderate orange tones."
[Then you would call the set_color tool with approximately: red=1.0, green=0.5, blue=0.25]
After the tool call: "I've set a warm orange with strong red, moderate green, and minimal blue components that is reminiscent of the sun low on the horizon."
## When Descriptions are Unclear
If a color description is ambiguous or unclear, please ask the user clarifying questions, one at a time.
## When Users Select Historical Colors
Sometimes, the user will manually select a color from the history panel. When this happens, you'll receive a notification about this selection that includes details about the color. Acknowledge this selection with a brief response that recognizes what they've done and comments on the selected color.
Example notification:
User: "User selected color from history: {red: 0.2, green: 0.5, blue: 0.8, hexCode: #3380CC}"
You: "I see you've selected an ocean blue from your history. This tranquil blue with a moderate intensity has a calming, professional quality to it. Would you like to explore similar shades or create a contrasting color?"
## Important Guidelines
- Always keep RGB values between 0.0 and 1.0
- Provide thoughtful, knowledgeable responses about colors
- When possible, include color psychology, associations, or interesting facts about colors
- Be conversational and engaging in your responses
- Focus on being helpful and accurate with your color interpretations
En önemli ekleme, "Kullanıcılar Geçmiş Renkleri Seçtiğinde" bölümüdür. Bu bölüm:
- LLM'ye geçmiş seçimi bildirimleri kavramını açıklar.
- Bu bildirimlerin nasıl göründüğüne dair bir örnek sunar.
- Uygun bir yanıt örneği gösterir.
- Seçimi onaylama ve renk hakkında yorum yapma beklentilerini belirler.
Bu, LLM'nin bu özel mesajlara nasıl uygun şekilde yanıt vereceğini anlamasına yardımcı olur.
Riverpod kodu oluşturma
Gerekli Riverpod kodunu oluşturmak için derleme çalıştırıcı komutunu çalıştırın:
dart run build_runner build --delete-conflicting-outputs
LLM bağlam senkronizasyonunu çalıştırma ve test etme
Uygulamanızı çalıştırın:
flutter run -d DEVICE
LLM bağlam senkronizasyonunu test etme şunları içerir:
- Öncelikle, renkleri sohbette açıklayarak birkaç renk oluşturun
- "Show me a vibrant purple" (Canlı bir mor rengi göster)
- "Orman yeşili istiyorum"
- "Parlak kırmızı rengini göster"
- Ardından, geçmiş şeridindeki renk küçük resimlerinden birini tıklayın.
Şunlara dikkat etmelisiniz:
- Seçilen renk ana ekranda görünür.
- Sohbette, renk seçimini belirten bir kullanıcı mesajı görünür.
- LLM, seçimi onaylayarak ve renk hakkında yorum yaparak yanıt verir.
- Etkileşimin tamamı doğal ve tutarlı olmalıdır.
Bu sayede, LLM'nin hem doğrudan mesajlardan hem de kullanıcı arayüzü etkileşimlerinden haberdar olduğu ve bunlara uygun şekilde yanıt verdiği sorunsuz bir deneyim sağlanır.
LLM Bağlam Senkronizasyonu'nun işleyiş şekli
Bu senkronizasyonun işleyiş şekliyle ilgili teknik ayrıntıları inceleyelim:
Veri Akışı
- Kullanıcı işlemi: Kullanıcı, geçmiş şeridinde bir rengi tıklar.
- Kullanıcı arayüzü etkinliği:
MainScreen
widget'ı bu seçimi algılar - Geri çağırma yürütmesi:
notifyColorSelection
geri çağırması tetiklenir. - Mesaj oluşturma: Renk verileriyle özel olarak biçimlendirilmiş bir mesaj oluşturulur.
- LLM işleme: Mesaj, biçimi tanıyan Gemini'a gönderilir.
- Bağlama uygun yanıt: Gemini, sistem istemine göre uygun şekilde yanıt verir.
- Kullanıcı arayüzü güncellemesi: Yanıt, sohbet içinde gösterilerek tutarlı bir deneyim sunuluyor.
Veri serileştirme
Bu yaklaşımın önemli bir yönü, renk verilerini nasıl serileştirdiğinizdir:
'User selected color from history: ${json.encode(color.toLLMContextMap())}'
toLLMContextMap()
yöntemi (colorist_ui
paketi tarafından sağlanır), ColorData
nesnesini LLM'nin anlayabileceği anahtar özelliklere sahip bir haritaya dönüştürür. Bu ekip genellikle şu kişilerden oluşur:
- RGB değerleri (kırmızı, yeşil, mavi)
- Onaltılık kod gösterimi
- Renk ile ilişkili herhangi bir ad veya açıklama
Bu verileri tutarlı bir şekilde biçimlendirip iletiye ekleyerek LLM'nin uygun şekilde yanıt vermek için ihtiyaç duyduğu tüm bilgilere sahip olmasını sağlarsınız.
LLM Bağlam Senkronizasyonu'nun daha geniş uygulama alanları
Kullanıcı arayüzü etkinlikleri hakkında LLM'yi bilgilendirme modeli, renk seçiminin ötesinde çok sayıda uygulamaya sahiptir:
Diğer kullanım alanları
- Filtre değişiklikleri: Kullanıcılar verilere filtre uyguladığında LLM'yi bilgilendirin.
- Gezinme etkinlikleri: Kullanıcılar farklı bölümlere gittiğinde LLM'yi bilgilendirir.
- Seçim değişiklikleri: Kullanıcılar listelerden veya ızgaralardan öğe seçtiğinde LLM'yi güncelleme
- Tercih güncellemeleri: Kullanıcılar ayarları veya tercihleri değiştirdiğinde LLM'ye bilgi verin.
- Veri manipülasyonu: Kullanıcılar veri eklediğinde, düzenlediğinde veya sildiğinde LLM'yi bilgilendirin.
Her durumda, kalıp aynı kalır:
- Kullanıcı arayüzü etkinliğini algılama
- Alakalı verileri serileştirme
- LLM'ye özel olarak biçimlendirilmiş bir bildirim gönderme
- Sistem istemi aracılığıyla LLM'yi uygun şekilde yanıt vermeye yönlendirme
LLM bağlam senkronizasyonu için en iyi uygulamalar
Uygulamanıza bağlı olarak, etkili LLM bağlam senkronizasyonu için bazı en iyi uygulamaları aşağıda bulabilirsiniz:
1. Tutarlı format
LLM'nin kolayca tanımlayabilmesi için bildirimlerde tutarlı bir biçim kullanın:
"User [action] [object]: [structured data]"
2. Zengin bağlam
LLM'nin akıllıca yanıt vermesi için bildirimlere yeterli ayrıntı ekleyin. Renkler için bu; RGB değerleri, onaltılık renk kodları ve diğer alakalı özellikler anlamına gelir.
3. Net talimatlar
Sistem isteminde bildirimlerin nasıl işleneceğiyle ilgili açık talimatlar verin. İdeal olarak örnekler de ekleyin.
4. Doğal entegrasyon
Bildirimleri, teknik kesintiler olarak değil, görüşmede doğal bir şekilde akacak şekilde tasarlayın.
5. Seçici bildirim
LLM'yi yalnızca ileti dizisiyle alakalı işlemler hakkında bilgilendirin. Her kullanıcı arayüzü etkinliğinin bildirilmesi gerekmez.
Sorun giderme
Bildirim sorunları
Büyük dil modeli, renk seçimlerine düzgün şekilde yanıt vermiyorsa:
- Bildirim mesajı biçiminin, sistem isteminde açıklananlarla eşleştiğini kontrol edin.
- Renk verilerinin düzgün şekilde serileştirildiğini doğrulayın.
- Sistem isteminin, seçimlerin işlenmesiyle ilgili net talimatlar içerdiğinden emin olun.
- Bildirim gönderirken sohbet hizmetinde hata olup olmadığını kontrol edin.
Bağlam yönetimi
LLM bağlamı kaybediyor gibi görünüyorsa:
- Sohbet oturumunun düzgün şekilde sürdürüldüğünü kontrol edin.
- Sohbet durumlarının doğru şekilde geçiş yaptığını doğrulayın.
- Bildirimlerin aynı sohbet oturumu üzerinden gönderildiğinden emin olun.
Genel sorunlar
Genel sorunlar için:
- Günlüklerde hata veya uyarı olup olmadığını inceleyin.
- Firebase AI Logic bağlantısını doğrulama
- İşlev parametrelerinde tür uyuşmazlığı olup olmadığını kontrol edin.
- Riverpod tarafından oluşturulan tüm kodların güncel olduğundan emin olun.
Öğrenilen temel kavramlar
- Kullanıcı arayüzü ile LLM arasında LLM bağlamı senkronizasyonu oluşturma
- Kullanıcı arayüzü etkinliklerini LLM dostu bağlama dönüştürme
- Farklı etkileşim kalıpları için LLM davranışını yönlendirme
- Mesaj ve mesaj dışı etkileşimlerde tutarlı bir deneyim oluşturma
- LLM'nin daha geniş uygulama durumu hakkındaki farkındalığını artırma
LLM Bağlam Senkronizasyonu'nu uygulayarak LLM'nin yalnızca bir metin oluşturucu değil, bilinçli ve duyarlı bir asistan gibi davrandığı, gerçekten entegre bir deneyim oluşturmuş olursunuz. Bu kalıp, daha doğal ve sezgisel yapay zeka destekli arayüzler oluşturmak için sayısız başka uygulamaya uygulanabilir.
9. Tebrikler!
Colorist codelab'ini başarıyla tamamladınız. 🎉
Oluşturduklarınız
Doğal dil renk açıklamalarını yorumlamak için Google'ın Gemini API'sini entegre eden, tam işlevsel bir Flutter uygulaması oluşturdunuz. Uygulamanız artık şunları yapabilir:
- "Gün batımı turuncusu" veya "derin okyanus mavisi" gibi doğal dil açıklamalarını işleme
- Bu açıklamaları akıllı bir şekilde RGB değerlerine çevirmek için Gemini'ı kullanın.
- Yorumlanan renkleri, akış yanıtlarıyla anlık olarak gösterme
- Hem sohbet hem de kullanıcı arayüzü öğeleri aracılığıyla kullanıcı etkileşimlerini yönetme
- Farklı etkileşim yöntemlerinde bağlamsal farkındalığı koruma
Şimdi beni ne bekliyor?
Gemini'ı Flutter ile entegre etmenin temel bilgilerini öğrendiğinize göre yolculuğunuza devam etmek için yapabilecekleriniz:
Colorist uygulamanızı geliştirme
- Renk paletleri: Tamamlayıcı veya eşleşen renk şemaları oluşturma işlevi ekleyin.
- Ses girişi: Sözlü renk açıklamaları için konuşma tanımayı entegre edin.
- Geçmiş yönetimi: Renk kümelerini adlandırma, düzenleme ve dışa aktarma seçenekleri ekleyin.
- Özel istem: Kullanıcıların sistem istemlerini özelleştirebileceği bir arayüz oluşturun.
- Gelişmiş analizler: En iyi sonuç veren veya zorluklara neden olan açıklamaları izleyin.
Diğer Gemini özelliklerini keşfedin
- Çok formatlı girişler: Fotoğraflardan renkleri almak için resim girişleri ekleyin.
- İçerik üretme: Açıklama veya hikaye gibi renkle ilgili içerikler üretmek için Gemini'ı kullanın.
- İşlev çağırma geliştirmeleri: Birden fazla işlevle daha karmaşık araç entegrasyonları oluşturun.
- Güvenlik ayarları: Farklı güvenlik ayarlarını ve bunların yanıtlara etkisini keşfedin.
Bu kalıpları diğer alanlara uygulama
- Belge analizi: Belgeleri anlayıp analiz edebilen uygulamalar oluşturun
- Yaratıcı yazma yardımı: LLM destekli önerilerle yazma araçları oluşturun
- Görev otomasyonu: Doğal dili otomatik görevlere çeviren uygulamalar tasarlama
- Bilgiye dayalı uygulamalar: Belirli alanlarda uzman sistemler oluşturun.
Kaynaklar
Öğrenmeye devam etmenize yardımcı olacak bazı değerli kaynakları aşağıda bulabilirsiniz:
Resmi belgeler
İstem yazma kursu ve kılavuzu
Topluluk
Observable Flutter Agentic serisi
59. bölümde Craig Labenz ve Andrew Brogden, bu codelab'i inceliyor ve uygulama geliştirme sürecindeki ilginç noktaları vurguluyor.
60. bölümde Craig ve Andrew'a tekrar katılarak codelab uygulamasını yeni özelliklerle genişletmelerini ve LLM'lerin isteneni yapmasını sağlamak için verdikleri mücadeleyi izleyin.
61. bölümde Craig, Chris Sells ile birlikte haber başlıklarını analiz etmeye ve ilgili resimleri oluşturmaya yönelik yeni bir yaklaşım sunuyor.
Geri bildirim
Bu codelab ile ilgili deneyiminizi bizimle paylaşmanızı çok isteriz. Lütfen aşağıdaki yöntemlerden biriyle geri bildirimde bulunun:
Bu codelab'i tamamladığınız için teşekkür ederiz. Flutter ve yapay zekanın kesişim noktasındaki heyecan verici olanakları keşfetmeye devam etmenizi umuyoruz.