paint-brush
Kurumsal Verilerdeki Benzerlikleri Bulmak İçin pgvector'u Kullanmaile@johnjvester
805 okumalar
805 okumalar

Kurumsal Verilerdeki Benzerlikleri Bulmak İçin pgvector'u Kullanma

ile John Vester14m2024/03/21
Read on Terminal Reader

Çok uzun; Okumak

Bir pazarlama kampanyasına yardımcı olmak amacıyla kurumsal verilerle veri korelasyonlarını keşfetmeye yardımcı olmak için kelime vektörlerinin ve benzerlik aramalarının gücünden yararlanın.
featured image - Kurumsal Verilerdeki Benzerlikleri Bulmak İçin pgvector'u Kullanma
John Vester HackerNoon profile picture
0-item
1-item


Yazılım mühendisleri bu dünyada heyecan verici bir yere sahiptir. Teknoloji yığını veya endüstri ne olursa olsun, işverenlerimizin amaç ve hedeflerine doğrudan katkıda bulunan sorunları çözmekle görevlendirildik. Bonus olarak, hedefimize gelen zorlukları hafifletmek için teknolojiyi kullanabiliyoruz.


Bu örnekte, Postgres için açık kaynaklı bir vektör benzerlik araması olan pgvector'un kurumsal verilerde mevcut olan veri benzerliklerini tanımlamak için nasıl kullanılabileceğine odaklanmak istedim.

Basit Bir Kullanım Örneği

Basit bir örnek olarak, pazarlama departmanının başlatmayı planladığı bir kampanya için yardıma ihtiyacı olduğunu varsayalım. Amaç, yazılım endüstrisiyle yakından bağlantılı sektörlerdeki tüm Salesforce hesaplarına ulaşmaktır.


Sonunda, en çok benzer olan ilk üç sektördeki hesaplara odaklanmak ve bu aracı gelecekte diğer sektörler için benzerlikler bulmak amacıyla kullanmak istiyorlar. Mümkünse, her zaman ilk üçe geri dönmek yerine, istenen sayıda eşleşen sektörü sağlama seçeneğini tercih ediyorlar.

Üst Düzey Tasarım

Bu kullanım senaryosu benzerlik araması gerçekleştirmeye odaklanmaktadır. Bu alıştırmayı manuel olarak tamamlamak mümkün olsa da, birden fazla dil için önceden oluşturulmuş önceden eğitilmiş yerleştirmeler nedeniyle akla Wikipedia2Vec aracı geliyor. Kelime gömmeleri (vektörler olarak da bilinir), kelimelerin hem sözdizimsel hem de anlamsal bilgilerini içeren sayısal temsilleridir. Kelimeleri vektörler olarak temsil ederek, hangi kelimelerin anlamsal olarak diğerlerine “daha yakın” olduğunu matematiksel olarak belirleyebiliriz.


Örneğimizde, Salesforce'ta yapılandırılan her sektör için kelime vektörleri oluşturmak üzere basit bir Python programı da yazabilirdik.


pgvector uzantısı bir Postgres veritabanı gerektirir. Ancak örneğimize ilişkin kurumsal veriler şu anda Salesforce'ta bulunmaktadır. Neyse ki Heroku Connect , Salesforce hesaplarını Heroku Postgres ile senkronize etmenin kolay bir yolunu sağlar ve bunu salesforce.account adlı bir tabloda saklar. Ardından, Salesforce'taki her sektörü (VARCHAR anahtarı olarak) ve ilgili kelime vektörünü içeren salesforce.industries adında başka bir tablomuz olacak.


Postgres'teki Salesforce verileri ve kelime vektörleri ile Java ve Spring Boot kullanarak bir RESTful API oluşturacağız. Bu hizmet gerekli sorgulamayı gerçekleştirecek ve sonuçları JSON formatında döndürecektir.


Çözümün üst düzey görünümünü şu şekilde gösterebiliriz:


