Aşağıdaki rehber, Claris FileMaker ile OpenAI (ChatGPT) API’sini kullanarak basit bir “semantic find” (anlamsal arama) uygulaması oluşturmanın genel mantığını anlatır. Buradaki temel yaklaşım, OpenAI Embeddings özelliğini kullanarak verileri ve arama sorgusunu “vektör” formuna dönüştürmek ve benzerlik skoruna göre en alakalı kayıtları getirmektir. “Semantic find” dendiğinde kastedilen, metinlerin sadece kelime eşleşmesiyle değil, anlam düzeyinde bir benzerlik karşılaştırması yapmaktır.
Kavramsal Ön Bilgi
Embeddings (Vektör Temsili)
Embedding, bir metni (cümle, paragraf, belge vb.) matematiksel olarak bir vektör (örneğin 1536 boyutlu bir dizi) şeklinde temsil eder.
OpenAI’nin “text-embedding-ada-002” gibi modelleriyle kelimelerin ve cümlelerin anlamsal benzerliklerini ölçmek mümkün hale gelir.
İki metnin embedding’leri arasındaki kozinüs benzerliği (cosine similarity) veya Öklid mesafesi (euclidean distance) hesaplanarak hangi metinlerin birbirine anlam olarak daha yakın olduğu tespit edilebilir.
Neden Embeddings Tabanlı Yaklaşım?
Geleneksel FileMaker “Find” işlemi, büyük oranda kelime eşleşmesine dayanır (özel arama operatörleriyle bir ölçüde geliştirilebilir). Ancak “semantic find” ile “araba” ve “otomobil” kelimeleri arasındaki benzerliği ya da sinonimleri sezgisel olarak yakalayabilir, hatta metnin tüm bağlamını anlayabilirsiniz.
Genel Adımlar
Veritabanı Tasarımı
Bir tablo (örneğin Documents
) olsun. Aşağıdaki alanlara sahip olabilir:
docID
(Numara veya metin, benzersiz kimlik)
docText
(Metin, arama yapılacak içerik)
docEmbedding
(metin veya JSON alanı; embeddings verisini saklayacağımız yer)
Metin İçin Embedding Alma
docText
alanındaki içeriği, OpenAI’nin Embeddings endpoint’ine (ör: https://api.openai.com/v1/embeddings
) göndererek bir vektör (dizi) elde edeceğiz.
Alınan bu dizi ([0.123, -0.045, 0.879, … ]
gibi) docEmbedding
alanına kaydedilir. Bu işlemi, tabloya yeni kayıt eklendikçe veya kayıt güncellendikçe otomatik olarak yapan bir script yazabilirsiniz.
Kullanıcının Sorgusunu Embedding’e Dönüştürme
Kullanıcı bir arama sorgusu (ör. “Hızlı ve ucuz bir otomobil arıyorum”) girdiğinde, aynı şekilde bu metni de OpenAI Embeddings API’sine gönderip sorgunun vektörel temsilini elde edersiniz (ör: $queryEmbedding
).
Benzerlik Hesaplaması
Tüm kayıtlardaki docEmbedding
alanıyla $queryEmbedding
arasında bir benzerlik skoru (örneğin kozinüs benzerliği) hesaplanır.
Daha yüksek skor, sorguyla daha yakından ilişkili bir metin anlamına gelir.
Sonuçları Sıralama veya Filtreleme
Kozinüs benzerliği belli bir eşik değerinin (ör. 0.80) üzerindeyse o kayıtları “benzer” kabul edip sonuç listesine dahil edebilirsiniz.
Veya skorlamaya göre sıralama yaparak en yüksekten en düşüğe listelersiniz.
Sonuçları Listeleme
FileMaker tarafında bir “Sonuç” portalı veya liste görünümü oluşturarak kullanıcıya en alakalı kayıtları gösterin.
Örnek Teknik Uygulama Adımları
Aşağıdaki adımlar, “Embeddings” kullanan tipik bir “semantic find” için örnek betik akışı sağlar. Burada varsayım olarak text-embedding-ada-002
modelini kullanıyoruz. (Bu model, 1536 boyutlu bir vektör döndürür. Güncel OpenAI dokümantasyonunu mutlaka inceleyin.)
Not: Aşağıdaki cURL örnekleri “Insert from URL” script adımında kullanılabilir.
Kayıt Oluşturma / Güncelleme Script’i
Amaç: Yeni bir belge eklendiğinde veya mevcut belge güncellendiğinde OpenAI’den embedding alıp docEmbedding
alanına kaydetmek.
// 1) Gerekli değişkenleri set et
Set Variable [ $apiKey ; Value: "YOUR_OPENAI_API_KEY" ]
Set Variable [ $text ; Value: Documents::docText ]
// 2) JSON body oluştur
Set Variable [ $jsonBody ; Value:
"{
\"input\": \"" & Substitute($text; "\""; "\\\"") & "\",
\"model\": \"text-embedding-ada-002\"
}"
]
// 3) Embedding endpoint URL
Set Variable [ $url ; Value: "https://api.openai.com/v1/embeddings" ]
// 4) API çağrısı yap
Insert from URL [
Select;
With dialog: Off;
Target: $response;
URL: $url;
cURL options:
"--request POST " &
"--header \"Content-Type: application/json\" " &
"--header \"Authorization: Bearer " & $apiKey & "\" " &
"--data " & Quote($jsonBody)
]
// 5) Dönen JSON içinde "data[0].embedding" yolunu al
Set Variable [ $embedding ; Value: JSONGetElement($response; "data[0].embedding") ]
// 6) docEmbedding alanına kaydet
Set Field [ Documents::docEmbedding ; $embedding ]
Bu script’i, OnRecordCommit veya özel bir buton üzerinden çalıştırabilirsiniz.
$embedding
tipik olarak [0.01, 0.234, -0.12, ...]
şeklinde bir dizi (JSON Array) olacaktır.
Kullanıcının Arama Sorgusu İçin Embedding Alma
Amaç: Kullanıcı, “Ne arıyorsunuz?” benzeri bir alana sorgu girer. Bu sorgunun embedding’ini alıp diğer kayıtlarla karşılaştıracağız.
// 1) Sorguyu al
Set Variable [ $query ; Value: GlobalFields::UserSearchQuery ]
// 2) JSON body
Set Variable [ $jsonBody ; Value:
"{
\"input\": \"" & Substitute($query; "\""; "\\\"") & "\",
\"model\": \"text-embedding-ada-002\"
}"
]
// 3) API çağrısı
Insert from URL [
Select;
With dialog: Off;
Target: $response;
URL: "https://api.openai.com/v1/embeddings";
cURL options:
"--request POST " &
"--header \"Content-Type: application/json\" " &
"--header \"Authorization: Bearer YOUR_OPENAI_API_KEY\" " &
"--data " & Quote($jsonBody)
]
// 4) $queryEmbedding i al
Set Variable [ $queryEmbedding ; Value: JSONGetElement($response; "data[0].embedding") ]
Benzerlik Hesaplama
FileMaker’ın yerleşik olarak kozinüs benzerliği veya vektör matematiği fonksiyonları yoktur. Aşağıdaki yaklaşımlardan birini seçebilirsiniz:
FileMaker’da “Custom Function” (Özel Fonksiyon)
cosineSimilarity(vectorA; vectorB)
şeklinde bir custom function yazıp, JSON içindeki vektörleri döngüyle parse ederek toplamları hesaplayabilirsiniz.
Ardından her kayıt için cosineSimilarity(Documents::docEmbedding; $queryEmbedding)
şeklinde bir değer elde edersiniz.
Script Döngüsü ve JSONGetElement
Tüm kayıtları bir script ile dolaşarak embedding alanındaki dizi elemanlarını JSONGetElement
ile çekip $queryEmbedding
’in elemanlarıyla çarpar, toplamı alır, normları hesaplar vs.
Elde ettiğiniz skoru geçici bir alana (örneğin similarityScore
) yazarsınız.
Dış Kaynak / Mikro Hizmet
Bazı geliştiriciler bu matematiksel işlemleri bir mikroserviste veya Python/R gibi bir ortamda yapıp sonucu FileMaker’a geri gönderirler.
Bu, büyük veri setlerinde performansı artırabilir.
Kozinüs Benzerliği Formülü:
[
\text{cosineSimilarity}(A, B)
= \frac{A \cdot B}{|A| \times |B|}
= \frac{\sum_{i=1}^{n} A_i \times B_i}{\sqrt{\sum_{i=1}^{n} A_i^2} \times \sqrt{\sum_{i=1}^{n} B_i^2}}
]
Örnek bir pseudo-FMP Script (tam code değil, fikir vermek amaçlı):
// Tüm Documents kayıtlarında dön
Go to Layout [ "Documents" (Documents) ]
Show All Records
Go to Record/Request/Page [ First ]
Loop
// docEmbedding i JSON array olarak çek
Set Variable [ $docVector ; Value: Documents::docEmbedding ]
// similarity score u hesapla
Set Variable [ $score ; Value: CosineSimilarity($docVector; $queryEmbedding) ]
// Bir alana yazabilirsiniz veya geçici bir global alan tutabilirsiniz
Set Field [ Documents::similarityScore ; $score ]
Go to Record/Request/Page [ Next ; Exit after last ]
End Loop
// Ardından "similarityScore" a göre Sort yapıp en yüksek skorlu kayıtları gösterebilirsiniz.
Buradaki CosineSimilarity
fonksiyonunu bir Custom Function olarak tanımlamanız gerekir (FM’de döngü, toplam vs. ile). Örneğin:
CosineSimilarity ( jsonVectorA ; jsonVectorB ) =
Let([
~countA = JSONListCount ( jsonVectorA );
~countB = JSONListCount ( jsonVectorB )
];
If(
~countA ≠ ~countB;
0;
// ...döngüsel çarpım, norm hesaplama işlemleri...
)
)
Böyle bir fonksiyon yazmak biraz uğraştırabilir ama bir kez yazıldıktan sonra sürekli kullanabilirsiniz.
Sonuçları Listelemek
Benzerlik Skoruna Göre Sıralama
similarityScore
alanına göre inen sırada sort ederek en alakalı kayıtları en üste alabilirsiniz.
Belirli Bir Eşik Değerine Göre Filtre
Örneğin similarityScore >= 0.80
olan kayıtları listeleyin.
Bu kayıtları bir “BUL” (Find) işlemiyle değil, muhtemelen bir If kontrolü veya İlişkili Kayıt (ör. global field = “1” ve similarityScore
ilişkisi) kullanarak getirebilirsiniz.
ChatGPT Modeli İle “Semantic Find”
Yukarıda anlattığımız Embeddings yaklaşımı, “semantic search” için en doğru yol. Ancak daha küçük veri setlerinde, “Chat Completions” API’sini “arama verisini prompt’a gömerek” da kullanabilirsiniz. Örneğin, şöyle bir sistem mesajı verip:
“Aşağıda bir dizi belgenin özetleri var. Kullanıcının sorduğu soruyla en alakalı belgeyi belirle ve cevabı döndür.”
Ardından user mesajında hem doküman özetlerini hem de sorguyu verebilirsiniz. Bu, basit sistemlerde çalışabilir ama veri seti büyüdükçe performans ve token maliyeti artar.
Özet / Sonuç
Embeddings Altyapısını Kullanın:
Her kayıt için embedding’i bir defa alıp veritabanına kaydedin.
Kullanıcı sorgusunu embedding’e dönüştürüp kayıtlarla benzerlik skorunu hesaplayın.
FileMaker’da Vektör Karşılaştırması:
Kendi “custom function” veya bir script döngüsüyle kozinüs benzerliğini hesaplayın.
En benzer kayıtları listeleyin.
Optimizasyon ve Pratiklik:
Kayıt sayınız çok fazlaysa, bu işlemi bir “mikroservis/Python” katmanıyla hızlandırmayı düşünün.
Eşik değeri (ör. 0.75, 0.80) ile benzerlik sonuçlarını filtreleyerek kullanıcının görmek istemediği düşük alakalı sonuçları eleyin.
Böylece, Claris FileMaker içinde geleneksel “string find” yerine, anlam odaklı (semantic) bir arama sistemi kurgulayabilir; kullanıcıların yakın anlamlı kelime veya benzer içerik arayışlarını daha iyi karşılayan bir deneyim sunabilirsiniz.