paint-brush
ChatGPT, Google Cloud ve Python ile Doküman Analizörü Oluşturunile@shanglun
9,140 okumalar
9,140 okumalar

ChatGPT, Google Cloud ve Python ile Doküman Analizörü Oluşturun

ile Shanglun Wang31m2023/08/05
Read on Terminal Reader
Read this story w/o Javascript

Çok uzun; Okumak

Herhangi bir dildeki belgeleri analiz eden ve belgeyle ilgili her türlü soruyu yanıtlayabilen güçlü bir yapay zeka uygulaması oluşturmak için ChatGPT, Google Cloud ve React JS'yi kullanıyoruz. Araştırmacılar ve kodlayıcılar için harika bir kaynak.
featured image - ChatGPT, Google Cloud ve Python ile Doküman Analizörü Oluşturun
Shanglun Wang HackerNoon profile picture
0-item
1-item

OpenAI, ChatGPT'yi genel kamuoyuna sunduğunda, OpenAI'nin yöneticileri de dahil olmak üzere çok az kişi, genel halk tarafından benimsenme hızını öngörebildi. O zamandan beri ChatGPT, 100 milyon kullanıcıya ulaşan en hızlı uygulama olarak TikTok'un yerini aldı. Hayatın her kesiminden insanlar, verimliliklerini artırmak için ChatGPT'yi kullanmanın yollarını buldu ve şirketler, bunun kullanımına ilişkin yönergeler geliştirmek için çabaladılar. Pek çok akademik kurumun da aralarında bulunduğu bazı kuruluşlar, bunun kullanımına çoğunlukla şüpheyle yaklaşırken, teknoloji şirketleri gibi diğer kuruluşlar ise çok daha liberal bir politika benimsemiş, hatta ChatGPT API etrafında uygulamalar geliştirmiştir. Bugün böyle bir uygulamanın oluşturulmasını ele alacağız.

Hedef kitle

Bu makale üç bölüme ayrılmıştır: 1) uygulamanın temelini oluşturan teknolojilerin açıklaması, 2) uygulamanın arka ucu ve 3) uygulamanın ön ucu. Eğer bazı temel Python kodlarını okuyabiliyorsanız ilk iki bölümü rahatlıkla takip edebilmeniz gerekir, eğer React.js ile ilgili temel bir deneyiminiz varsa üçüncü bölümü de sorunsuz bir şekilde takip edebilirsiniz.

Uygulama

Bugün geliştirdiğimiz uygulama, yabancı dil kaynaklarını kullanarak düzenli olarak araştırma yapan herkesin işine yarayacaktır. Bunun iyi bir örneği, sıklıkla yabancı dillerde yayınlanan hükümet raporlarını okumak zorunda kalan makroiktisatçılar olabilir. Bazen bu raporlar makine çeviri hizmetlerine kopyalanıp yapıştırılabilir, ancak bazen aranamayan PDF'ler biçiminde yayınlanırlar. Bu durumlarda araştırmacının insan çevirmenlerle çalışması gerekecektir, ancak kaynak kısıtlamaları çevrilebilecek raporların sayısını önemli ölçüde sınırlamaktadır. Sorunu daha da karmaşık hale getirmek için, bu raporların okunması çok uzun ve sıkıcı olabilir; bu da çeviri ve analizi maliyetli ve zaman alıcı hale getirir.


Uygulamamız, çeşitli yapay zeka ve makine öğrenimi araçlarını (OCR, Makine Çevirisi ve Büyük Dil Modelleri) birleştirerek bu süreci kolaylaştıracaktır. Ham metin içeriğini OCR kullanarak bir PDF'den çıkaracağız, makine çevirisini kullanarak İngilizceye çevireceğiz ve çevrilmiş çıkarma işlemini büyük bir dil modeli kullanarak analiz edeceğiz.


Bugünkü başvuru için Japon hükümetinin PDF yayınına ve Eğitim, Kültür, Spor, Bilim ve Teknoloji Bakanlığı'nın İnovasyon Beyaz Kitabına bakacağız. PDF'nin kendisi aranabilir ve bir çeviri motoruna kopyalanabilir olsa da, uygulamada kullanılan teknolojileri sergilemek için PDF'de arama yapılamazmış gibi davranacağız. Orijinal belgeyi burada bulabilirsiniz.


Uygulamayı şimdi oluşturmak istiyorsanız sonraki bölümü atlamaktan çekinmeyin. Ancak bu makalede kullanacağımız çeşitli teknolojileri daha iyi anlamak istiyorsanız bir sonraki bölümde size biraz arka plan bilgisi vereceğiz.

Temel Teknolojiler

Kullanacağımız ilk teknoloji, genel kullanıma sunulan en eski ticari makine öğrenimi uygulamalarından biri olan OCR veya Optik Karakter Tanıma'dır. OCR modelleri ve uygulamaları, bir resim veya görüntü çekmeyi, ardından görüntüdeki metin bilgisini tanımlayıp çıkarmayı amaçlamaktadır. Bu ilk başta basit bir iş gibi görünebilir ancak sorun aslında oldukça karmaşıktır. Örneğin harfler biraz bulanık olabilir, bu da olumlu bir tanımlama yapmayı zorlaştırır. Mektup ayrıca alışılmadık bir yönde de düzenlenebilir; bu, makine öğrenimi modelinin dikey ve baş aşağı metni tanımlaması gerektiği anlamına gelir. Bu zorluklara rağmen araştırmacılar birçok hızlı ve güçlü OCR modeli geliştirdiler ve bunların çoğu nispeten düşük maliyetle mevcut. Bugünkü uygulamamız için Google Cloud API kullanarak erişebileceğimiz Google'ın Cloud Vision modelini kullanacağız.