Kaynak kodu GitLab'da bulunacaktır. git push heroku komutunun verilmesi, Heroku'da bir dağıtımı tetikleyecek ve pazarlama ekibinin kolayca kullanabileceği bir RESTful API sunacaktır.

Çözümü Oluşturmak

Üst düzey tasarım uygulandığında bir çözüm oluşturmaya başlayabiliriz. Salesforce oturum açma bilgilerimi kullanarak bu alıştırmanın verilerini görüntülemek için Hesaplar ekranına gidebildim. Kurumsal verilerin ilk sayfasına bir örnek:


Bir Heroku Uygulaması Oluşturun

Bu çaba için pazarlama ekibinin isteğini çözmek üzere Heroku'yu kullanmayı planladım. Heroku hesabımda oturum açtım ve similarity-search-sfdc adlı yeni bir uygulama oluşturmak için Yeni Uygulama Oluştur düğmesini kullandım:


Uygulamayı oluşturduktan sonra Heroku Postgres eklentisini bulmak için Kaynaklar sekmesine gittim. Eklenti arama alanına “Postgres” yazdım.


Listeden Heroku Postgres'i seçtikten sonra Standart 0 planını seçtim, ancak pgvector, PostgreSQL 15 veya beta Essential katmanlı veritabanını çalıştıran Standart katmanlı (veya daha yüksek) veritabanı tekliflerinde mevcuttur .


Eklentiyi onayladığımda Heroku bir DATABASE_URL bağlantı dizesi oluşturdu ve sağladı. Bunu uygulamamın Ayarlar sekmesindeki Yapılandırma Değişkenleri bölümünde buldum. Bu bilgiyi veritabanıma bağlanmak ve pgvector uzantısını şu şekilde etkinleştirmek için kullandım:


 CREATE EXTENSION vector;


Daha sonra Heroku Connect eklentisini aradım ve buldum. Bunun bana Salesforce'taki kurumsal verilere bağlanmak için kolay bir yol sağlayacağını biliyordum.


Bu alıştırmada ücretsiz Demo Sürümü planı gayet iyi çalışıyor.


Bu noktada similarity-search-sfdc uygulamasının Kaynaklar sekmesi şuna benziyordu:


Salesforce hesabımı Heroku Connect'e bağlamak için “ Heroku Connect'i Kurma ” talimatlarını takip ettim. Daha sonra senkronizasyon için Hesap nesnesini seçtim. Tamamlandığında, aynı Salesforce hesap verilerini Heroku Connect'te ve temel Postgres veritabanında görebildim.


SQL açısından bakıldığında yaptığım şey, aşağıdaki tasarıma sahip bir salesforce.account tablosunun oluşturulmasıyla sonuçlandı:


 create table salesforce.account ( createddate timestamp, isdeleted boolean, name varchar(255), systemmodstamp timestamp, accountnumber varchar(40), industry varchar(255), sfid varchar(18), id serial primary key, _hc_lastop varchar(32), _hc_err text );


Vektörler Oluştur

Benzerlik aramasının beklendiği gibi çalışabilmesi için her Salesforce hesap sektörü için kelime vektörleri oluşturmam gerekiyordu:


  • Giyim
  • Bankacılık
  • Biyoteknoloji
  • Yapı
  • Eğitim
  • Elektronik
  • Mühendislik
  • Eğlence
  • Yiyecek ve İçecek
  • Finans
  • Devlet
  • Sağlık hizmeti
  • Misafirperverlik
  • Sigorta
  • Medya
  • Kâr Amaçlı Değil
  • Diğer
  • Yeniden yaratma
  • Perakende
  • Nakliye
  • Teknoloji
  • Telekomünikasyon
  • Toplu taşıma
  • Araçlar


Birincil kullanım durumu, yazılım endüstrisi için benzerlikler bulma ihtiyacını gösterdiğinden, o endüstri için de bir kelime vektörü oluşturmamız gerekir.


