1. Giriş
Bu codelab'de, Google Cloud'da Vertex AI'da barındırılan Gemini Büyük Dil Modeli (LLM) üzerinde odaklanılmaktadır. Vertex AI, Google Cloud'daki tüm makine öğrenimi ürünlerini, hizmetlerini ve modellerini kapsayan bir platformdur.
LangChain4j çerçevesini kullanarak Gemini API ile etkileşimde bulunmak için Java'yı kullanacaksınız. Soru yanıtlama, fikir oluşturma, varlık ve yapılandırılmış içerik ayıklama, artırılmış oluşturma getirme ve işlev çağrısı için LLM'den yararlanmak üzere somut örnekler üzerinden geçeceksiniz.
Üretken yapay zeka nedir?
Üretken yapay zeka; metin, resim, müzik, ses ve video gibi yeni içerikler oluşturmak için yapay zekanın kullanılmasını ifade eder.
Üretken yapay zeka, çoklu görev ve özetleme, soru-cevap, sınıflandırma gibi kullanıma hazır görevleri gerçekleştirebilen büyük dil modelleri (LLM) tarafından desteklenir. Minimum eğitimle, temel modeller çok az örnek veriyle hedeflenmiş kullanım alanları için uyarlanabilir.
Üretken yapay zeka nasıl çalışır?
Üretken yapay zeka, insan tarafından oluşturulan içeriklerden oluşan bir veri kümesindeki kalıpları ve ilişkileri öğrenmek için makine öğrenimi (ML) modelinden yararlanır. Ardından öğrenilen kalıpları kullanarak yeni içerikler üretir.
Üretken yapay zeka modelini eğitmenin en yaygın yolu, gözetimli öğrenmeden yararlanmaktır. Modele, insan tarafından oluşturulan bir dizi içerik ve ilgili etiketler verilir. Daha sonra, gerçek kişiler tarafından oluşturulan içeriklere benzer içerikler üretmeyi öğrenir.
Yaygın olarak kullanılan üretken yapay zeka uygulamaları nelerdir?
Üretken yapay zeka şu amaçlarla kullanılabilir:
- Gelişmiş sohbet ve arama deneyimleriyle müşteri etkileşimlerini iyileştirin.
- Sohbet arayüzleri ve özetler sayesinde çok sayıda yapılandırılmamış veriyi keşfedin.
- Teklif taleplerini yanıtlama, pazarlama içeriğini farklı dillerde yerelleştirme, müşteri sözleşmelerini uygunluk açısından kontrol etme gibi tekrar eden görevlerde destek olun.
Google Cloud hangi üretken yapay zeka tekliflerini sunuyor?
Vertex AI sayesinde makine öğrenimi konusunda çok az uzmanlaşmış veya hiç bilgi sahibi olmadan temel modellerle etkileşimde bulunabilir, modelleri özelleştirebilir ve uygulamanıza yerleştirebilirsiniz. Model Garden'da temel modellerine erişebilir, Vertex AI Studio'daki basit bir kullanıcı arayüzüyle model ayarlarını yapabilir veya modelleri bir veri bilimi not defterinde kullanabilirsiniz.
Vertex AI Arama ve Sohbet, geliştiricilere üretken yapay zeka destekli arama motorları ve chatbot'lar geliştirmenin en hızlı yolunu sunar.
Gemini tarafından desteklenen Google Cloud için Gemini, Google Cloud ve IDE'lerde daha fazla işi daha kısa sürede yapmanıza yardımcı olan yapay zeka destekli bir ortak çalışandır. Gemini Code Assist; kod tamamlama, kod oluşturma ve kod açıklamaları sunar. Ayrıca sohbet ederek teknik sorular sormanıza da olanak tanır.
Gemini nedir?
Gemini, Google DeepMind tarafından geliştirilen ve çok modlu kullanım alanları için tasarlanmış bir üretken yapay zeka modeli ailesidir. Çok modlu; metin, kod, resim ve ses gibi farklı içerik türlerini işleyip oluşturabileceği anlamına gelir.
Gemini'ın farklı varyantları ve boyutları vardır:
- Gemini Ultra: Karmaşık görevler için en büyük ve en yetenekli sürüm.
- Gemini Flash: Yüksek hacimli görevler için optimize edilmiş, en hızlı ve en uygun maliyetli.
- Gemini Pro: Orta boyutlu, çeşitli görevlerde ölçeklendirme için optimize edilmiş.
- Gemini Nano: Cihazdaki görevler için tasarlanmış en verimli model.
Temel Özellikler:
- Çok modluluk: Gemini'ın birden fazla bilgi biçimini anlayıp işleme becerisi, geleneksel yalnızca metin dili modellerinin ötesinde önemli bir adımdır.
- Performans: Gemini Ultra, birçok karşılaştırmada mevcut en gelişmiş teknolojilerden daha iyi performans gösterir ve zorlu MMLU (Massive Multitask Language Understanding) karşılaştırmasında gerçek kişi olan uzmanları geride bırakan ilk model olmuştur.
- Esneklik: Farklı Gemini boyutları, büyük ölçekli araştırmalardan mobil cihazlarda dağıtıma kadar çeşitli kullanım alanlarına uyarlanabilir.
Java'dan Vertex AI'da Gemini ile nasıl etkileşimde bulunursunuz?
Bunun için iki seçeneğiniz bulunmaktadır:
- Resmi Vertex AI Java API for Gemini kitaplığı.
- LangChain4j çerçevesidir.
Bu codelab'de LangChain4j çerçevesini kullanacaksınız.
LangChain4j çerçevesi nedir?
LangChain4j çerçevesi, LLM'nin kendisi gibi çeşitli bileşenlerin yanı sıra vektör veritabanları (anlamsal aramalar için), belge yükleyiciler ve ayırıcılar (belgeleri analiz etmek ve bunlardan bilgi edinmek için), çıkış ayrıştırıcıları ve daha fazlasını düzenleyerek Java uygulamalarınıza LLM'leri entegre etmek için kullanılan açık kaynak bir kitaplıktır.
Proje, LangChain Python projesinden esinlenerek Java geliştiricilerine hizmet sunmayı amaçladı.
Neler öğreneceksiniz?
- Gemini ve LangChain4j'i kullanmak için bir Java projesi oluşturma
- İlk isteminizi Gemini'a programatik olarak gönderme
- Gemini'daki yanıtları akış şeklinde gösterme
- Kullanıcı ile Gemini arasında sohbet oluşturma
- Gemini'ın hem metin hem de resim göndererek çok modlu bir bağlamda nasıl kullanılacağı
- Yapılandırılmamış içerikten kullanışlı yapılandırılmış bilgileri ayıklama
- İstem şablonlarını değiştirme
- Yaklaşım analizi gibi metin sınıflandırmaları yapma
- Kendi dokümanlarınızla sohbet etme (Alma Artırılmış Oluşturma)
- İşlev çağrısı ile chatbot'larınızı genişletme
- Gemma'yı Ollama ve TestContainers ile yerel olarak kullanma
Gerekenler
- Java programlama dili bilgisi
- Bir Google Cloud projesi
- Chrome veya Firefox gibi bir tarayıcı
2. Kurulum ve şartlar
Kendi hızınızda ortam kurulumu
- Google Cloud Console'da oturum açıp yeni bir proje oluşturun veya mevcut bir projeyi yeniden kullanın. Gmail veya Google Workspace hesabınız yoksa hesap oluşturmanız gerekir.
- Proje adı, bu projenin katılımcıları için görünen addır. Google API'leri tarafından kullanılmayan bir karakter dizesidir. İstediğiniz zaman güncelleyebilirsiniz.
- Proje Kimliği, tüm Google Cloud projelerinde benzersizdir ve değiştirilemez (belirlendikten sonra değiştirilemez). Cloud Console, otomatik olarak benzersiz bir dize oluşturur. bunun ne olduğunu umursamıyorsunuz. Çoğu codelab'de proje kimliğinizi (genellikle
PROJECT_ID
olarak tanımlanır) belirtmeniz gerekir. Oluşturulan kimliği beğenmezseniz rastgele bir kimlik daha oluşturabilirsiniz. Alternatif olarak, kendi ölçümünüzü deneyip mevcut olup olmadığına bakabilirsiniz. Bu adımdan sonra değiştirilemez ve proje süresince kalır. - Bilginiz olması açısından, bazı API'lerin kullandığı üçüncü bir değer, yani Proje Numarası daha vardır. Bu değerlerin üçü hakkında daha fazla bilgiyi belgelerde bulabilirsiniz.
- Sonraki adımda, Cloud kaynaklarını/API'lerini kullanmak için Cloud Console'da faturalandırmayı etkinleştirmeniz gerekir. Bu codelab'i çalıştırmanın maliyeti, yüksek değildir. Bu eğitim dışında faturalandırmanın tekrarlanmasını önlemek amacıyla kaynakları kapatmak için oluşturduğunuz kaynakları silebilir veya projeyi silebilirsiniz. Yeni Google Cloud kullanıcıları 300 ABD doları değerindeki ücretsiz denemeden yararlanabilir.
Cloud Shell'i başlatma
Google Cloud, dizüstü bilgisayarınızdan uzaktan çalıştırılabilse de bu codelab'de Cloud'da çalışan bir komut satırı ortamı olan Cloud Shell'i kullanacaksınız.
Cloud Shell'i etkinleştirme
- Cloud Console'da, Cloud Shell'i etkinleştir simgesini tıklayın.
Cloud Shell'i ilk kez başlatıyorsanız ne olduğunu açıklayan bir ara ekran gösterilir. Ara bir ekran görüntülendiyse Devam'ı tıklayın.
Temel hazırlık ve Cloud Shell'e bağlanmak yalnızca birkaç dakika sürer.
Gereken tüm geliştirme araçları bu sanal makinede yüklüdür. 5 GB boyutunda kalıcı bir ana dizin sunar ve Google Cloud'da çalışarak ağ performansını ve kimlik doğrulamasını büyük ölçüde iyileştirir. Bu codelab'deki çalışmalarınızın tamamı olmasa bile büyük bir kısmı tarayıcıyla yapılabilir.
Cloud Shell'e bağlandıktan sonra kimliğinizin doğrulandığını ve projenin proje kimliğinize ayarlandığını göreceksiniz.
- Kimlik doğrulamanızın tamamlandığını onaylamak için Cloud Shell'de aşağıdaki komutu çalıştırın:
gcloud auth list
Komut çıkışı
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
- gcloud komutunun projenizi bildiğini onaylamak için Cloud Shell'de aşağıdaki komutu çalıştırın:
gcloud config list project
Komut çıkışı
[core] project = <PROJECT_ID>
Doğru değilse aşağıdaki komutla ayarlayabilirsiniz:
gcloud config set project <PROJECT_ID>
Komut çıkışı
Updated property [core/project].
3. Geliştirme ortamınızı hazırlama
Bu codelab'de, Java programlarınızı geliştirmek için Cloud Shell terminalini ve Cloud Shell düzenleyicisini kullanacaksınız.
Vertex AI API'lerini etkinleştirme
Google Cloud konsolunda projenizin adının, Google Cloud konsolunuzun en üst kısmında gösterildiğinden emin olun. Açık değilse Proje Seç'i tıklayarak Proje Seçici'yi açın ve istediğiniz projeyi seçin.
Vertex AI API'lerini Google Cloud Console'un Vertex AI bölümünden veya Cloud Shell terminalinden etkinleştirebilirsiniz.
Google Cloud konsolundan etkinleştirmek için önce Google Cloud Console menüsünün Vertex AI bölümüne gidin:
Vertex AI kontrol panelinde Enable All Recommended APIs'ı (Önerilen Tüm API'leri Etkinleştir) tıklayın.
Bu işlem çeşitli API'leri etkinleştirir ancak codelab için en önemli olan aiplatform.googleapis.com
API'dir.
Alternatif olarak, bu API'yi aşağıdaki komutla Cloud Shell terminalinden de etkinleştirebilirsiniz:
gcloud services enable aiplatform.googleapis.com
GitHub deposunu klonlama
Cloud Shell terminalinde bu codelab'e ait depoyu klonlayın:
git clone https://github.com/glaforge/gemini-workshop-for-java-developers.git
Projenin çalıştırılmaya hazır olup olmadığını kontrol etmek için "Hello World" komutunu çalıştırmayı deneyebilirsiniz çok önemli.
En üst düzey klasörde olduğunuzdan emin olun:
cd gemini-workshop-for-java-developers/
Gradle sarmalayıcıyı oluşturun:
gradle wrapper
gradlew
ile çalıştır:
./gradlew run
Aşağıdaki çıkışı göreceksiniz:
.. > Task :app:run Hello World!
Cloud Editor'ı açma ve kurma
Kodu Cloud Shell'deki Cloud Code Editor ile açın:
Cloud Code Editor'da File
-> öğesini seçerek codelab kaynak klasörünü açın. Open Folder
ve codelab kaynak klasörünün (ör. /home/username/gemini-workshop-for-java-developers/
) bilgileri gösterilir.
Java için Gradle'ı yükleme
Bulut kod düzenleyicinin Gradle ile düzgün çalışmasını sağlamak amacıyla Gradle for Java uzantısını yükleyin.
İlk olarak Java Projeleri bölümüne gidin ve artı işaretine basın:
Gradle for Java
öğesini seçin:
Install Pre-Release
sürümünü seçin:
Uzantıyı yükledikten sonra Disable
ve Uninstall
düğmelerini göreceksiniz:
Son olarak, yeni ayarların uygulanması için çalışma alanını temizleyin:
Bu işlem sırasında atölyeyi yeniden yükleyip silmeniz istenir. Devam edin ve Reload and delete
öğesini seçin:
App.Java gibi dosyalardan birini açarsanız artık düzenleyicinin söz dizimi vurgulamayla düzgün bir şekilde çalıştığını görmeniz gerekir:
Artık Gemini ile bazı örnekleri çalıştırmaya hazırsınız.
Ortam değişkenlerini ayarlama
Terminal
-> öğesini seçerek Cloud Code Editor'da yeni bir terminal açın. New Terminal
. Kod örneklerini çalıştırmak için gerekli iki ortam değişkenini ayarlayın:
- PROJECT_ID: Google Cloud projenizin kimliği
- LOCATION: Gemini modelinin dağıtıldığı bölge
Değişkenleri aşağıdaki gibi dışa aktarın:
export PROJECT_ID=$(gcloud config get-value project) export LOCATION=us-central1
4. Gemini modeline ilk çağrı
Proje düzgün şekilde ayarlandığına göre artık Gemini API'yi çağırmanın zamanı geldi.
app/src/main/java/gemini/workshop
dizinindeki QA.java
kitaplığına göz atın:
package gemini.workshop;
import dev.langchain4j.model.vertexai.VertexAiGeminiChatModel;
import dev.langchain4j.model.chat.ChatLanguageModel;
public class QA {
public static void main(String[] args) {
ChatLanguageModel model = VertexAiGeminiChatModel.builder()
.project(System.getenv("PROJECT_ID"))
.location(System.getenv("LOCATION"))
.modelName("gemini-1.5-flash-001")
.build();
System.out.println(model.generate("Why is the sky blue?"));
}
}
Bu ilk örnekte, ChatModel
arayüzünü uygulayan VertexAiGeminiChatModel
sınıfını içe aktarmanız gerekir.
main
yönteminde, VertexAiGeminiChatModel
için oluşturucuyu kullanarak sohbet dili modelini yapılandırır ve şunları belirtirsiniz:
- Proje
- Konum
- Model adı (
gemini-1.5-flash-001
).
Dil modeli hazır olduğuna göre artık generate()
yöntemini çağırabilir ve isteminizi, sorunuzu veya LLM'ye gönderilecek talimatları iletebilirsiniz. Burada, gökyüzünü mavi yapan şeylerle ilgili basit bir soru soruyorsunuz.
Farklı soruları veya görevleri denemek için bu istemi değiştirebilirsiniz.
Kaynak kodu kök klasöründe örneği çalıştırın:
./gradlew run -q -DjavaMainClass=gemini.workshop.QA
Şuna benzer bir çıkış görürsünüz:
The sky appears blue because of a phenomenon called Rayleigh scattering. When sunlight enters the atmosphere, it is made up of a mixture of different wavelengths of light, each with a different color. The different wavelengths of light interact with the molecules and particles in the atmosphere in different ways. The shorter wavelengths of light, such as those corresponding to blue and violet light, are more likely to be scattered in all directions by these particles than the longer wavelengths of light, such as those corresponding to red and orange light. This is because the shorter wavelengths of light have a smaller wavelength and are able to bend around the particles more easily. As a result of Rayleigh scattering, the blue light from the sun is scattered in all directions, and it is this scattered blue light that we see when we look up at the sky. The blue light from the sun is not actually scattered in a single direction, so the color of the sky can vary depending on the position of the sun in the sky and the amount of dust and water droplets in the atmosphere.
Tebrikler, Gemini'ı ilk kez kullandınız.
Yanıt akışı
Yanıtın bir seferde, birkaç saniye sonra verildiğini fark ettiniz mi? Akış yanıtı varyantı sayesinde kademeli olarak da yanıt alabilirsiniz. Akış yanıtı olan model, kullanılabilir hale geldikçe yanıtı parça parça döndürür.
Bu codelab'de canlı olmayan yanıtı uygulayacağız ancak nasıl yapılacağını görmek için akış yanıtına göz atalım.
app/src/main/java/gemini/workshop
dizinindeki StreamQA.java
bölümünde akış yanıtını iş başında görebilirsiniz:
package gemini.workshop;
import dev.langchain4j.model.chat.StreamingChatLanguageModel;
import dev.langchain4j.model.vertexai.VertexAiGeminiStreamingChatModel;
import dev.langchain4j.model.StreamingResponseHandler;
public class StreamQA {
public static void main(String[] args) {
StreamingChatLanguageModel model = VertexAiGeminiStreamingChatModel.builder()
.project(System.getenv("PROJECT_ID"))
.location(System.getenv("LOCATION"))
.modelName("gemini-1.5-flash-001")
.build();
model.generate("Why is the sky blue?", new StreamingResponseHandler<>() {
@Override
public void onNext(String text) {
System.out.println(text);
}
@Override
public void onError(Throwable error) {
error.printStackTrace();
}
});
}
}
Bu kez, StreamingChatLanguageModel
arayüzünü uygulayan VertexAiGeminiStreamingChatModel
akış sınıfı varyantlarını içe aktarıyoruz. Ayrıca, bir StreamingResponseHandler
numarası da gereklidir.
Bu kez, generate()
yönteminin imzası biraz farklıdır. Dönüş türü, dize döndürmek yerine geçersizdir. İsteme ek olarak, bir akış yanıtı işleyicisi iletmeniz gerekir. Burada, arayüzü, onNext(String text)
ve onError(Throwable error)
olmak üzere iki yöntemle anonim bir iç sınıf oluşturarak uygularsınız. İlk yanıt, yanıtın yeni bir parçası her kullanılabilir olduğunda çağrılır; ikinci yanıt ise yalnızca bir hata oluşursa çağrılır.
Çalıştırma:
./gradlew run -q -DjavaMainClass=gemini.workshop.StreamQA
Önceki sınıfa benzer bir yanıt alacaksınız ancak bu kez tam cevabın gösterilmesini beklemek yerine yanıtın kabuğunuzda kademeli olarak göründüğünü fark edeceksiniz.
Ek yapılandırma
Yapılandırma için yalnızca projeyi, konumu ve model adını tanımladık. Ancak model için belirtebileceğiniz başka parametreler de var:
temperature(Float temp)
: Yanıtın nasıl reklam öğesi olmasını istediğinizi tanımlamak için (0 az reklam öğesi ve genellikle daha gerçekçi, 1 ise daha fazla reklam öğesi içindir)topP(Float topP)
— Toplam olasılığı bu kayan nokta sayısına denk gelen olası kelimeleri seçmek için (0 ile 1 arasında)topK(Integer topK)
— metin tamamlama için olası maksimum kelime sayısı arasından bir kelimeyi rastgele seçmek için (1 ile 40 arasında)maxOutputTokens(Integer max)
: Modelin verdiği yanıtın maksimum uzunluğunu belirtmek için (genellikle 4 jeton yaklaşık 3 kelimeyi temsil eder)maxRetries(Integer retries)
: İstek başına zaman kotasını aşıyorsanız veya platformla ilgili teknik sorunlar yaşanıyorsa modelin aramayı 3 kez yeniden denemesini sağlayabilirsiniz
Şimdiye kadar Gemini'a tek bir soru sordunuz ancak çok dönüşlü bir sohbet de yapabilirsiniz. Bu konuyu bir sonraki bölümde keşfedeceksiniz.
5. Gemini ile sohbet et
Önceki adımda tek bir soru sormuştunuz. Artık kullanıcı ile LLM arasında gerçek bir konuşma yapmanın zamanı geldi. Her soru ve yanıt öncekilerin üzerine koyarak gerçek bir tartışma oluşturabilir.
app/src/main/java/gemini/workshop
klasöründeki Conversation.java
klasörüne göz atın:
package gemini.workshop;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.vertexai.VertexAiGeminiChatModel;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.service.AiServices;
import java.util.List;
public class Conversation {
public static void main(String[] args) {
ChatLanguageModel model = VertexAiGeminiChatModel.builder()
.project(System.getenv("PROJECT_ID"))
.location(System.getenv("LOCATION"))
.modelName("gemini-1.5-flash-001")
.build();
MessageWindowChatMemory chatMemory = MessageWindowChatMemory.builder()
.maxMessages(20)
.build();
interface ConversationService {
String chat(String message);
}
ConversationService conversation =
AiServices.builder(ConversationService.class)
.chatLanguageModel(model)
.chatMemory(chatMemory)
.build();
List.of(
"Hello!",
"What is the country where the Eiffel tower is situated?",
"How many inhabitants are there in that country?"
).forEach( message -> {
System.out.println("\nUser: " + message);
System.out.println("Gemini: " + conversation.chat(message));
});
}
}
Bu sınıfta dikkat çekici birkaç yeni içe aktarma:
MessageWindowChatMemory
- Konuşmanın çok dönüşlü yönünü ele almanıza ve önceki soru ve yanıtların yerel hafızada kalmasına yardımcı olacak bir sınıfAiServices
: Sohbet modeliyle sohbet belleğini birbirine bağlayacak sınıf
Ana yöntemde modeli, sohbet belleğini ve yapay zeka hizmetini kuracaksınız. Model; proje, konum ve model adı bilgileriyle her zamanki gibi yapılandırılır.
Sohbet belleği olarak, son 20 mesajın aktarıldığı bir anı oluşturmak için MessageWindowChatMemory
uygulamasının oluşturucusunu kullanırız. Bağlamı Java sınıf istemcimizde yerel olarak saklanan ileti dizilerinin üzerinde kayan bir penceredir.
Ardından, sohbet modelini sohbet belleğine bağlayan AI service
öğesini oluşturursunuz.
Yapay zeka hizmetinin, tanımladığımız, LangChain4j tarafından uygulanan ve String
sorgusu alıp String
yanıtı döndürdüğü özel bir ConversationService
arayüzünden nasıl yararlandığına dikkat edin.
Şimdi Gemini ile sohbet etme zamanı. Önce basit bir selamlama gönderilir, ardından Eyfel Kulesi'nin hangi ülkede bulunabileceğini öğrenmek için ilk soru gönderilir. Son cümlenin ilk sorunun yanıtıyla ilgili olduğuna dikkat edin. Eyfel Kulesi'nin bulunduğu ülkede kaç kişinin yaşadığını merak edersiniz. Bir önceki yanıtta belirtilen ülkeden açıkça bahsetmeksizin. Bu grafik, eski soruların ve yanıtların her istemle birlikte gönderildiğini gösterir.
Örneği çalıştırın:
./gradlew run -q -DjavaMainClass=gemini.workshop.Conversation
Aşağıdakilere benzer üç yanıt göreceksiniz:
User: Hello! Gemini: Hi there! How can I assist you today? User: What is the country where the Eiffel tower is situated? Gemini: France User: How many inhabitants are there in that country? Gemini: As of 2023, the population of France is estimated to be around 67.8 million.
Gemini ile tek yanıtlı sorular sorabilir veya birden fazla dönüşlü sohbet edebilirsiniz ancak şimdiye kadar yalnızca metinden yararlanıldı. Peki ya resimler? Bir sonraki adımda resimleri keşfedelim.
6. Gemini ile çok modluluk
Gemini çok modlu bir modeldir. Giriş olarak yalnızca metin kabul etmekle kalmaz, aynı zamanda resim ve hatta videoları da giriş olarak kabul eder. Bu bölümde, metin ve resimlerin bir arada kullanıldığı bir kullanım alanı bulacaksınız.
Sence Gemini bu kediyi tanıyabilir mi?
Vikipedi'den alınmış, karda duran bir kedinin resmihttps://upload.wikimedia.org/wikipedia/commons/b/b6/Felis_catus-cat_on_snow.jpg
app/src/main/java/gemini/workshop
dizininde Multimodal.java
kitaplığına göz atın:
package gemini.workshop;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.vertexai.VertexAiGeminiChatModel;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.model.output.Response;
import dev.langchain4j.data.message.ImageContent;
import dev.langchain4j.data.message.TextContent;
public class Multimodal {
static final String CAT_IMAGE_URL =
"https://upload.wikimedia.org/wikipedia/" +
"commons/b/b6/Felis_catus-cat_on_snow.jpg";
public static void main(String[] args) {
ChatLanguageModel model = VertexAiGeminiChatModel.builder()
.project(System.getenv("PROJECT_ID"))
.location(System.getenv("LOCATION"))
.modelName("gemini-1.5-flash-001")
.build();
UserMessage userMessage = UserMessage.from(
ImageContent.from(CAT_IMAGE_URL),
TextContent.from("Describe the picture")
);
Response<AiMessage> response = model.generate(userMessage);
System.out.println(response.content().text());
}
}
İçe aktarma işlemlerinde, farklı ileti ve içerik türlerini birbirinden ayırdığımıza dikkat edin. UserMessage
öğesi hem TextContent
hem de ImageContent
nesnesi içerebilir. Burada çok modluluk, yani metin ve resimleri bir arada kullanma becerisi öne çıkıyor. Model, AiMessage
içeren bir Response
geri gönderir.
Daha sonra content()
aracılığıyla yanıttan AiMessage
metnini ve ardından text()
sayesinde de ileti metnini alıyorsunuz.
Örneği çalıştırın:
./gradlew run -q -DjavaMainClass=gemini.workshop.Multimodal
Resmin adı kesinlikle resmin içeriğine dair ipucu verdi ama Gemini çıktısı şuna benziyor:
A cat with brown fur is walking in the snow. The cat has a white patch of fur on its chest and white paws. The cat is looking at the camera.
Resimleri ve metin istemlerini bir arada kullanmak, ilginç kullanım alanlarının önünü açar. Aşağıdaki işlemleri yapabilecek uygulamalar oluşturabilirsiniz:
- Resimlerdeki metinleri tanır.
- Bir resmin görüntülenmesinin güvenli olup olmadığını kontrol edin.
- Görsel başlıkları oluşturun.
- Düz metin açıklamaları içeren bir görüntü veritabanında arama yapın.
Resimlerden bilgi ayıklamanın yanı sıra yapılandırılmamış metinlerden de bilgi ayıklayabilirsiniz. Bir sonraki bölümde bunları öğreneceksiniz.
7. Yapılandırılmamış metinden yapılandırılmış bilgileri ayıklama
Önemli bilgilerin rapor dokümanlarında, e-postalarda veya diğer uzun metinlerde yapılandırılmamış bir şekilde verildiği birçok durum vardır. İdeal olarak, yapılandırılmamış metindeki önemli ayrıntıları yapılandırılmış nesneler biçiminde ayıklamanız gerekir. Bunu nasıl yapabileceğinize bakalım.
Bir kişinin adını ve yaşını, biyografisi veya açıklamasına göre çıkarmak istediğinizi varsayalım. LLM'ye, zekice düzenlenmiş bir istemle (genellikle "istem mühendisliği" olarak adlandırılır) yapılandırılmamış metinden JSON çıkarma talimatı verebilirsiniz.
app/src/main/java/gemini/workshop
bölgesindeki ExtractData.java
ürününe göz atın:
package gemini.workshop;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.vertexai.VertexAiGeminiChatModel;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.UserMessage;
public class ExtractData {
static record Person(String name, int age) {}
interface PersonExtractor {
@UserMessage("""
Extract the name and age of the person described below.
Return a JSON document with a "name" and an "age" property, \
following this structure: {"name": "John Doe", "age": 34}
Return only JSON, without any markdown markup surrounding it.
Here is the document describing the person:
---
{{it}}
---
JSON:
""")
Person extractPerson(String text);
}
public static void main(String[] args) {
ChatLanguageModel model = VertexAiGeminiChatModel.builder()
.project(System.getenv("PROJECT_ID"))
.location(System.getenv("LOCATION"))
.modelName("gemini-1.5-flash-001")
.temperature(0f)
.topK(1)
.build();
PersonExtractor extractor = AiServices.create(PersonExtractor.class, model);
Person person = extractor.extractPerson("""
Anna is a 23 year old artist based in Brooklyn, New York. She was born and
raised in the suburbs of Chicago, where she developed a love for art at a
young age. She attended the School of the Art Institute of Chicago, where
she studied painting and drawing. After graduating, she moved to New York
City to pursue her art career. Anna's work is inspired by her personal
experiences and observations of the world around her. She often uses bright
colors and bold lines to create vibrant and energetic paintings. Her work
has been exhibited in galleries and museums in New York City and Chicago.
"""
);
System.out.println(person.name()); // Anna
System.out.println(person.age()); // 23
}
}
Bu dosyadaki çeşitli adımlara bakalım:
Person
kaydı, bir kişiyi tanımlayan ayrıntıları ( ad ve yaş) temsil edecek şekilde tanımlanır.PersonExtractor
arayüzü, yapılandırılmamış metin dizesi sağlayan bir yöntemle tanımlanır vePerson
örneği döndürür.extractPerson()
, bir istemi kendisiyle ilişkilendiren@UserMessage
ek açıklamasına sahiptir. Bu, modelin bilgileri ayıklamak ve ayrıntıları sizin için ayrıştırılacak vePerson
örneğine aktarılmadan JSON belgesi biçiminde döndürmek için kullanacağı istemdir.
Şimdi main()
yönteminin içeriğine göz atalım:
- Sohbet modeli örneklendirilir. Son derece deterministik bir yanıt elde etmek için çok düşük bir
temperature
(sıfır) ve yalnızca bir (topK
) değerini kullandığımıza dikkat edin. Bu işlem, modelin talimatları daha iyi takip etmesine de yardımcı olur. Özellikle, Gemini'ın JSON yanıtını fazladan Markdown işaretlemesiyle sarmalamasını istemeyiz. - LangChain4j'in
AiServices
sınıfı sayesinde birPersonExtractor
nesnesi oluşturuldu. - Ardından, yapılandırılmamış metindeki kişinin ayrıntılarını ayıklamak için
Person person = extractor.extractPerson(...)
öğesini çağırmanız yeterlidir. Ardından, ad ve yaş bilgilerini içeren birPerson
örneği geri alabilirsiniz.
Örneği çalıştırın:
./gradlew run -q -DjavaMainClass=gemini.workshop.ExtractData
Aşağıdaki çıkışı göreceksiniz:
Anna 23
Evet, bu Ayşe ve 23 yaşındalar.
Bu AiServices
yaklaşımıyla, güçlü bir şekilde yazılmış nesnelerle çalışırsınız. Doğrudan LLM ile etkileşimde bulunmuyorsunuz. Bunun yerine, ayıklanan kişisel bilgileri temsil eden Person
kaydı gibi somut sınıflarla çalışıyorsunuz ve Person
örneği döndüren bir extractPerson()
yöntemine sahip PersonExtractor
nesneniz var. LLM kavramı soyutlanmış ve bir Java geliştiricisi olarak yalnızca normal sınıfları ve nesneleri değiştiriyorsunuz.
8. İstem şablonlarıyla istemleri yapılandırma
Yaygın olarak kullanılan bir dizi talimat veya soru kullanarak bir LLM ile etkileşimde bulunduğunuzda, bu istemin hiç değişmeyen bir bölümü bulunurken diğer kısımlarında veriler yer alır. Örneğin, yemek tarifi oluşturmak istiyorsanız "Yetenekli bir şefsiniz, lütfen şu malzemelerle bir tarif oluştur: ..." gibi bir istem kullanabilir ve ardından malzemeleri bu metnin sonuna eklersiniz. Programlama dillerindeki interpolasyon dizeleri gibi istem şablonları da bu amaca yöneliktir. İstem şablonu, LLM'ye yapılan belirli bir çağrı için doğru verilerle değiştirebileceğiniz yer tutucular içerir.
Daha somut bir şekilde anlatmak gerekirse app/src/main/java/gemini/workshop
dizininde TemplatePrompt.java
alanını inceleyelim:
package gemini.workshop;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.vertexai.VertexAiGeminiChatModel;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.model.input.Prompt;
import dev.langchain4j.model.input.PromptTemplate;
import dev.langchain4j.model.output.Response;
import java.util.HashMap;
import java.util.Map;
public class TemplatePrompt {
public static void main(String[] args) {
ChatLanguageModel model = VertexAiGeminiChatModel.builder()
.project(System.getenv("PROJECT_ID"))
.location(System.getenv("LOCATION"))
.modelName("gemini-1.5-flash-001")
.maxOutputTokens(500)
.temperature(0.8f)
.topK(40)
.topP(0.95f)
.maxRetries(3)
.build();
PromptTemplate promptTemplate = PromptTemplate.from("""
You're a friendly chef with a lot of cooking experience.
Create a recipe for a {{dish}} with the following ingredients: \
{{ingredients}}, and give it a name.
"""
);
Map<String, Object> variables = new HashMap<>();
variables.put("dish", "dessert");
variables.put("ingredients", "strawberries, chocolate, and whipped cream");
Prompt prompt = promptTemplate.apply(variables);
Response<AiMessage> response = model.generate(prompt.toUserMessage());
System.out.println(response.content().text());
}
}
Her zaman olduğu gibi, VertexAiGeminiChatModel
modelini yapılandırırken yaratıcılık düzeyiniz yüksek, topP ve topK değerleri yüksek. Ardından, istemimizin dizesini ileterek from()
statik yöntemiyle bir PromptTemplate
oluşturursunuz ve çift küme parantezi yer tutucu değişkenlerini kullanırsınız: {{dish}}
ve {{ingredients}}
.
Yer tutucunun adını ve yerine kullanılacak dize değerini temsil eden anahtar/değer çiftlerinin bir eşlemesini alan apply()
öğesini çağırarak son istemi oluşturursunuz.
Son olarak, bu istemden prompt.toUserMessage()
talimatıyla bir kullanıcı mesajı oluşturarak Gemini modelinin generate()
yöntemini çağırırsınız.
Örneği çalıştırın:
./gradlew run -q -DjavaMainClass=gemini.workshop.TemplatePrompt
Şuna benzer şekilde oluşturulmuş bir çıkış görürsünüz:
**Strawberry Shortcake** Ingredients: * 1 pint strawberries, hulled and sliced * 1/2 cup sugar * 1/4 cup cornstarch * 1/4 cup water * 1 tablespoon lemon juice * 1/2 cup heavy cream, whipped * 1/4 cup confectioners' sugar * 1/4 teaspoon vanilla extract * 6 graham cracker squares, crushed Instructions: 1. In a medium saucepan, combine the strawberries, sugar, cornstarch, water, and lemon juice. Bring to a boil over medium heat, stirring constantly. Reduce heat and simmer for 5 minutes, or until the sauce has thickened. 2. Remove from heat and let cool slightly. 3. In a large bowl, combine the whipped cream, confectioners' sugar, and vanilla extract. Beat until soft peaks form. 4. To assemble the shortcakes, place a graham cracker square on each of 6 dessert plates. Top with a scoop of whipped cream, then a spoonful of strawberry sauce. Repeat layers, ending with a graham cracker square. 5. Serve immediately. **Tips:** * For a more elegant presentation, you can use fresh strawberries instead of sliced strawberries. * If you don't have time to make your own whipped cream, you can use store-bought whipped cream.
Haritada dish
ve ingredients
değerlerini değiştirebilir, sıcaklık, topK
ve tokP
ayarlarını yapıp kodu yeniden çalıştırabilirsiniz. Böylece, bu parametreleri değiştirmenin LLM'ye etkisini gözlemleyebilirsiniz.
İstem şablonları, LLM çağrıları için yeniden kullanılabilir ve parametrelenebilir talimatlara sahip olmanın iyi bir yoludur. Kullanıcılarınızın sağladığı farklı değerler için verileri iletebilir ve istemleri özelleştirebilirsiniz.
9. Birkaç çekim istemi içeren metin sınıflandırma
LLM'ler, metinleri farklı kategorilerde sınıflandırma konusunda oldukça iyidir. Metin örnekleri ve ilişkili kategorileriyle bu görevde bir LLM'ye yardımcı olabilirsiniz. Bu yaklaşıma genellikle az sayıda çekim isteme denir.
Belirli bir metin sınıflandırma türü: yaklaşım analizi yapmak için app/src/main/java/gemini/workshop
dizinindeki TextClassification.java
etiketine göz atın.
package gemini.workshop;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.vertexai.VertexAiGeminiChatModel;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.model.input.Prompt;
package gemini.workshop;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.vertexai.VertexAiGeminiChatModel;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.model.input.Prompt;
import dev.langchain4j.model.input.PromptTemplate;
import dev.langchain4j.model.output.Response;
import java.util.Map;
public class TextClassification {
public static void main(String[] args) {
ChatLanguageModel model = VertexAiGeminiChatModel.builder()
.project(System.getenv("PROJECT_ID"))
.location(System.getenv("LOCATION"))
.modelName("gemini-1.5-flash-001")
.maxOutputTokens(10)
.maxRetries(3)
.build();
PromptTemplate promptTemplate = PromptTemplate.from("""
Analyze the sentiment of the text below. Respond only with one word to describe the sentiment.
INPUT: This is fantastic news!
OUTPUT: POSITIVE
INPUT: Pi is roughly equal to 3.14
OUTPUT: NEUTRAL
INPUT: I really disliked the pizza. Who would use pineapples as a pizza topping?
OUTPUT: NEGATIVE
INPUT: {{text}}
OUTPUT:
""");
Prompt prompt = promptTemplate.apply(
Map.of("text", "I love strawberries!"));
Response<AiMessage> response = model.generate(prompt.toUserMessage());
System.out.println(response.content().text());
}
}
main()
yönteminde, Gemini sohbet modelini her zamanki gibi oluşturursunuz ancak yalnızca kısa bir yanıt istediğiniz için küçük bir maksimum çıkış jetonu numarasıyla oluşturursunuz: Metin POSITIVE
, NEGATIVE
veya NEUTRAL
biçimindedir.
Ardından, modele birkaç giriş ve çıkış örneği hakkında talimat vererek birkaç atışlık istem tekniğiyle yeniden kullanılabilir bir istem şablonu oluşturuyorsunuz. Bu, modelin de gerçek çıktıyı takip etmesine yardımcı olur. Gemini size tek cümleyle yanıt vermez. Bunun yerine tek kelimeyle yanıt vermesi istenir.
{{text}}
yer tutucusunu gerçek parametreyle ("I love strawberries"
) değiştirmek ve bu şablonu toUserMessage()
içeren bir kullanıcı mesajına dönüştürmek için değişkenleri apply()
yöntemiyle uygularsınız.
Örneği çalıştırın:
./gradlew run -q -DjavaMainClass=gemini.workshop.TextClassification
Tek bir kelime göreceksiniz:
POSITIVE
Çilek sevgisi olumlu bir duygu gibi görünüyor.
10. Alma için Artırılmış Nesil
LLM'ler çok sayıda metinle eğitilir. Ancak bilgileri yalnızca eğitim sırasında gördüğü bilgileri kapsıyor. Model eğitimi bitiş tarihinden sonra yayınlanan yeni bilgiler varsa bu ayrıntılar model tarafından kullanılamaz. Dolayısıyla, model daha önce görmediği bilgilerle ilgili soruları yanıtlayamaz.
Bu nedenle Almayla Artırılmış Oluşturma (RAG) gibi yaklaşımlar, LLM'nin kullanıcılarının isteklerini yerine getirmek, daha güncel olabilecek bilgilerle yanıt vermek veya eğitim sırasında erişilemeyen özel bilgilerle yanıt vermek için bilmesi gereken ek bilgilerin sağlanmasına yardımcı olur.
Şimdi sohbetlere dönelim. Bu kez, dokümanlarınız hakkında soru sorabileceksiniz. Daha küçük parçalara ("parçalar") ayrılmış dokümanlarınızı içeren bir veritabanından alakalı bilgileri alabilecek bir chatbot oluşturacaksınız ve model, sadece eğitimde yer alan bilgilere güvenmek yerine, bu bilgileri kullanarak cevaplarını sağlamlaştıracak.
RAG'de iki aşama vardır:
- Besleme aşaması: Belgeler belleğe yüklenir, daha küçük parçalara bölünür ve vektör yerleştirmeler (parçaların yüksek çok boyutlu vektör temsili) hesaplanır ve anlamsal aramalar yapabilen bir vektör veritabanında depolanır. Bu alıp kullanma aşaması, normalde bir kez, belge kitaplığına yeni dokümanların eklenmesi gerektiğinde yapılır.
- Sorgu aşaması: Kullanıcılar artık dokümanlar hakkında sorular sorabilir. Soru da bir vektöre dönüştürülür ve veritabanındaki diğer tüm vektörlerle karşılaştırılır. En benzer vektörler genellikle anlam açısından alakalıdır ve vektör veritabanı tarafından döndürülür. Ardından LLM'ye konuşmanın bağlamı, veritabanı tarafından döndürülen vektörlere karşılık gelen metin parçaları verilir ve kullanıcıdan bu parçalara bakarak yanıtını temel alması istenir.
Dokümanlarınızı hazırlama
Bu yeni demoda, "Tüm ihtiyacınız olan ilgiyi çekmek" hakkında sorular soracaksınız. bir araştırma raporudur. Google'ın öncülük ettiği ve tüm modern büyük dil modellerinin günümüzde uygulanma şekli olan dönüştürücü nöral ağ mimarisini açıklar.
Gazete, depodaki attention-is-all-you-need.pdf dosyasına zaten indirilmiştir.
Chatbot'u uygulama
2 aşamalı yaklaşımın nasıl geliştirileceğini inceleyelim: İlk olarak belge besleme ve ardından kullanıcıların doküman hakkında sorular sorduğu sorgu zamanı.
Bu örnekte, her iki aşama aynı sınıfta uygulanmıştır. Normalde, aktarımı gerçekleştiren bir uygulamanız ve kullanıcılarınıza chatbot arayüzünü sunan başka bir uygulamanız olur.
Ayrıca, bu örnekte bellek içi vektör veritabanını kullanacağız. Gerçek bir üretim senaryosunda, besleme ve sorgulama aşamaları iki farklı uygulamada ayrılır ve vektörler, bağımsız bir veritabanında saklanır.
Belge besleme
Belge besleme aşamasının ilk adımı, daha önce indirdiğimiz PDF dosyasını bulmak ve bu dosyayı okumak için bir PdfParser
hazırlamaktır:
URL url = new URI("https://github.com/glaforge/gemini-workshop-for-java-developers/raw/main/attention-is-all-you-need.pdf").toURL();
ApachePdfBoxDocumentParser pdfParser = new ApachePdfBoxDocumentParser();
Document document = pdfParser.parse(url.openStream());
Normal sohbet dili modelini oluşturmak yerine bir yerleştirme modelinin örneği oluşturursunuz. Bu model, rolü metin parçalarının (kelimeler, cümleler, hatta paragraflar) vektör gösterimlerini oluşturmaktır. Metin yanıtlarını döndürmek yerine, kayan nokta sayılarının vektörlerini döndürür.
VertexAiEmbeddingModel embeddingModel = VertexAiEmbeddingModel.builder()
.endpoint(System.getenv("LOCATION") + "-aiplatform.googleapis.com:443")
.project(System.getenv("PROJECT_ID"))
.location(System.getenv("LOCATION"))
.publisher("google")
.modelName("textembedding-gecko@003")
.maxRetries(3)
.build();
Daha sonra, birlikte çalışmak için birkaç sınıfa ihtiyacınız olacak:
- PDF dokümanını parçalar halinde yükleyin ve bölün.
- Bu parçaların tümü için vektör yerleştirmeleri oluşturun.
InMemoryEmbeddingStore<TextSegment> embeddingStore =
new InMemoryEmbeddingStore<>();
EmbeddingStoreIngestor storeIngestor = EmbeddingStoreIngestor.builder()
.documentSplitter(DocumentSplitters.recursive(500, 100))
.embeddingModel(embeddingModel)
.embeddingStore(embeddingStore)
.build();
storeIngestor.ingest(document);
Vektör yerleştirmelerini depolamak için bellek içi vektör veritabanı olan InMemoryEmbeddingStore
örneği oluşturuldu.
Doküman, DocumentSplitters
sınıfı sayesinde parçalara ayrıldı. PDF dosyasındaki metin, 100 karakterlik örtüşmeyle 500 karakterlik snippet'lere bölünür (kelimeleri veya cümleleri parçalar halinde kesmemek için sonraki parçayla birlikte).
Mağaza aktarıcısı belge ayırıcıyı, vektörleri hesaplamak için yerleştirme modelini ve bellek içi vektör veritabanını bağlar. Ardından ingest()
yöntemi, besleme işlemini gerçekleştirir.
İlk aşama bitti. Doküman, ilişkili vektör yerleştirmeleriyle birlikte metin parçalarına dönüştürüldü ve vektör veritabanında depolandı.
Soru sorma
Soru sormaya hazırlanma vakti geldi. Görüşmeyi başlatmak için bir sohbet modeli oluşturun:
ChatLanguageModel model = VertexAiGeminiChatModel.builder()
.project(System.getenv("PROJECT_ID"))
.location(System.getenv("LOCATION"))
.modelName("gemini-1.5-flash-001")
.maxOutputTokens(1000)
.build();
Vektör veritabanını (embeddingStore
değişkeninde) yerleştirme modeline bağlamak için de bir retriever sınıfına ihtiyacınız vardır. Görevi, kullanıcı sorgusu için vektör yerleştirmeyi hesaplayarak vektör veritabanını sorgulamak ve veritabanındaki benzer vektörleri bulmaktır.
EmbeddingStoreContentRetriever retriever =
new EmbeddingStoreContentRetriever(embeddingStore, embeddingModel);
Ana yöntemin dışında, bir LLM uzman asistanını temsil eden bir arayüz oluşturun. Bu arayüz, modelle etkileşimde bulunmanız için AiServices
sınıfının uygulayacağı bir arayüzdür:
interface LlmExpert {
String ask(String question);
}
Bu noktada yeni bir AI hizmeti yapılandırabilirsiniz:
LlmExpert expert = AiServices.builder(LlmExpert.class)
.chatLanguageModel(model)
.chatMemory(MessageWindowChatMemory.withMaxMessages(10))
.contentRetriever(retriever)
.build();
Bu hizmet birbirine bağlanır:
- Daha önce yapılandırdığınız sohbet dili modeli.
- Görüşmeyi takip etmek için bir sohbet belleği.
- retriever, bir vektör yerleştirme sorgusunu veritabanındaki vektörlerle karşılaştırır.
- İstem şablonunda, sohbet modelinin verdiği bilgilere (ör. vektör yerleştirmesi kullanıcının sorusu vektörüne benzer olan dokümanlardan ilgili alıntılar) dayanarak yanıt vermesi gerektiğini açıkça belirten bir ifade vardır.
.retrievalAugmentor(DefaultRetrievalAugmentor.builder()
.contentInjector(DefaultContentInjector.builder()
.promptTemplate(PromptTemplate.from("""
You are an expert in large language models,\s
you excel at explaining simply and clearly questions about LLMs.
Here is the question: {{userMessage}}
Answer using the following information:
{{contents}}
"""))
.build())
.contentRetriever(retriever)
.build())
Nihayet sorularınızı sormaya hazırsınız!
List.of(
"What neural network architecture can be used for language models?",
"What are the different components of a transformer neural network?",
"What is attention in large language models?",
"What is the name of the process that transforms text into vectors?"
).forEach(query ->
System.out.printf("%n=== %s === %n%n %s %n%n", query, expert.ask(query)));
);
Tam kaynak kodu, app/src/main/java/gemini/workshop
dizinindeki RAG.java
klasöründedir:
Örneği çalıştırın:
./gradlew -q run -DjavaMainClass=gemini.workshop.RAG
Çıktıda sorularınızın yanıtlarını göreceksiniz:
=== What neural network architecture can be used for language models? === Transformer architecture === What are the different components of a transformer neural network? === The different components of a transformer neural network are: 1. Encoder: The encoder takes the input sequence and converts it into a sequence of hidden states. Each hidden state represents the context of the corresponding input token. 2. Decoder: The decoder takes the hidden states from the encoder and uses them to generate the output sequence. Each output token is generated by attending to the hidden states and then using a feed-forward network to predict the token's probability distribution. 3. Attention mechanism: The attention mechanism allows the decoder to attend to the hidden states from the encoder when generating each output token. This allows the decoder to take into account the context of the input sequence when generating the output sequence. 4. Positional encoding: Positional encoding is a technique used to inject positional information into the input sequence. This is important because the transformer neural network does not have any inherent sense of the order of the tokens in the input sequence. 5. Feed-forward network: The feed-forward network is a type of neural network that is used to predict the probability distribution of each output token. The feed-forward network takes the hidden state from the decoder as input and outputs a vector of probabilities. === What is attention in large language models? === Attention in large language models is a mechanism that allows the model to focus on specific parts of the input sequence when generating the output sequence. This is important because it allows the model to take into account the context of the input sequence when generating each output token. Attention is implemented using a function that takes two sequences as input: a query sequence and a key-value sequence. The query sequence is typically the hidden state from the previous decoder layer, and the key-value sequence is typically the sequence of hidden states from the encoder. The attention function computes a weighted sum of the values in the key-value sequence, where the weights are determined by the similarity between the query and the keys. The output of the attention function is a vector of context vectors, which are then used as input to the feed-forward network in the decoder. The feed-forward network then predicts the probability distribution of the next output token. Attention is a powerful mechanism that allows large language models to generate text that is both coherent and informative. It is one of the key factors that has contributed to the recent success of large language models in a wide range of natural language processing tasks. === What is the name of the process that transforms text into vectors? === The process of transforming text into vectors is called **word embedding**. Word embedding is a technique used in natural language processing (NLP) to represent words as vectors of real numbers. Each word is assigned a unique vector, which captures its meaning and semantic relationships with other words. Word embeddings are used in a variety of NLP tasks, such as machine translation, text classification, and question answering. There are a number of different word embedding techniques, but one of the most common is the **skip-gram** model. The skip-gram model is a neural network that is trained to predict the surrounding words of a given word. By learning to predict the surrounding words, the skip-gram model learns to capture the meaning and semantic relationships of words. Once a word embedding model has been trained, it can be used to transform text into vectors. To do this, each word in the text is converted to its corresponding vector. The vectors for all of the words in the text are then concatenated to form a single vector, which represents the entire text. Text vectors can be used in a variety of NLP tasks. For example, text vectors can be used to train machine translation models, text classification models, and question answering models. Text vectors can also be used to perform tasks such as text summarization and text clustering.
11. İşlev çağırma
Ayrıca, bir LLM'nin harici sistemlere erişmesini istediğiniz durumlar da vardır. Örneğin, bilgi alan veya işlem yapan bir uzak web API'si ya da bir tür hesaplama yapan hizmetler buna örnek olarak gösterilebilir. Örneğin:
Uzak web API'leri:
- Müşteri siparişlerini takip etme ve güncelleme.
- Sorun izleyicide bir destek kaydı bulun veya oluşturun.
- Hisse senedi fiyatları veya IoT sensör ölçümleri gibi gerçek zamanlı verileri getirin.
- E-posta gönderin.
Hesaplama araçları:
- Daha ileri düzey matematik problemleri için hesap makinesi.
- LLM'ler akıl yürütme mantığına ihtiyaç duyduğunda kod çalıştırmak için kod yorumlama.
- LLM'nin bir veritabanını sorgulayabilmesi için doğal dil isteklerini SQL sorgularına dönüştürün.
İşlev çağrısı, modelin kendi adına bir veya daha fazla işlev çağrısının yapılmasını isteme olanağıdır. Böylece, kullanıcının istemine daha fazla yeni veri sunarak doğru şekilde yanıt verebilir.
Kullanıcıdan gelen belirli bir istem ve bu bağlamla alakalı olabilecek mevcut işlevler hakkında bilgi göz önünde bulundurulduğunda LLM, işlev çağrısı isteğiyle yanıt verebilir. Ardından LLM'yi entegre eden uygulama işlevi çağırabilir ve ardından LLM'ye yanıt vererek LLM'ye yanıt verebilir. Daha sonra LLM, yazılı bir yanıt vererek söz konusu yanıtı yorumlar.
İşlev çağrısının dört adımı
Şimdi bir işlev çağrısı örneğine bakalım: hava durumu tahmini hakkında bilgi alma.
Gemini'a veya başka bir LLM'ye Paris'teki hava durumunu sorduğunuzda, hava durumu tahminiyle ilgili bilgi olmadığını söyleyerek yanıt verirler. LLM'nin hava durumu verilerine gerçek zamanlı olarak erişebilmesini istiyorsanız kullanabileceği bazı işlevleri tanımlamanız gerekir.
Aşağıdaki şemaya göz atın:
1️⃣ İlk olarak, bir kullanıcı Paris'teki hava durumunu sorar. Chatbot uygulaması, LLM'nin sorguyu yerine getirmesine yardımcı olacak bir veya daha fazla işlev olduğunu bilir. Chatbot, hem ilk istemi hem de çağrılabilecek işlevlerin listesini gönderir. Burada, konum için bir dize parametresi alan getWeather()
adlı bir işlev görünür.
LLM hava durumu tahminleri hakkında bilgi sahibi olmadığından, metinle yanıt vermek yerine bir işlev yürütme isteği gönderir. Chatbot, konum parametresi olarak "Paris"
ile getWeather()
işlevini çağırmalıdır.
2️⃣ Chatbot, LLM adına bu işlevi çağırır, işlev yanıtını alır. Burada, yanıtın {"forecast": "sunny"}
olduğunu varsayıyoruz.
3️⃣ Chatbot uygulaması, JSON yanıtını LLM'ye geri gönderir.
4️⃣ LLM, JSON yanıtına bakar, bu bilgiyi yorumlar ve sonunda Paris'te havanın güneşli olduğu metniyle yanıt verir.
Her adımı kod olarak
İlk olarak Gemini modelini her zamanki gibi yapılandıracaksınız:
ChatLanguageModel model = VertexAiGeminiChatModel.builder()
.project(System.getenv("PROJECT_ID"))
.location(System.getenv("LOCATION"))
.modelName("gemini-1.5-flash-001")
.maxOutputTokens(100)
.build();
Çağrılabilecek işlevi açıklayan bir araç spesifikasyonu belirtirsiniz:
ToolSpecification weatherToolSpec = ToolSpecification.builder()
.name("getWeatherForecast")
.description("Get the weather forecast for a location")
.addParameter("location", JsonSchemaProperty.STRING,
JsonSchemaProperty.description("the location to get the weather forecast for"))
.build();
Parametrenin adı ve türünün yanı sıra işlevin adı tanımlanır, ancak hem işleve hem de parametrelere açıklama verildiğine dikkat edin. Açıklamalar çok önemlidir ve LLM'nin bir işlevin neler yapabileceğini gerçekten anlamasına yardımcı olur, böylece bu işlevin görüşme bağlamında çağrılması gerekip gerekmediğine karar verir.
Paris'teki hava durumuyla ilgili ilk soruyu göndererek 1. adıma başlayalım:
List<ChatMessage> allMessages = new ArrayList<>();
// 1) Ask the question about the weather
UserMessage weatherQuestion = UserMessage.from("What is the weather in Paris?");
allMessages.add(weatherQuestion);
2. adımda, modelin kullanmasını istediğimiz aracı iletiriz ve model çok fazla yürütme isteğiyle yanıt verir:
// 2) The model replies with a function call request
Response<AiMessage> messageResponse = model.generate(allMessages, weatherToolSpec);
ToolExecutionRequest toolExecutionRequest = messageResponse.content().toolExecutionRequests().getFirst();
System.out.println("Tool execution request: " + toolExecutionRequest);
allMessages.add(messageResponse.content());
3. Adım: Bu noktada, LLM'nin hangi işlevi çağırmamızı istediğini anlıyoruz. Kodda, harici bir API'ye gerçek bir çağrıda bulunmak yerine, doğrudan varsayıma dayalı bir hava durumu tahmini döndürülür:
// 3) We send back the result of the function call
ToolExecutionResultMessage toolExecResMsg = ToolExecutionResultMessage.from(toolExecutionRequest,
"{\"location\":\"Paris\",\"forecast\":\"sunny\", \"temperature\": 20}");
allMessages.add(toolExecResMsg);
4. adımda LLM, işlev yürütme sonucunu öğrenir ve metinsel bir yanıt sentezleyebilir:
// 4) The model answers with a sentence describing the weather
Response<AiMessage> weatherResponse = model.generate(allMessages);
System.out.println("Answer: " + weatherResponse.content().text());
Çıkış şu şekildedir:
Tool execution request: ToolExecutionRequest { id = null, name = "getWeatherForecast", arguments = "{"location":"Paris"}" }
Answer: The weather in Paris is sunny with a temperature of 20 degrees Celsius.
Aracı yürütme isteğinin üzerindeki çıktıyı ve yanıtı görebilirsiniz.
Tam kaynak kodu, app/src/main/java/gemini/workshop
dizinindeki FunctionCalling.java
klasöründedir:
Örneği çalıştırın:
./gradlew run -q -DjavaMainClass=gemini.workshop.FunctionCalling
Şuna benzer bir çıkış alırsınız:
Tool execution request: ToolExecutionRequest { id = null, name = "getWeatherForecast", arguments = "{"location":"Paris"}" }
Answer: The weather in Paris is sunny with a temperature of 20 degrees Celsius.
12. LangChain4j, işlev çağrısını gerçekleştiriyor
Önceki adımda, normal metin sorusu/yanıtı ve işlev istek/yanıt etkileşimlerinin araya nasıl dahil edildiğini gördünüz. Bunların arasında, gerçek bir işlev çağırmadan istenen işlev yanıtını doğrudan sağladınız.
Ancak LangChain4j, ileti dizisini her zamanki gibi ele alırken işlev çağrılarını sizin için şeffaf bir şekilde işleyebilen daha üst düzey bir soyutlama sunar.
Tek işlev çağrısı
FunctionCallingAssistant.java
hizmetini adım adım inceleyelim.
Öncelikle, işlevin yanıt veri yapısını temsil edecek bir kayıt oluşturursunuz:
record WeatherForecast(String location, String forecast, int temperature) {}
Yanıtta konum, hava durumu ve sıcaklıkla ilgili bilgiler yer alır.
Ardından, modelde kullanılabilir olmasını istediğiniz gerçek işlevi içeren bir sınıf oluşturursunuz:
static class WeatherForecastService {
@Tool("Get the weather forecast for a location")
WeatherForecast getForecast(@P("Location to get the forecast for") String location) {
if (location.equals("Paris")) {
return new WeatherForecast("Paris", "Sunny", 20);
} else if (location.equals("London")) {
return new WeatherForecast("London", "Rainy", 15);
} else {
return new WeatherForecast("Unknown", "Unknown", 0);
}
}
}
Bu sınıfın tek bir işlev içerdiğini, ancak modelin çağırmak isteyebileceği işlevin açıklamasına karşılık gelen @Tool
ek açıklamasıyla birlikte not aldığını unutmayın.
İşlevin parametreleri de (burada tek bir tane) gösterilir, ancak bu kısa @P
ek açıklaması da parametrenin bir açıklamasını sunar. Daha karmaşık senaryolarda modelin kullanılabilir olmasını sağlamak için istediğiniz kadar işlev ekleyebilirsiniz.
Bu sınıfta bazı hazır yanıtlar veriyorsunuz. Ancak gerçek bir harici hava durumu tahmin hizmeti çağırmak isterseniz bu, söz konusu yöntemin gövdesinde bulunan ve ilgili hizmete çağrı yapacaktınız.
Önceki yaklaşımda bir ToolSpecification
oluşturduğunuzda gördüğümüz gibi, bir işlevin ne yaptığını belgelemek ve parametrelerin neye karşılık geldiğini açıklamak önemlidir. Bu, modelin bu işlevin nasıl ve ne zaman kullanılabileceğini anlamasına yardımcı olur.
Ardından, LangChain4j, modelle etkileşimde bulunmak için kullanmak istediğiniz sözleşmeye karşılık gelen bir arayüz sağlamanıza olanak tanır. Burada, kullanıcı mesajını temsil eden bir dizeyi alıp modelin yanıtına karşılık gelen bir dize döndüren basit bir arayüz gösterilmektedir:
interface WeatherAssistant {
String chat(String userMessage);
}
LangChain4j'in UserMessage
(bir kullanıcı mesajı için) veya AiMessage
(model yanıtı için) içeren daha karmaşık imzalar, hatta daha ileri düzey durumları ele almak istiyorsanız TokenStream
(bu karmaşık nesneler aynı zamanda girdi sayısı, kullanılan jetonlar ve dizeler gibi ek bilgiler de içerir) içeren daha karmaşık imzalar kullanmak da mümkündür.
Tüm parçaları birbirine bağlayan main()
yöntemiyle başlayalım:
public static void main(String[] args) {
ChatLanguageModel model = VertexAiGeminiChatModel.builder()
.project(System.getenv("PROJECT_ID"))
.location(System.getenv("LOCATION"))
.modelName("gemini-1.5-flash-001")
.maxOutputTokens(100)
.build();
WeatherForecastService weatherForecastService = new WeatherForecastService();
WeatherAssistant assistant = AiServices.builder(WeatherAssistant.class)
.chatLanguageModel(model)
.chatMemory(MessageWindowChatMemory.withMaxMessages(10))
.tools(weatherForecastService)
.build();
System.out.println(assistant.chat("What is the weather in Paris?"));
}
Gemini sohbet modelini her zaman olduğu gibi yapılandırırsınız. Ardından, "fonksiyon"u içeren hava durumu tahmini hizmetinizi örneklendirirsiniz. telefon etmemizi ister.
Şimdi AiServices
sınıfını tekrar kullanarak sohbet modelini, sohbet belleğini ve aracı (ör. hava durumu tahmin hizmeti işleviyle) bağlayabilirsiniz. AiServices
, tanımladığınız WeatherAssistant
arayüzünüzü uygulayan bir nesne döndürür. Kalan tek şey söz konusu asistanın chat()
yöntemini çağırmaktır. Çağrı yaparken yalnızca metin yanıtlarını görürsünüz, ancak işlev çağrısı istekleri ve işlev çağrısı yanıtları geliştirici tarafından görülemez, ayrıca bu istekler otomatik ve şeffaf bir şekilde işlenir. Gemini bir işlevin çağrılması gerektiğini düşünürse işlev çağrısı isteğiyle yanıt verir ve LangChain4j, sizin adınıza yerel işlevi çağırma işlemini gerçekleştirir.
Örneği çalıştırın:
./gradlew run -q -DjavaMainClass=gemini.workshop.FunctionCallingAssistant
Şuna benzer bir çıkış alırsınız:
OK. The weather in Paris is sunny with a temperature of 20 degrees.
Bu, tek bir işlevin örneğidir.
Birden çok işlev çağrısı
Birden çok işleviniz de olabilir ve LangChain4j'in sizin adınıza birden çok işlev çağrısını işlemesine izin verebilirsiniz. Birden çok işlev örneği için MultiFunctionCallingAssistant.java
bölümüne bakın.
Para birimlerini dönüştürme işlevi vardır:
@Tool("Convert amounts between two currencies")
double convertCurrency(
@P("Currency to convert from") String fromCurrency,
@P("Currency to convert to") String toCurrency,
@P("Amount to convert") double amount) {
double result = amount;
if (fromCurrency.equals("USD") && toCurrency.equals("EUR")) {
result = amount * 0.93;
} else if (fromCurrency.equals("USD") && toCurrency.equals("GBP")) {
result = amount * 0.79;
}
System.out.println(
"convertCurrency(fromCurrency = " + fromCurrency +
", toCurrency = " + toCurrency +
", amount = " + amount + ") == " + result);
return result;
}
Hisse senedinin değerini öğrenmek için kullanılan diğer bir fonksiyon:
@Tool("Get the current value of a stock in US dollars")
double getStockPrice(@P("Stock symbol") String symbol) {
double result = 170.0 + 10 * new Random().nextDouble();
System.out.println("getStockPrice(symbol = " + symbol + ") == " + result);
return result;
}
Belirli bir tutara yüzde uygulamak için kullanılan diğer bir fonksiyon:
@Tool("Apply a percentage to a given amount")
double applyPercentage(@P("Initial amount") double amount, @P("Percentage between 0-100 to apply") double percentage) {
double result = amount * (percentage / 100);
System.out.println("applyPercentage(amount = " + amount + ", percentage = " + percentage + ") == " + result);
return result;
}
Ardından tüm bu fonksiyonları ve bir Çok Amaçlı Araçlar sınıfını birleştirebilirsiniz. Örneğin, "AAPL hisse senedi fiyatının% 10'u USD'den EUR'ye dönüştürülür?" gibi sorular sorabilirsiniz.
public static void main(String[] args) {
ChatLanguageModel model = VertexAiGeminiChatModel.builder()
.project(System.getenv("PROJECT_ID"))
.location(System.getenv("LOCATION"))
.modelName("gemini-1.5-flash-001")
.maxOutputTokens(100)
.build();
MultiTools multiTools = new MultiTools();
MultiToolsAssistant assistant = AiServices.builder(MultiToolsAssistant.class)
.chatLanguageModel(model)
.chatMemory(withMaxMessages(10))
.tools(multiTools)
.build();
System.out.println(assistant.chat(
"What is 10% of the AAPL stock price converted from USD to EUR?"));
}
Aşağıdaki gibi çalıştırın:
./gradlew run -q -DjavaMainClass=gemini.workshop.MultiFunctionCallingAssistant
Şu ada sahip birden çok işlev göreceksiniz:
getStockPrice(symbol = AAPL) == 172.8022224055534 convertCurrency(fromCurrency = USD, toCurrency = EUR, amount = 172.8022224055534) == 160.70606683716468 applyPercentage(amount = 160.70606683716468, percentage = 10.0) == 16.07060668371647 10% of the AAPL stock price converted from USD to EUR is 16.07060668371647 EUR.
Temsilcilere Doğru
İşlev çağırma, Gemini gibi büyük dil modelleri için mükemmel bir uzantı mekanizmasıdır. Genellikle "aracı" adı verilen daha karmaşık sistemler geliştirmemizi sağlar. "Yapay zeka destekli asistanlar". Bu aracılar, harici API'ler ve harici ortamda yan etkileri olabilecek hizmetlerle (örneğin, e-posta gönderme, destek kaydı oluşturma vb.) harici dünyayla etkileşim kurabilir.
Böyle güçlü aracılar oluştururken bunu sorumlu bir şekilde yapmalısınız. Otomatik işlemler yapmadan önce işin bir parçasını göz önünde bulundurmalısınız. Dış dünyayla etkileşim kuran LLM destekli temsilciler tasarlarken güvenliği göz önünde bulundurmak önemlidir.
13. Gemma'yı Ollama ve TestContainers ile çalıştırma
Şimdiye kadar Gemini'ı kullandık. Ancak bir de Gemma, yani küçük kardeş modeli var.
Gemma, Gemini modellerini oluşturmak için kullanılan araştırma ve teknolojiyle oluşturulmuş hafif ve son teknoloji ürünü açık modeller ailesidir. Gemma, Gemma1 ve Gemma2 olmak üzere her biri farklı boyutlara sahip iki varyant halinde sunulur. Gemma1'in iki boyutu vardır: 2B ve 7B. Gemma2'nin iki boyutu vardır: 9B ve 27B. Ağırlıkları serbest, küçük boyutları sayesinde dizüstü bilgisayarınızda veya Cloud Shell'de bile kendi başınıza çalıştırabilirsiniz.
Gemma nasıl çalıştırılır?
Gemma'yı bulutta, tek tıkla Vertex AI'ı veya bazı GPU'larla birlikte GKE'yi kullanarak çalıştırabilirsiniz. Gemma'yı yerel olarak da çalıştırabilirsiniz.
Gemma'yı yerel olarak çalıştırmak için iyi bir seçenek olan Ollama aracı, Lama 2 ve Mistral gibi birçok küçük modeli yerel makinenizde çalıştırmanıza olanak tanır. Docker'a benzer, ancak LLM'ler içindir.
İşletim Sisteminize ilişkin talimatları uygulayarak Ollama'yı yükleyin.
Linux ortamı kullanıyorsanız, Ollama'yı yükledikten sonra etkinleştirmeniz gerekir.
ollama serve > /dev/null 2>&1 &
Yerel olarak yüklendikten sonra, model çekmek için komutlar çalıştırabilirsiniz:
ollama pull gemma:2b
Modelin çekilmesini bekleyin. Bu işlem biraz zaman alabilir.
Modeli çalıştırın:
ollama run gemma:2b
Artık modelle etkileşimde bulunabilirsiniz:
>>> Hello! Hello! It's nice to hear from you. What can I do for you today?
İstemden çıkmak için Ctrl+D tuşlarına basın
TestContainers'da Ollama'da Gemma'yı çalıştırma
Ollama'yı yerel olarak yükleyip çalıştırmak zorunda kalmadan, TestContainers tarafından işlenen bir kapsayıcı içinde Ollama'yı kullanabilirsiniz.
TestContainers yalnızca test için faydalı değildir, container'ları yürütmek için de kullanılabilir. Yararlanabileceğiniz özel bir OllamaContainer
bile var.
Resmin tamamını aşağıda görebilirsiniz:
Uygulama
GemmaWithOllamaContainer.java
hizmetini adım adım inceleyelim.
Öncelikle, Gemma modelini çeken, türetilmiş bir Ollama kapsayıcısı oluşturmanız gerekir. Bu görüntü, önceki bir çalıştırmada zaten mevcut ya da oluşturulacak. Resim zaten mevcutsa TestContainers'a, varsayılan Ollama resmini Gemma destekli varyantınızla değiştirmek istediğinizi söyleyin:
private static final String TC_OLLAMA_GEMMA_2_B = "tc-ollama-gemma-2b";
// Creating an Ollama container with Gemma 2B if it doesn't exist.
private static OllamaContainer createGemmaOllamaContainer() throws IOException, InterruptedException {
// Check if the custom Gemma Ollama image exists already
List<Image> listImagesCmd = DockerClientFactory.lazyClient()
.listImagesCmd()
.withImageNameFilter(TC_OLLAMA_GEMMA_2_B)
.exec();
if (listImagesCmd.isEmpty()) {
System.out.println("Creating a new Ollama container with Gemma 2B image...");
OllamaContainer ollama = new OllamaContainer("ollama/ollama:0.1.26");
ollama.start();
ollama.execInContainer("ollama", "pull", "gemma:2b");
ollama.commitToImage(TC_OLLAMA_GEMMA_2_B);
return ollama;
} else {
System.out.println("Using existing Ollama container with Gemma 2B image...");
// Substitute the default Ollama image with our Gemma variant
return new OllamaContainer(
DockerImageName.parse(TC_OLLAMA_GEMMA_2_B)
.asCompatibleSubstituteFor("ollama/ollama"));
}
}
Ardından Ollama test container'ı oluşturup başlatın. Ardından, kullanmak istediğiniz modelle birlikte container'ın adresine ve bağlantı noktasına işaret ederek bir Ollama sohbet modeli oluşturun. Son olarak, model.generate(yourPrompt)
öğesini her zamanki gibi çağırırsınız:
public static void main(String[] args) throws IOException, InterruptedException {
OllamaContainer ollama = createGemmaOllamaContainer();
ollama.start();
ChatLanguageModel model = OllamaChatModel.builder()
.baseUrl(String.format("http://%s:%d", ollama.getHost(), ollama.getFirstMappedPort()))
.modelName("gemma:2b")
.build();
String response = model.generate("Why is the sky blue?");
System.out.println(response);
}
Aşağıdaki gibi çalıştırın:
./gradlew run -q -DjavaMainClass=gemini.workshop.GemmaWithOllamaContainer
İlk çalıştırmanın kapsayıcı oluşturulması ve çalıştırılması biraz zaman alabilir, ancak işlem tamamlandığında Gemma'nın şu şekilde yanıt verdiğini göreceksiniz:
INFO: Container ollama/ollama:0.1.26 started in PT2.827064047S
The sky appears blue due to Rayleigh scattering. Rayleigh scattering is a phenomenon that occurs when sunlight interacts with molecules in the Earth's atmosphere.
* **Scattering particles:** The main scattering particles in the atmosphere are molecules of nitrogen (N2) and oxygen (O2).
* **Wavelength of light:** Blue light has a shorter wavelength than other colors of light, such as red and yellow.
* **Scattering process:** When blue light interacts with these molecules, it is scattered in all directions.
* **Human eyes:** Our eyes are more sensitive to blue light than other colors, so we perceive the sky as blue.
This scattering process results in a blue appearance for the sky, even though the sun is actually emitting light of all colors.
In addition to Rayleigh scattering, other atmospheric factors can also influence the color of the sky, such as dust particles, aerosols, and clouds.
Cloud Shell'de Gemma çalışıyor.
14. Tebrikler
Tebrikler, LangChain4j ve Gemini API'yi kullanarak Java'da ilk üretken yapay zeka sohbet uygulamanızı başarıyla derlediniz. Bu süreçte çok modlu büyük dil modellerinin oldukça güçlü olduğunu ve kendi belgeleriniz, veri ayıklama, harici API'lerle etkileşime geçme ve hatta soru/cevap gibi çeşitli görevleri yerine getirebildiğini keşfettiniz.
Sırada ne var?
Güçlü LLM entegrasyonlarıyla uygulamalarınızı geliştirme sırası sizde.
Daha fazla bilgi
- Üretken yapay zekanın yaygın kullanım alanları
- Üretken yapay zeka ile ilgili eğitim kaynakları
- Üretken Yapay Zeka Studio üzerinden Gemini ile etkileşim kurma
- Sorumlu AI