Kullanacağımız bir sonraki teknoloji makine çevirisidir. Bu, OCR gibi son derece zor bir makine öğrenme sorunudur. İnsan dili, bilgisayarların işlemesini ve anlamasını özellikle zorlaştıran kendine has özellikler ve bağlamsal karmaşıklıklarla doludur. Çince ve İngilizce gibi farklı dil çiftleri arasındaki çeviri, bu dillerin doğası gereği farklı yapısı nedeniyle, dijitalleştirme ve yerleştirme için çok farklı stratejiler gerektirmesi nedeniyle özellikle hatalı ve komik sonuçlar verme eğilimindedir. Ancak bu zorluklara rağmen araştırmacılar güçlü ve karmaşık modeller geliştirerek bunları genel kullanıma sunmuşlardır. Bugün, mevcut en iyi ve en yaygın kullanılan makine çevirisi araçlarından biri olan Google Çeviri API'sini kullanacağız.


Kullanacağımız son makine öğrenimi teknolojisi, tüketici yapay zekası için devrim niteliğinde olan LLM veya Büyük Dil Modeli'dir. LLM, doğal insan dilinin yapısını anlayabilir ve ayrıntılı ve bilgilendirici bir yanıt üretmek için geniş bir veri kümesinden yararlanabilir. Teknolojinin hâlâ pek çok sınırlaması var, ancak esnekliği ve veri işleme yetenekleri, modelle etkileşime geçmek için birçok yeni tekniğin yaratılmasına ilham kaynağı oldu. Böyle bir teknik, İstenilen sonucu elde etmek için kullanıcıların modele ustaca ifade edilmiş ve yapılandırılmış girdiler veya istemler oluşturup ince ayar yaptığı İstem Mühendisliği olarak adlandırılır. Bugünkü uygulamada, çevrilmiş raporu analiz etmemize yardımcı olması için ChatGPT'nin API'sini ve bazı basit istem mühendisliğini kullanacağız.

Arka uç

Bulut Hizmetleri Kurulumu

Uygulamayı kodlamaya başlamadan önce hizmetlere kaydolmamız gerekecek.


ChatGPT'nin API web sitesi sürekli değiştiğinden, ChatGPT API'sine kaydolmak için tam adımları sağlayamayacağız. Ancak API dokümantasyonu web sitesinde takip edilmesi kolay talimatlar bulacaksınız. ChatGPT API'sini çağırmamız gereken bir API anahtarı alana kadar ilerleyin.


Google Cloud biraz daha karmaşıktır ancak kaydolması da nispeten basittir. Google Cloud konsoluna gidip proje oluşturma talimatlarını uygulamanız yeterlidir. Projeye girdikten sonra IAM ve Yönetici konsoluna gidip bir hizmet hesabı oluşturmak isteyeceksiniz. Google Cloud konsolu sürekli değişirken, web sayfasında yalnızca "IAM" ve "Hizmet Hesabı"nı arayarak arayüzde gezinebilmeniz gerekir. Hizmet hesabı oluşturulduktan sonra özel anahtar dosyasının kopyasını bilgisayarınıza indirmek isteyeceksiniz. Çeviri REST API'si anahtar dosyası yerine özel anahtar dizesini kullandığından, özel anahtar dizesini de kopyalamak isteyeceksiniz.


Google Cloud kurulumunu tamamlamadan önce, ana konsol sayfasından yapabileceğiniz Makine Görme API'sini etkinleştirmek isteyeceksiniz. Basitçe Makine Görme API'sini arayın, Google'daki ürüne tıklayın ve API'yi etkinleştirin. Ayrıca bu proje için kullanacağımız verileri tutacak bir paket oluşturmak isteyeceksiniz.

Python Kurulumu

Artık uygun hizmetlere kaydolduğumuza göre uygulamamızı Python'da kodlamaya başlamaya hazırız. Öncelikle gerekli paketleri Python ortamımıza kurmak isteyeceğiz.


Pip install google-cloud-storage google-cloud-vision openai requests


Kurulum tamamlandıktan sonra yeni bir klasör oluşturalım, PDF dosyasını indirelim ve aynı klasörde yeni bir Python dosyası oluşturalım. Biz buna document_analyze.py adını vereceğiz. Gerekli paketleri içe aktararak başlıyoruz:


 import requests Import openai from google.cloud import vision from google.cloud import storage Import os Import json Import time Import shutil

Daha sonra uygulamamızın yeni kaydolduğumuz bulut hizmetlerini kullanabilmesi için bazı temel kurulumlar yapabiliriz:

 os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = [Path to your Google Cloud key file] openai.api_key = [your openAI API key]

Bu kimlik bilgilerinin yerine getirilmesiyle artık Python komut dosyanızdan Google Cloud ve ChatGPT API'lerine erişebilmeniz gerekir. Artık uygulamamız için istenilen işlevselliği sağlayacak fonksiyonları yazabiliriz.

OCR Kodu