Bu alıştırmada işleri basit tutmak için, bu görevi Python 3.9 ve şuna benzeyen embed.py adlı bir dosyayı kullanarak manuel olarak yürüttüm:


 from wikipedia2vec import Wikipedia2Vec wiki2vec = Wikipedia2Vec.load('enwiki_20180420_100d.pkl') print(wiki2vec.get_word_vector('software').tolist())


Lütfen dikkat: get_word_vector() yöntemi, sektörün küçük harfle temsil edilmesini bekler.


Python embed.py çalıştırmak, software kelimesi için aşağıdaki kelime vektörünü oluşturdu:


 [-0.40402618050575256, 0.5711150765419006, -0.7885153293609619, -0.15960034728050232, -0.5692323446273804, 0.005377458408474922, -0.1315757781267166, -0.16840921342372894, 0.6626015305519104, -0.26056772470474243, 0.3681095242500305, -0.453583300113678, 0.004738557618111372, -0.4111144244670868, -0.1817493587732315, -0.9268549680709839, 0.07973367720842361, -0.17835664749145508, -0.2949991524219513, -0.5533796548843384, 0.04348105192184448, -0.028855713084340096, -0.13867013156414032, -0.6649054884910583, 0.03129105269908905, -0.24817068874835968, 0.05968991294503212, -0.24743635952472687, 0.20582349598407745, 0.6240783929824829, 0.3214546740055084, -0.14210252463817596, 0.3178422152996063, 0.7693028450012207, 0.2426985204219818, -0.6515568494796753, -0.2868216037750244, 0.3189859390258789, 0.5168254971504211, 0.11008890718221664, 0.3537853956222534, -0.713259220123291, -0.4132286608219147, -0.026366405189037323, 0.003034653142094612, -0.5275223851203918, -0.018167126923799515, 0.23878540098667145, -0.6077089905738831, 0.5368344187736511, -0.1210874393582344, 0.26415619254112244, -0.3066694438457489, 0.1471938043832779, 0.04954215884208679, 0.2045321762561798, 0.1391817331314087, 0.5286830067634583, 0.5764685273170471, 0.1882934868335724, -0.30167853832244873, -0.2122340053319931, -0.45651525259017944, -0.016777794808149338, 0.45624101161956787, -0.0438646525144577, -0.992512047290802, -0.3771328926086426, 0.04916151612997055, -0.5830298066139221, -0.01255014631897211, 0.21600870788097382, -0.18419665098190308, 0.1754663586616516, -0.1499166339635849, -0.1916201263666153, -0.22884036600589752, 0.17280352115631104, 0.25274306535720825, 0.3511175513267517, -0.20270302891731262, -0.6383468508720398, 0.43260180950164795, -0.21136239171028137, -0.05920517444610596, 0.7145522832870483, 0.7626600861549377, -0.5473887920379639, 0.4523043632507324, -0.1723199188709259, -0.10209759324789047, -0.5577948093414307, -0.10156919807195663, 0.31126976013183594, 0.3604489266872406, -0.13295558094978333, 0.2473849356174469, 0.278846800327301, -0.28618067502975464, 0.00527254119515419]


Endüstriler için Tablo Oluşturun

Kelime vektörlerini depolamak için aşağıdaki SQL komutunu kullanarak Postgres veritabanına bir industries tablosu eklememiz gerekiyordu:


 create table salesforce.industries ( name varchar not null constraint industries_pk primary key, embeddings vector(100) not null );