Artık uygulamanın yapı taşı olacak bazı fonksiyonları oluşturmaya başlayabiliriz. OCR işlevleriyle başlayalım:


 # upload the file to google cloud storage bucket for further processing def upload_file(file_name, bucket_name, bucket_path): client = storage.Client() bucket = client.get_bucket(bucket_name) blob = bucket.blob(bucket_path) blob.upload_from_filename(file_name) # kick off the OCR process on the document. This is asynchronous because OCR can take a while def async_detect_document(gcs_source_uri, gcs_destination_uri): client = vision.ImageAnnotatorClient() input_config = vision.InputConfig(gcs_source=vision.GcsSource(uri=gcs_source_uri), mime_type= 'application/pdf') output_config = vision.OutputConfig( gcs_destination=vision.GcsDestination(uri=gcs_destination_uri), batch_size=100 ) async_request = vision.AsyncAnnotateFileRequest( features=[vision.Feature(type_=vision.Feature.Type.DOCUMENT_TEXT_DETECTION)], input_config=input_config, output_config=output_config ) operation = client.async_batch_annotate_files(requests=[async_request]) def check_results(bucket_path, prefix): storage_client = storage.Client() bucket = storage_client.get_bucket(bucket_path) blob_list = list(bucket.list_blobs(prefix=prefix)) blb = [b for b in blob_list if 'output-' in b.name and '.json' in b.name] return len(blb) != 0 # download the OCR result file def write_to_text(bucket_name, prefix): bucket = storage.Client().get_bucket(bucket_name) blob_list = list(bucket.list_blobs(prefix=prefix)) if not os.path.exists('ocr_results'): os.mkdir('ocr_results') for blob in blob_list: if blob.name.endswith('.json'): with open(os.path.join('ocr_results', blob.name), 'w') as fp_data: fp_data.write(blob.download_as_string().decode('utf-8')) def delete_objects(bucket, prefix): bucket = storage.Client().get_bucket(bucket) blob_list = list(bucket.list_blobs(prefix=prefix)) for blob in blob_list: blob.delete() print('Blob', blob.name, 'Deleted')


Her fonksiyonun ne işe yaradığını detaylı olarak inceleyelim.


upload_file işlevi, Google Cloud Storage kapsayıcısından bir paket alan ve dosyanızı ona yükleyen bir işlevdir. Google Cloud'un mükemmel soyutlamaları bu işlevin yazılmasını çok kolaylaştırır.


async_detect_document işlevi, eşzamansız olarak Google Cloud'un OCR işlevini çağırır. Google Cloud'da mevcut olan seçeneklerin sayısı nedeniyle birkaç yapılandırma nesnesi oluşturmamız gerekiyor, ancak bu aslında yalnızca Google Cloud'un kaynak dosyanın nerede olduğunu ve çıktının nereye yazılması gerektiğini bilmesini sağlıyor. batch_size değişkeni 100 olarak ayarlandığından Google Cloud, belgeyi tek seferde 100 sayfa işleyecektir. Bu, yazılan çıktı dosyalarının sayısını azaltır ve bu da işlemeyi kolaylaştırır. Dikkat edilmesi gereken bir diğer önemli husus, çağrının eşzamansız olmasıdır; bu, Python betiğinin yürütülmesinin, işlemin bitmesini beklemek yerine devam edeceği anlamına gelir. Bu, bu aşamada büyük bir fark yaratmasa da, daha sonra Python kodunu bir web API'sine dönüştürdüğümüzde daha kullanışlı hale gelecektir.


check_results işlevi, işlemin yapılıp yapılmadığını kontrol etmek için kullanılan basit bir bulut depolama işlevidir. OCR işlevini eşzamansız olarak çağırdığımız için, sonuç dosyasının mevcut olup olmadığını görmek için bu işlevi periyodik olarak çağırmamız gerekir. Sonuç dosyası varsa fonksiyon true değerini döndürür ve analize devam edebiliriz. Sonuç dosyası yoksa fonksiyon false değerini döndürecek ve işlem bitene kadar beklemeye devam edeceğiz.


write_to_text işlevi, sonuç dosyalarını daha ileri işlemler için diske indirir. İşlev, paketinizdeki tüm dosyaları belirli bir önekle yineleyecek, çıktı dizesini alacak ve sonucu yerel dosya sistemine yazacaktır.


delete_objects işlevi, OCR ile tam olarak alakalı olmasa da, sistemin gereksiz yapıları Google Bulut Depolama'da tutmaması için yüklenen dosyaları temizler.


Artık OCR çağrılarını bitirdiğimize göre makine çeviri koduna bakalım!

Makine Çeviri Kodu

Artık çeviri fonksiyonlarını tanımlayabiliriz:


 # detect the language we're translating from def detect_language(text): url = 'https://translation.googleapis.com/language/translate/v2/detect' data = { "q": text, "key": [your google cloud API key] } res = requests.post(url, data=data) return res.json()['data']['detections'][0][0]['language'] # translate the text def translate_text(text): url = 'https://translation.googleapis.com/language/translate/v2' language = detect_language(text) if language == 'en': return text data = { "q": text, "source": language, "target": "en", "format": "text", "key": [your google cloud API key] } res = requests.post(url, data=data) return res.json()['data']['translations'][0]['translatedText']


Bu işlevler oldukça basittir. detect_language işlevi, sonraki translate_text çağrısının kaynak dilini belirlemek için dil algılama API'sini çağırır. PDF'nin Japonca yazıldığını bilsek de uygulamanın diğer dilleri işleyebilmesi için dil algılamayı çalıştırmak yine de en iyi yöntemdir. translate_text işlevi, metni algılanan kaynak dilden İngilizceye çevirmek için Google Çeviri API'sini kullanır; ancak kaynak dilin zaten İngilizce olduğunu belirlerse çeviriyi atlar.

ChatGPT Kodu ve İstemi Mühendisliği

Son olarak ChatGPT'ye çağrılarımız var:

 def run_chatgpt_api(report_text): completion = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=[ {"role": "user", "content": ''' Consider the following report: --- %s --- 1. Summarize the purpose of the report. 2. Summarize the primary conclusion of the report. 3. Summarize the secondary conclusion of the report 4. Who is the intended audience for this report? 5. What other additional context would a reader be interested in knowing? Please reply in json format with the keys purpose, primaryConclusion, secondaryConclusion, intendedAudience, and additionalContextString. ''' % report_text}, ] ) return completion.choices[0]['message']['content']


Python çağrısının nispeten basit bir API çağrısı olduğuna, ancak istemin belirli sonuçlar üretecek şekilde yazıldığına dikkat edin:


  1. İstem, rapor metnini bağlam olarak sağlar, böylece ChatGPT raporu kolayca analiz edebilir. Metnin sınırları kesik çizgiler kullanılarak çizilmiş olup, raporun nerede bitip soruların nerede başladığının anlaşılmasını kolaylaştırır.

  2. Sorular paragraf formatında belirtilmek yerine numaralandırılmıştır. Bu nedenle tepkinin benzer bir yapıyı takip etmesi muhtemeldir. Numaralandırılmış yapı, sonucun kodla ayrıştırılmasını ChatGPT'nin paragraf biçiminde yanıtlamasına göre çok daha kolay hale getirir.

  3. Bilgi istemi yanıtın biçimini, bu durumda JSON biçimini belirtir. JSON formatının kodla işlenmesi çok kolaydır.

  4. İstem, JSON nesnesinin anahtarlarını belirtir ve sorularla ilişkilendirilmesi çok kolay olan anahtarları seçer.

  5. Anahtarlar ayrıca ChatGPT'nin tanıması gereken yaygın olarak kullanılan bir kuralı (camelCase) kullanır. JSON anahtarları kısaltmalar yerine tam kelimelerdir. Bu, ChatGPT'nin işleme sürecinin bir parçası olarak "yazım düzeltmeleri" yapma alışkanlığı olduğundan, ChatGPT'nin yanıtta gerçek anahtarı kullanma olasılığını artırır.

  6. İlaveContextString, ChatGPT'nin ek bilgileri iletmesi için bir çıkış sağlar. Bu, büyük dil modellerinin serbest biçimli analiz yeteneğinden yararlanır.

  7. Bilgi istemi, eldeki konuyla ilgili teknik tartışmalarda sıklıkla bulunan ifadeleri kullanır. API çağrısının yapısından da tahmin edebileceğiniz gibi, ChatGPT'nin "gerçek" hedefi, isteğe bir yanıt sağlamak değil, diyalogdaki bir sonraki satırı tahmin etmektir.

    Bu nedenle, eğer isteminiz yüzeysel bir tartışmadan alınan bir satır gibi ifade edilmişse, muhtemelen yüzeysel bir cevap alırsınız; oysa, eğer isteminiz bir uzman tartışmasından alınmış bir satır gibi ifade edilmişse, uzman bir sonuç alma olasılığınız daha yüksektir. Bu etki özellikle matematik veya teknoloji gibi konularda belirgindir ancak burada da geçerlidir.


Yukarıdakiler, kullanıcının belirli bir sonuç elde etmek için istemlerini yapılandırdığı "istem mühendisliği" adı verilen yeni bir çalışma grubundaki temel tekniklerdir. ChatGPT gibi büyük dil modellerinde, istemin dikkatli bir şekilde hazırlanması, modelin etkililiğinde çarpıcı artışlara neden olabilir. Kodlamaya pek çok benzerlik vardır, ancak hızlı mühendislik, mühendis açısından çok daha fazla sezgi ve bulanık akıl yürütme gerektirir. ChatGPT gibi araçlar işyerinde daha fazla yerleşik hale geldikçe, mühendislik artık tamamen teknik bir çaba değil, aynı zamanda felsefi bir çaba olacaktır ve mühendisler, büyük dil modelleri için sezgilerini ve bir "zihin teorisini" geliştirmeye özen göstermelidir. onların verimliliği.

Hepsini bir araya koy

Şimdi hepsini bir araya getirelim. Önceki bölümü izlediyseniz aşağıdaki kod bloğunun anlaşılması oldukça kolay olacaktır.


 bucket = [Your bucket name] upload_file_name = [the name of the PDF in the Google Cloud bucket] upload_prefix = [the prefix to use for the analysis results] pdf_to_analyze = [path to the PDF to analyze] upload_file(pdf_to_analyze, bucket, upload_file_name) async_detect_document(f'gs://{bucket}/{upload_file_name}', f'gs://{bucket}/{upload_prefix}') while not check_results(bucket, upload_prefix): print('Not done yet... checking again') time.sleep(5) If __name__ == '__main__': write_to_text(bucket, upload_prefix) all_responses = [] for result_json in os.listdir('ocr_results'): with open(os.path.join('ocr_results', result_json)) as fp_res: response = json.load(fp_res) all_responses.extend(response['responses']) texts = [a['fullTextAnnotation']['text'] for a in all_responses] translated_text = [translate_text(t) for t in texts] print('Running cleanup...') delete_objects(bucket, upload_file_name) delete_objects(bucket, upload_prefix) shutil.rmtree('ocr_results') print('Running Analysis...') analysis = run_chatgpt_api('\n'.join(translated_text)) print('=== purpose ====') print(analysis_res['purpose']) print() print('==== primary conclusion =====') print(analysis_res['primaryConclusion']) print() print('==== secondary conclusion =====') print(analysis_res['secondaryConclusion']) print() print('==== intended audience ====') print(analysis_res['intendedAudience']) print() print('===== additional context =====') print(analysis_res['additionalContextString'])


Raporu pakete yüklüyoruz, OCR'yi başlatıyoruz ve OCR'nin bitmesini bekliyoruz. Daha sonra OCR sonuçlarını indirip bir listeye koyuyoruz. Sonuç listesini tercüme edip analiz için ChatGPT'ye gönderiyoruz ve analiz sonucunun çıktısını alıyoruz.