Oluşturulan industries tablosuyla, oluşturulan kelime vektörlerinin her birini ekleyeceğiz. Bunu aşağıdakine benzer SQL ifadeleriyle yaparız:


 INSERT INTO salesforce.industries (name, embeddings) VALUES ('Software','[-0.40402618050575256, 0.5711150765419006, -0.7885153293609619, -0.15960034728050232, -0.5692323446273804, 0.005377458408474922, -0.1315757781267166, -0.16840921342372894, 0.6626015305519104, -0.26056772470474243, 0.3681095242500305, -0.453583300113678, 0.004738557618111372, -0.4111144244670868, -0.1817493587732315, -0.9268549680709839, 0.07973367720842361, -0.17835664749145508, -0.2949991524219513, -0.5533796548843384, 0.04348105192184448, -0.028855713084340096, -0.13867013156414032, -0.6649054884910583, 0.03129105269908905, -0.24817068874835968, 0.05968991294503212, -0.24743635952472687, 0.20582349598407745, 0.6240783929824829, 0.3214546740055084, -0.14210252463817596, 0.3178422152996063, 0.7693028450012207, 0.2426985204219818, -0.6515568494796753, -0.2868216037750244, 0.3189859390258789, 0.5168254971504211, 0.11008890718221664, 0.3537853956222534, -0.713259220123291, -0.4132286608219147, -0.026366405189037323, 0.003034653142094612, -0.5275223851203918, -0.018167126923799515, 0.23878540098667145, -0.6077089905738831, 0.5368344187736511, -0.1210874393582344, 0.26415619254112244, -0.3066694438457489, 0.1471938043832779, 0.04954215884208679, 0.2045321762561798, 0.1391817331314087, 0.5286830067634583, 0.5764685273170471, 0.1882934868335724, -0.30167853832244873, -0.2122340053319931, -0.45651525259017944, -0.016777794808149338, 0.45624101161956787, -0.0438646525144577, -0.992512047290802, -0.3771328926086426, 0.04916151612997055, -0.5830298066139221, -0.01255014631897211, 0.21600870788097382, -0.18419665098190308, 0.1754663586616516, -0.1499166339635849, -0.1916201263666153, -0.22884036600589752, 0.17280352115631104, 0.25274306535720825, 0.3511175513267517, -0.20270302891731262, -0.6383468508720398, 0.43260180950164795, -0.21136239171028137, -0.05920517444610596, 0.7145522832870483, 0.7626600861549377, -0.5473887920379639, 0.4523043632507324, -0.1723199188709259, -0.10209759324789047, -0.5577948093414307, -0.10156919807195663, 0.31126976013183594, 0.3604489266872406, -0.13295558094978333, 0.2473849356174469, 0.278846800327301, -0.28618067502975464, 0.00527254119515419] ');


Lütfen unutmayın; Yazılım Endüstrisini (yazılım) küçük harfle temsil eden bir kelime vektörü oluştururken, industries.name sütununun büyük harfle yazılan endüstri adıyla (Yazılım) eşleşmesi gerekir.


Oluşturulan tüm kelime vektörleri industries tablosuna eklendikten sonra odak noktamızı RESTful API'yi tanıtmaya değiştirebiliriz.

Spring Boot Hizmetini Tanıtın

Bu, bir yazılım mühendisi olarak tutkumun vites yükselttiği noktaydı çünkü elimdeki zorluğu çözecek her şeye sahiptim.


Daha sonra Spring Boot 3.2.2 ve Java (temurin) 17'yi kullanarak IntelliJ IDEA'da similarity-search-sfdc projesini aşağıdaki Maven bağımlılıklarıyla oluşturdum:


 <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.pgvector</groupId> <artifactId>pgvector</artifactId> <version>0.1.4</version> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>


Hem Hesap nesnesi hem de Endüstri (yerleştirme) nesnesi için, daha önce oluşturulan Postgres veritabanı tablolarıyla aynı hizada olan basitleştirilmiş varlıklar oluşturdum.


 @AllArgsConstructor @NoArgsConstructor @Data @Entity @Table(name = "account", schema = "salesforce") public class Account { @Id @Column(name = "sfid") private String id; private String name; private String industry; } @AllArgsConstructor @NoArgsConstructor @Data @Entity @Table(name = "industries", schema = "salesforce") public class Industry { @Id private String name; }


Postgres tablolarına kolay erişim sağlamak için JpaRepository arayüzünü kullanarak aşağıdaki uzantıları ekledim:


 public interface AccountsRepository extends JpaRepository<Account, String> { @Query(nativeQuery = true, value = "SELECT sfid, name, industry " + "FROM salesforce.account " + "WHERE industry IN (SELECT name " + " FROM salesforce.industries " + " WHERE name != :industry " + " ORDER BY embeddings <-> (SELECT embeddings FROM salesforce.industries WHERE name = :industry) " + " LIMIT :limit)" + "ORDER BY name") Set<Account> findSimilaritiesForIndustry(String industry, int limit); } public interface IndustriesRepository extends JpaRepository<Industry, String> { }


findSimilaritiesForIndustry() yönteminin, bu kullanım senaryosunu çözmek için tüm ağır işlerin gerçekleştirileceği yer olduğuna dikkat edin. Yöntem aşağıdaki parametreleri kabul edecektir:


  • industry : benzerlikleri bulmak için endüstri
  • limit : hesaplar sorgulanırken aranacak sektör benzerliklerinin maksimum sayısı


Yukarıdaki sorgumuzda Öklid uzaklık operatörünü (<->) not edin. Bu, benzerlik aramasını gerçekleştirmek için uzantının yerleşik operatörüdür .


Orijinal "Yazılım" sektörü kullanım durumu ve en yakın üç sektöre ayarlanan limit ile yürütülen sorgu şu şekilde görünecektir:


 SELECT sfid, name, industry FROM salesforce.account WHERE industry IN (SELECT name FROM salesforce.industries WHERE name != 'Software' ORDER BY embeddings <-> (SELECT embeddings FROM salesforce.industries WHERE name = 'Software') LIMIT 3) ORDER BY name;


Oradan, JPA depolarıyla etkileşim kurmak için AccountsService sınıfını oluşturdum:


 @RequiredArgsConstructor @Service public class AccountsService { private final AccountsRepository accountsRepository; private final IndustriesRepository industriesRepository; public Set<Account> getAccountsBySimilarIndustry(String industry, int limit) throws Exception { List<Industry> industries = industriesRepository.findAll(); if (industries .stream() .map(Industry::getName) .anyMatch(industry::equals)) { return accountsRepository .findSimilaritiesForIndustry(industry, limit); } else { throw new Exception( "Could not locate '" + industry + "' industry"); } } }


Son olarak, AccountsController sınıfının RESTful bir giriş noktası sağlamasını ve AccountsService bağlanmasını sağladım:


 @RequiredArgsConstructor @RestController @RequestMapping(value = "/accounts") public class AccountsController { private final AccountsService accountsService; @GetMapping(value = "/similarities") public ResponseEntity<Set<Account>> getAccountsBySimilarIndustry(@RequestParam String industry, @RequestParam int limit) { try { return new ResponseEntity<>( accountsService .getAccountsBySimilarIndustry(industry, limit), HttpStatus.OK); } catch (Exception e) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } } }


Heroku'ya konuşlandır