Yapay zeka araçları belirleyici olmadığından, bu kodu çalıştırırsanız muhtemelen benzer ancak aynı olmayan bir sonuç elde edersiniz. Ancak yukarıda bağlantılı PDF'yi kullanarak çıktı olarak elde ettiğim şey şu:


 Not done yet... checking again Not done yet... checking again Running cleanup... Blob [pdf name] Deleted Blob [OCR Output Json] Deleted Running Analysis... === purpose ==== The purpose of the report is to analyze the current status and issues of Japan's research capabilities, discuss the government's growth strategy and investment in science and technology, and introduce the initiatives towards realizing a science and technology nation. ==== primary conclusion ===== The primary conclusion of the report is that Japan's research capabilities, as measured by publication index, have been declining internationally, raising concerns about a decline in research capabilities. ==== secondary conclusion ===== The secondary conclusion of the report is that the Kishida Cabinet's growth strategy emphasizes becoming a science and technology nation and strengthening investment in people to achieve growth and distribution. ==== intended audience ==== The intended audience for this report is government officials, policymakers, researchers, and anyone interested in Japan's research capabilities and science and technology policies. ===== additional context ===== The report focuses on the importance of science, technology, and innovation for Japan's future development and highlights the government's efforts to promote a 'new capitalism' based on a virtuous cycle of growth and distribution. It also mentions the revision to the Basic Law on Science, Technology, and Innovation, the 6th Science, Technology, and Innovation Basic Plan, and the concept of Society 5.0 as the future society Japan aims for. The report suggests that comprehensive knowledge is necessary to promote science, technology, and innovation and emphasizes the importance of transcending disciplinary boundaries and utilizing diverse knowledge.


Japonca konuşan biri olarak analizin oldukça iyi olduğunu doğrulayabilirim! Kendi PDF'nizi sağlayarak ve soruları ihtiyaçlarınıza göre değiştirerek kendi başınıza denemeler yapabilirsiniz. Artık karşılaştığınız herhangi bir yabancı dil PDF dosyasını tercüme etmek ve özetlemek için güçlü bir yapay zeka aracına sahipsiniz. Bu makalenin hedef kitlesi arasındaysanız, umarım yeni açılan fırsatlardan dolayı biraz heyecan duyuyorsunuzdur!


Arka uç kodunun tamamını GitHub'ımda bulabilirsiniz

Ön Uç

Zaten güçlü bir uygulama geliştirdik, ancak mevcut haliyle kullanıcının uygulamayı tam anlamıyla kullanabilmesi için biraz Python bilmesi gerekecek. Peki ya herhangi bir kod okumak veya yazmak istemeyen bir kullanıcınız olsaydı? Bu durumda, insanların yapay zekanın tüm gücüne tarayıcı rahatlığında erişebilmesi için bu aracın etrafında bir web uygulaması oluşturmak isteyeceğiz.

React Uygulamasının Yapılandırılması

Bir React uygulaması oluşturarak başlayalım. Node'un kurulu olduğundan emin olun, uygulama kodunun yaşamasını istediğiniz klasöre gidin ve create-react-app betiğini çalıştırın ve bazı temel paketleri yükleyin:


npx create-react-app llm-frontend


Ve daha sonra:


 cd llm-frontend npm install bootstrap react-bootstrap axios


Tam teşekküllü bir uygulama geliştiriyor olsaydık, durum yönetimi ve yönlendirmeyi idare edecek paketleri de kurmak isterdik, ancak bu, bu makalenin kapsamı dışındadır. Sadece App.jsx dosyasında düzenlemeler yapacağız.


Geliştirme sunucusunu başlatmak için npm run start çalıştırın; tarayıcınız http://localhost:3000 adresine bir sayfa açmalıdır. Bu sayfayı saklayın ve favori metin düzenleyicinizde App.jsx dosyasını açın. Bunun gibi bir şey görmelisiniz:


 import logo from './logo.svg'; import './App.css'; function App() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p> Edit <code>src/App.js</code> and save to reload. </p> <a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer" > Learn React </a> </header> </div> ); } export default App;


Devam edin ve standart kodu silin ve onu bazı temel Bootstrap bileşenleriyle değiştirin.


 import React, {useState, useEffect} from 'react'; Import axios from 'axios'; import Container from 'react-bootstrap/Container'; import Row from 'react-bootstrap/Row'; import Col from 'react-bootstrap/Col'; import 'bootstrap/dist/css/bootstrap.min.css'; function App() { return ( <Container> <Row> <Col md={{ span: 10, offset: 1 }}> Main Application Here </Col> </Row> </Container> ); } export default App;


Uygulamayı kaydedin; tarayıcıda güncellendiğini görmelisiniz. Şimdilik oldukça seyrek görünecek ama endişelenmeyin, bunu yakında düzelteceğiz.

Uygulama Bileşenleri

Bu uygulamanın çalışması için dört ana bileşene ihtiyacımız olacak: dosyayı yüklemek için bir dosya seçici, çeviriyi ve özeti görüntülemek için bir sonuç ekranı, kullanıcının kendi sorularını sorabilmesi için bir metin girişi ve görüntülenecek bir sonuç ekranı. Kullanıcı sorularının cevabı.


Şimdilik daha basit bileşenleri oluşturabilir ve daha karmaşık arayüzler için yer tutucular yerleştirebiliriz. Hazır bu arada arayüzü güçlendirmek için kullanacağımız veri kaplarını oluşturalım:


 import React, {useState, useEffect} from 'react'; import axios from 'axios'; import Container from 'react-bootstrap/Container'; import Row from 'react-bootstrap/Row'; import Col from 'react-bootstrap/Col'; import Button from 'react-bootstrap/Button'; import Accordion from 'react-bootstrap/Accordion'; import Form from 'react-bootstrap/Form'; import ListGroup from 'react-bootstrap/ListGroup'; import 'bootstrap/dist/css/bootstrap.min.css'; const ResultDisplay = ({ initialAnalysis, userQuestion, setUserQuestion, userQuestionResult, userQuestionMessage, userQuestionAsked }) => { return <Row> <Col> <Row style={{marginTop: '10px'}}> <Col md={{ span: 10, offset: 1 }}> <Accordion defaultActiveKey="0"> <Accordion.Item eventKey="0"> <Accordion.Header>Analysis Result</Accordion.Header> <Accordion.Body> {initialAnalysis.analysis} </Accordion.Body> </Accordion.Item> <Accordion.Item eventKey="1"> <Accordion.Header>Raw Translated Text</Accordion.Header> <Accordion.Body> {initialAnalysis.translatedText} </Accordion.Body> </Accordion.Item> <Accordion.Item eventKey="2"> <Accordion.Header>Raw Source Text</Accordion.Header> <Accordion.Body> {initialAnalysis.rawText} </Accordion.Body> </Accordion.Item> </Accordion> </Col> </Row> <Row style={{marginTop: '10px'}}> <Col md={{ span: 8, offset: 1 }}> <Form.Control type="text" placeholder="Additional Questions" value={userQuestion} onChange={e => setUserQuestion(e.target.value)} /> </Col> <Col md={{ span: 2 }}> <Button variant="primary">Ask</Button> </Col> </Row> <Row><Col>{userQuestionMessage}</Col></Row> <Row style={{marginTop: '10px'}}> <Col md={{span: 10, offset: 1}}> {userQuestionResult && userQuestionAsked ? <ListGroup> <ListGroup.Item> <div><b>Q:</b> {userQuestionAsked}</div> <div><b>A:</b> {userQuestionResult}</div></ListGroup.Item> </ListGroup>: ''} </Col> </Row> </Col> </Row> } function App() { const [file, setFile] = useState(null); const [haveFileAnalysisResults, setHaveFileAnalysisResults] = useState(false); const [message, setMessage] = useState(''); const [userQuestionMessage, setUserMessage] = useState(''); const [initialAnalysis, setInitialAnalysis] = useState({analysis: '', translatedText: '', rawText: ''}); const [userQuestion, setUserQuestion] = useState(''); const [userQuestionResult, setUserQuestionResult] = useState(''); const [userQuestionAsked, setUserQuestionAsked] = useState(''); return ( <Container> <Row> <Col md={{ span: 8, offset: 1 }}> <Form.Group controlId="formFile"> <Form.Label>Select a File to Analyze</Form.Label> <Form.Control type="file" onChange={e => setFile(e.target.files[0])} /> </Form.Group> </Col> <Col md={{span: 2}}> <div style={{marginTop: '30px'}}><Button variant="primary" >Analyze</Button></div> </Col> <Col md={12}>{message}</Col> </Row> {haveFileAnalysisResults? <ResultDisplay initialAnalysis={initialAnalysis} userQuestion={userQuestion} setUserQuestion={setUserQuestion} userQuestionResult={userQuestionResult} userQuestionMessage={userQuestionMessage} userQuestionAsked={userQuestionAsked} />: ''} </Container>); }


Oldukça fazla yeni kod var, ancak yeni kodda karmaşık veya çığır açıcı hiçbir şey yok. Kod, React-Bootstrap bileşenlerini temel alan yalnızca temel bir veri girişi ve görüntüleme arayüzüdür.


Dosyayı kaydedin; tarayıcınızın dosya yükleme arayüzünü gösterecek şekilde güncellendiğini görmelisiniz.

Değişkenlerle oynayın ve bunun gibi bir arayüz görmelisiniz. Bu uygulamamızın ön arayüzü olacak.


Artık temel ön yüz arayüzünü yazdığımıza göre, uygulamayı (henüz yazılmamış) API'mize bağlayacak fonksiyonları yazalım. Bu işlevlerin tümü uygulama nesnesinde tanımlanacak ve böylece tüm React kancalarına erişebilecek. Bu işlevlerin nereye gitmesi gerektiğinden tam olarak emin değilseniz GitHub'da barındırılan kodun tamamına başvurabilirsiniz.


Öncelikle kullanıcıya mesaj iletmek için birkaç yardımcı fonksiyon yazalım.


 const flashMessageBuilder = (setMessage) => (message) => { setMessage(message); setTimeout(() => { setMessage(''); }, (5000)); } const flashMessage = flashMessageBuilder(setMessage); const flashUserQuestionMessage = flashMessageBuilder(setUserQuestionMessage);


Gördüğünüz gibi bunlar bir mesajı uygun yerde görüntüleyen ve mesajın 5 saniye sonra kaldırılması için bir süre yaratan basit işlevlerdir. Bu basit bir kullanıcı arayüzü özelliğidir ancak uygulamanın çok daha dinamik ve kullanışlı olmasını sağlar.