Spring Boot hizmeti hazır olduğunda projeye aşağıdaki Procfile ekledim ve Heroku'nun hizmetimiz hakkında daha fazla bilgi sahibi olmasını sağladım:


 web: java $JAVA_OPTS -Dserver.port=$PORT -jar target/*.jar


Güvende olmak için, hangi Java ve Maven sürümlerinin beklendiğini belirtmek için system.properties dosyasını ekledim:


 java.runtime.version=17 maven.version=3.9.5


Heroku CLI'yi kullanarak, Heroku platformuna similarity-search-sfdc hizmeti için GitLab depoma bir uzaktan kumanda ekledim:


 heroku git:remote -a similarity-search-sfdc


similarity-search-sfdc hizmetinin buildpack türünü de aşağıdaki komutla ayarladım:


 heroku buildpacks:set https://github.com/heroku/heroku-buildpack-java


Son olarak, aşağıdaki komutu kullanarak similarity-search-sfdc hizmetini Heroku'ya dağıttım:


 git push heroku


Şimdi similarity-search-sfdc uygulamasının Kaynaklar sekmesi aşağıda gösterildiği gibi göründü:


Eylemdeki Benzerlik Araması

RESTful API çalışırken, Yazılım sektörüne en yakın olan ilk üç Salesforce sektörünü (ve ilgili hesapları) bulmak için aşağıdaki cURL komutunu verdim:


 curl --location 'https://HEROKU-APP-ROOT-URL/accounts/similarities?industry=Software&limit=3'


RESTful API, aşağıdaki veriyle birlikte 200 OK HTTP yanıt durumunu döndürür:


 [ { "id": "001Kd00001bsP80IAE", "name": "CleanSlate Technology Group", "industry": "Technology" }, { "id": "001Kd00001bsPBFIA2", "name": "CMG Worldwide", "industry": "Media" }, { "id": "001Kd00001bsP8AIAU", "name": "Dev Spotlight", "industry": "Technology" }, { "id": "001Kd00001bsP8hIAE", "name": "Egghead", "industry": "Electronics" }, { "id": "001Kd00001bsP85IAE", "name": "Marqeta", "industry": "Technology" } ]


Sonuç olarak Teknoloji , Medya ve Elektronik sektörleri bu örnekte Yazılım sektörüne en yakın sektörlerdir.


Artık pazarlama departmanının bir sonraki kampanyaları için iletişime geçebilecekleri hesapların bir listesi var.

Çözüm

Yıllar önce Team Fortress 2 çok oyunculu video oyununu oynayarak itiraf etmek istediğimden daha fazla zaman harcadım. İşte 2012'deki çok eğlenceli bir etkinlikten bir ekran görüntüsü:


Hayatımın bu yönüne aşina olanlar size varsayılan oyuncu sınıfı seçimimin asker olduğunu söyleyebilir. Bunun nedeni askerin sağlık, hareket, hız ve ateş gücü açısından en iyi dengeye sahip olmasıdır.


Yazılım mühendislerinin gerçek dünyanın “asker sınıfı” olduğunu düşünüyorum çünkü her duruma uyum sağlayabiliyoruz ve beklentileri verimli bir şekilde karşılayan çözümler sunmaya odaklanabiliyoruz.


Birkaç yıldır her BT uzmanına uygulanabileceğini düşündüğüm aşağıdaki misyon beyanına odaklandım:


“Zamanınızı fikri mülkiyetinizin değerini artıran özellikler/işlevsellik sunmaya odaklayın. Diğer her şey için çerçevelerden, ürünlerden ve hizmetlerden yararlanın.”

-J.Vester


Bu yazının örneğinde, kurumsal verileri Postgres veritabanıyla senkronize etmek için Heroku Connect'ten yararlanabildik. Pgvector uzantısını yükledikten sonra bu Salesforce hesaplarından her benzersiz sektör için kelime vektörleri oluşturduk. Son olarak, sektörü başka bir sektöre en yakın olan Salesforce hesaplarını bulma sürecini basitleştiren bir Spring Boot hizmetini kullanıma sunduk.


Bu kullanım durumunu mevcut açık kaynak teknolojileri, küçük bir Spring Boot hizmetinin eklenmesi ve Heroku PaaS ile misyon beyanıma tamamen bağlı kalarak hızlı bir şekilde çözdük. Bu çerçeveler, ürünler ve hizmetler olmadan ne kadar zamana ihtiyaç duyulacağını hayal bile edemiyorum.


Eğer ilgileniyorsanız, bu makalenin orijinal kaynak kodunu GitLab'da bulabilirsiniz:


https://gitlab.com/johnjvester/similarity-search-sfdc


Gerçekten harika bir gün geçirin!