Daha sonra dosyayı analiz etmek ve sonuçları kontrol etmek için fonksiyonları yazalım.


 const pollForResults = (batchId) => { flashMessage('Checking for results...'); return new Promise((resolve, reject) => { setTimeout(() => { axios.post('http://localhost:5000/check_if_finished', {batchId}) .then(r => r.data) .then(d => { // the result should have a "status" key and a "result" key. if (d.status === 'complete') { resolve(d); // we're done! } else { resolve(pollForResults(batchId)); // wait 5 seconds and try again. } }).catch(e => reject(e)); }, 5000); }) } const analyzeFile = () => { if (file === null) { flashMessage('No file selected!'); return; } flashMessage('Uploading file...'); const formData = new FormData(); formData.append("file", file); axios.post("http://localhost:5000/analyze_file", formData, { headers: { 'Content-Type': 'multipart/form-data' } }).then(r => r.data) .then(d => { // the result should contain a batchId that we use to poll for results. flashMessage('File upload success, waiting for analysis results...'); return pollForResults(d.batchId); }) .then(({analysis, translatedText, rawText}) => { // the result should contain the initial analysis results with the proper format. setInitialAnalysis({analysis, translatedText, rawText}); setHaveFileAnalysisResults(true); // show the results display now that we have results }) .catch(e => { console.log(e); flashMessage('There was an error with the upload. Please check the console for details.'); }) }


Yine oldukça basit bir işlevler kümesi. analyzeFile işlevi, dosyayı analiz için analyze_file uç noktasına gönderir. API ona pollForResults işleviyle sonuçları kontrol etmek için kullandığı bir toplu kimlik numarası verecektir. pollForResults işlevi check_if_finished uç noktasına ulaşacak ve analiz bitmişse sonuçları döndürecek ve analiz hala işleniyorsa 5 saniye bekleyecektir. AnalizFile “iş parçacığı” daha sonra veriyi uygun yerlere koyarak çalışmaya devam edecektir.


Son olarak kullanıcının serbest soru sormasını sağlayan fonksiyonu yazalım:


 const askUserQuestion = () => { flashUserQuestionMessage('Asking user question...') axios.post('http://localhost:5000/ask_user_question', { text: initialAnalysis.translatedText, userQuestion }).then(r => r.data) .then(d => { setUserQuestionResult(d.result); setUserQuestionAsked(userQuestion); }).catch(e => { console.log(e); flashUserQuestionMessage('There was an issue asking the question. Please check the console for details'); }); }


Yine oldukça basit bir fonksiyon. API'mızın ChatGPT istemini oluşturabilmesi için çevrilmiş metni kullanıcı sorusuyla birlikte sağlıyoruz. Sonuç daha sonra görüntülenmek üzere uygun veri kaplarına gönderilir.


React uygulamasıyla işimiz neredeyse bitti, ancak API'yi kodlamaya geçmeden önce bir kozmetik değişiklik daha yapalım. Şu anda analiz sonucu ekranı, ChatGPT analizini bir dize olarak gösterecek şekilde yapılandırılmıştır. Bununla birlikte, ChatGPT analizi aslında bir JSON veri nesnesidir, dolayısıyla bunu insanların kullanımına uygun şekilde görüntülemek için görüntüleme nesnesine bazı biçimlendirmeler eklemek isteyeceğiz. İlk Akordeon öğesini aşağıdaki kodla değiştirin:


 <Accordion.Item eventKey="0"> <Accordion.Header>Analysis Result</Accordion.Header> <Accordion.Body> <h6>Purpose</h6> <p>{analysis.purpose}</p> <h6>Primary Conclusion</h6> <p>{analysis.primaryConclusion}</p> <h6>Secondary Conclusion</h6> <p>{analysis.secondaryConclusion}</p> <h6>Intended Audience</h6> <p>{analysis.intendedAudience}</p> <h6>Additional Context</h6> <p>{analysis.additionalContextString}</p> </Accordion.Body> </Accordion.Item>


Artık ön uç tamamlandı, hadi Python kodumuza gidelim ve arka ucu oluşturalım.

Şişe API'si

Öncelikle backendimizi yazmak için kullanacağımız Flask'ı kuralım.


Pip install flask flask-cors


Flask, web uygulamaları ve web API'leri oluşturmaya yönelik basit bir çerçevedir. Arayüz son derece basittir ve bir sunucunun çalışmasını sağlamak şu kadar kolaydır:


 from flask import Flask, request, jsonify from flask_cors import CORS app = Flask(__name__) CORS(app) @app.route('/') def hello_world(): return "Hello from flask!" if __name__ == '__main__': app.run(debug=True)


Bu dosyayı çalıştırın ve tarayıcınızda http://localhost:5000 adresine gidin; “Şişeden merhaba!” mesajını görmelisiniz. İleti.


Artık API işlevselliğini oluşturmaya başlayabiliriz. Gerekli işlevleri içe aktararak ve bazı sabitleri tanımlayarak başlayalım:


 from flask import Flask, request, jsonify from flask_cors import CORS import uuid import os import json from document_analyze import upload_file, async_detect_document, check_results, \ write_to_text, translate_text, delete_objects, run_chatgpt_api,\ ask_chatgpt_question app = Flask(__name__) CORS(app) BUCKET = '[YOUR BUCKET NAME]'


Bu kod, sunucu kodunuzun daha önce yazdığımız document_analyze.py dosyasıyla aynı klasörde olduğunu varsayar, ancak sunucu kodu document_analyze.py'yi bulup buradan içe aktarabildiği sürece istediğiniz dizin yapısını seçebilirsiniz. Dosya yükleme uç noktası için işleyiciyi yazalım:


 @app.route('/analyze_file', methods=['POST']) def analyze_file(): file_to_analyze = request.files['file'] batch_name = str(uuid.uuid4()) local_file_path = 'uploads/%s.pdf' % batch_name cloud_file_path = '%s.pdf' % batch_name file_to_analyze.save(local_file_path) upload_file(local_file_path, BUCKET, cloud_file_path) async_detect_document( f'gs://{BUCKET}/{cloud_file_path}', f'gs://{BUCKET}/{batch_name}') return jsonify({ 'batchId': batch_name })


Gördüğünüz gibi bu fonksiyon yüklenen dosyayı alıp Google Cloud Storage'a gönderiyor ve OCR sürecini başlatıyor. Oldukça tanıdık gelebilir ama burada dikkat çekmeye değer birkaç küçük değişiklik var. İlk olarak dosya, aynı zamanda toplu iş adı olarak da hizmet veren bir UUID ile tanımlanır. Bu, API'nin birden çok kez çağrılmasından kaynaklanabilecek olası çakışma sorunlarını önler ve aynı zamanda belirli bir analiz grubunda kullanılan tüm dosyaları benzersiz bir şekilde tanımlayarak ilerlemeyi kontrol etmeyi ve baştan sona temizleme gerçekleştirmeyi kolaylaştırır.


Şimdi uygulamanın analizin bitip bitmediğini kontrol etmesini sağlayan işleyiciyi yazalım.


 @app.route('/check_if_finished', methods=['POST']) def check_if_finished(): batch_name = request.json['batchId'] if not check_results(BUCKET, batch_name): return jsonify({ 'status': 'processing' }) write_to_text(BUCKET, batch_name) all_responses = [] for result_json in os.listdir('ocr_results'): if result_json.endswith('json') and result_json.startswith(batch_name): result_file = os.path.join('ocr_results', result_json) with open(os.path.join('ocr_results', result_json)) as fp_res: response = json.load(fp_res) all_responses.extend(response['responses']) os.remove(result_file) txts = [a['fullTextAnnotation']['text'] for a in all_responses] translated_text = [translate_text(t) for t in txts] print('Running cleanup...') delete_objects(BUCKET, batch_name) os.remove('uploads/%s.pdf' % batch_name) analysis = run_chatgpt_api('\n'.join(translated_text)) analysis_res = json.loads(analysis) return jsonify({ 'status': 'complete', 'analysis': analysis, 'translatedText': translated_text, 'rawText': '\n'.join(txts) })


Yine bu oldukça tanıdık geliyor olmalı. İlk önce OCR'nin yapılıp yapılmadığını kontrol ederiz, eğer OCR yapılmadıysa grubun hala işlendiğini belirten bir mesaj göndeririz. OCR yapılırsa, OCR sonuçlarını indirerek ve çeviri ile ChatGPT hattını çalıştırarak analize devam ederiz. Gereksiz depolama maliyetlerine yol açmamak için analiz tamamlandıktan sonra kaynak dosyaları da temizlediğinizden emin oluruz. Sonucu, ChatGPT analizi JSON'unu, çevrilmiş metni ve OCR tarafından çıkarılan ham metni içeren nihai sonuç nesnesine paketliyoruz.


Özel soru arka ucu yeni bir özellik olsa da oldukça basittir. Öncelikle özel bir soru soracak fonksiyonu tanımlamak isteyeceğiz:


 def ask_chatgpt_question(report_text, question_text): completion = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=[ {"role": "user", "content": ''' Consider the following report: --- %s --- Answer the following question: %s ''' % (report_text, question_text)}, ] ) return completion.choices[0]['message']['content']


Artık işlevi içe aktarabilir ve API uç noktasını tanımlayabiliriz:


 @app.route('/ask_user_question') def ask_user_question(): report_text = request.json['text'] user_question = request.json['userQuestion'] response = ask_chatgpt_question(report_text, user_question) return jsonify({ 'result': response })


Artık API'mizi yazdığımıza göre, onu ön uçtan test edelim. Devam edin ve dosyayı ön uçtan yükleyin. Bunun gibi bir şey görmelisiniz:

Dosyayı yükledikten ve Analiz Et düğmesine bastıktan sonra


Biraz bekleyin ve sonucun WebApp'te göründüğünü görmelisiniz.

Temel sonuç

Etrafınıza bakın ve çevrilmiş metni de göreceksiniz:

Çevrilmiş metin

Ve ham kaynak metin:

Ham metin

Şimdi özel sorular arayüzünü test edelim:

Belge hakkında soru sormak

Bayağı güzel! Bununla birlikte yapay zeka araçlarımızın etrafında başarıyla bir React.js uygulaması geliştirdik!

Çözüm

Bugünkü makalemizde şu anda piyasada bulunan en güçlü yapay zeka araçlarından bazılarından yararlanan bir uygulama geliştirdik. Bu özel uygulama yabancı dildeki PDF'leri ayrıştırmaya ve özetlemeye yönelik olsa da, benzer teknikler birçok alanda güçlü, devrim niteliğinde uygulamalar geliştirmek için uyarlanabilir.


Umarım bu makale size kendi AI odaklı uygulamalarınızı yazmanız için ilham vermiştir. Bana ulaşıp yapay zeka uygulamalarına bakış açınız hakkında konuşmak isterseniz, sizden haber almak isterim. Benzer bir uygulama oluşturmak istiyorsanız, Ön Uç ve Arka Uç için depoları bulabileceğiniz Github sayfamda barındırılan koda başvurmaktan çekinmeyin.


Bu uygulamayı kendi başınıza oluşturmanıza gerek kalmadan kullanmak istiyorsanız, uygulamanın genel kullanıma yönelik daha gelişmiş bir sürümünü derleyip barındırdım. Bu uygulamaya erişmek istiyorsanız lütfen bizimle iletişime geçin; web sitesine erişim sağlayabiliriz.


Lütfen kendi Yüksek Lisans örneğimizi oluşturup çalıştıracağımız bir takip makalesi için tetikte olun. Yazı yayınlandığında yazının linkini burada yayınlayacağız. Bizi izlemeye devam edin!