Article by Rafał Rybnik, Dyrektor ds. rozwoju oprogramowania w Instytut Badań Pollster
Niezależnie od tego, czy jesteś pisarzem, naukowcem zajmującym się danymi, czy po prostu przeglądasz źródła, aby wykonać pracę, czytanie dłuższych tekstów, aby wyłuskać z nich okruchy informacji, może być dość wyczerpujące. Automatyzacja takich elementów pracy pozwala skupić się na kreatywnej stronie rzeczy.

Jeśli nie zaznaczono inaczej, wszystkie zdjęcia w artykule są autorstwa autora.
Streszczanie tekstu jest techniką wyodrębniania kluczowych elementów informacyjnych z obszernego tekstu. Ręczne streszczanie tekstu jest trudnym i czasochłonnym zadaniem, dlatego algorytmy przetwarzania języka naturalnego i uczenia maszynowego stały się popularne, aby je zautomatyzować.
Na rynku istnieją gotowe rozwiązania, czy to w postaci bibliotek, czy też gotowych narzędzi dla użytkowników końcowych.
W tym artykule przygotujemy własne, dopasowane rozwiązanie, które jednocześnie nie wymaga zaawansowanej wiedzy z zakresu data science.
NLP Cloud jest dostawcą wielu API do przetwarzania tekstów z wykorzystaniem modeli uczenia maszynowego. Jednym z nich jest streszczacz tekstu, który wygląda obiecująco pod względem prostej implementacji.
Streszczacz dostarczany przez NLP Cloud jest abstrakcyjny, co oznacza, że mogą być generowane nowe zdania, a fragmenty o niskim stosunku informacji do szumu są usuwane.
Zobaczmy przykład:

Przekazujemy blok tekstu, a model zwraca podsumowanie. Jednak operowanie w konsoli nie jest zbyt wygodne. Sprawmy więc, aby Google Docs podsumowywał wybrany fragment tekstu w ten sposób.
Naszym celem jest stworzenie wygodnego menu, dzięki któremu streszczanie tekstu będzie odbywało się automatycznie z poziomu Dokumentów Google.

Tak właśnie wygląda struktura naszego projektu. Za pomocą Apps Script rozszerzymy GUI o przycisk, który będzie uruchamiał funkcje komunikujące się z API NLP Cloud, a następnie wstawiał poniższy wynik.
Zaczniemy od przygotowania dodatku do menu.
Używanie skryptów Google Apps do dodawania niestandardowych funkcji do Dokumentów Google jest dość proste. Można dostosować interfejs użytkownika za pomocą nowych menu, okien dialogowych i pasków bocznych. Aby utworzyć skrypt, po otwarciu Dokumentów Google wybierz Narzędzia -> Edytor skryptów.
Wszystkie elementy interfejsu powinny zostać dodane w tej funkcji: onOpen. Jest on uruchamiany po otwarciu dokumentu i pozwala nam na dodanie menu.
function onOpen() {
var ui = DocumentApp.getUi();
ui.createMenu('Text Summarizer')
.addItem('Summarize selection', 'summarizeSelection')
.addToUi();
}
function summarizeSelection() {
// summarization function
}
Po zapisaniu skryptu i odświeżeniu Docs, powinieneś znaleźć nowy element menu "Text Summarizer".

Musimy uzyskać zaznaczony tekst, a następnie zaimplementować następującą funkcję: summarizeSelection.
Najtrudniejszą częścią jest uzyskanie aktualnie zaznaczonego tekstu i przekazanie go do funkcji. Jest to możliwe dzięki tej funkcji: getSelection.
DocumentApp.getActiveDocument().getSelection();
However, this function returns not only highlighted part of the documents, but a whole paragraph in which selections resides. That’s why we create more complex getSelectedText function:
function getSelectedText() {
var document = DocumentApp.getActiveDocument();
var body = document.getBody();
var text = "";
var selection = document.getSelection();
var parent = false;
var insertPoint
if (selection) {
var elements = selection.getRangeElements();
if(elements[0].isPartial()) {
text = elements[0].getElement().asText().getText();
text = text.substring(elements[0].getStartOffset(),elements[0].getEndOffsetInclusive()+1)
parent = elements[0].getElement().getParent();
} else {
text = elements.map( function(element) {
parent = element.getElement().getParent();
return element.getElement().asText().getText();
});
}
// Logger.log(text);
if (parent) {
insertPoint = body.getChildIndex(parent);
}
}
return [text, insertPoint];
}
Funkcja po prostu bierze cały akapit i przycina go tylko do wybranego fragmentu. Zwraca również indeks akapitu, abyś wiedział, gdzie wstawić podsumowanie.
Teraz wyślijmy tekst do API i sparsujmy wynik.
Użyjemy następującej usługi do bezpośredniego wykonywania żądań API: UrlFetch. Żądanie API podsumowania tekstu wymaga autoryzacji poprzez token. Aby go otrzymać, zarejestruj się na nlpcloud.com (darmowy plan wystarczy).
Żądane API zwraca surową odpowiedź JSON dla żądania.
Pamiętaj, że wszystkie teksty przetwarzane przez ten skrypt są wysyłane do zewnętrznego API.
function summarizeSelection() {
var document = DocumentApp.getActiveDocument();
var selectedText = getSelectedText();
var text = selectedText[0];
var insertPoint = selectedText[1];
if (text) {
DocumentApp.getUi().alert(text);
var url = 'https://api.nlpcloud.io/v1/bart-large-cnn/summarization';
var response = UrlFetchApp.fetch(
url,
{
'method': 'POST',
'contentType': 'application/json',
'headers':{
'Authorization': 'Token c714fb961e7f6ef1336ab7f501f4d842f2dc2380'
},
'payload': JSON.stringify({"text":text}),
'muteHttpExceptions': true
}
);
try {
summary_text = JSON.parse(response.getContentText())['summary_text'];
DocumentApp.getUi().alert(summary_text);
} catch (e) {
DocumentApp.getUi().alert('Something went wrong 🙁');
}
} else {
DocumentApp.getUi().alert('You must select some text!');
}
}
Aby przetestować funkcjonalność, wystarczy zaznaczyć fragment tekstu w Docs i wybrać z menu Docs polecenie Podsumowanie tekstu -> Podsumuj zaznaczenie.
Po chwili przetwarzania powinieneś zobaczyć pop-up z wynikiem, który możesz nawet skopiować.

Wreszcie, możemy wstawić podsumowanie wygenerowane przez API bezpośrednio do dokumentu. Dla łatwiejszego rozróżnienia, pogrubiamy tekst podsumowania. Dlatego też poniższa funkcja zwraca również indeks akapitu zaznaczonego tekstu: getSelectedText.
W ten sposób wiemy dokładnie, w którym miejscu Apps Script ma wstawić nowy tekst.
function summarizeSelection() {
var document = DocumentApp.getActiveDocument();
var selectedText = getSelectedText();
var text = selectedText[0];
var insertPoint = selectedText[1];
if (text) {
DocumentApp.getUi().alert(text);
var url = 'https://api.nlpcloud.io/v1/bart-large-cnn/summarization';
var response = UrlFetchApp.fetch(
url,
{
'method': 'POST',
'contentType': 'application/json',
'headers':{
'Authorization': 'Token c714fb961e7f6ef1336ab7f501f4d842f2dc2380'
},
'payload': JSON.stringify({"text":text}),
'muteHttpExceptions': true
}
);
try {
summary_text = JSON.parse(response.getContentText())['summary_text'];
DocumentApp.getUi().alert(summary_text);
} catch (e) {
DocumentApp.getUi().alert('Something went wrong 🙁');
}
//////////////
var body = document.getBody();
var summaryParagraph = body.insertParagraph(insertPoint+1, summary_text);
summaryParagraph.setBold(true);
//////////////
} else {
DocumentApp.getUi().alert('You must select some text!');
}
}
Przetestujmy ostateczną wersję:
Zbudowanie aplikacji rozszerzającej funkcjonalność Google Docs w oparciu o zewnętrzne API jest ciekawą alternatywą dla budowania dużych systemów automatyzujących niewygodne etapy pracy. Co więcej, poszczególne komponenty mogą być wymieniane w zależności od potrzeb i konkretnych umiejętności. Przykładowo, nasze rozwiązanie można rozszerzyć o wykrywanie emocji czy klasyfikację tekstu (dostępne również w NLP Cloud). Istnieje również możliwość przygotowania własnego API lub prostych funkcji bezpośrednio w Apps Script.

Dziękuję za przeczytanie. Mam nadzieję, że czytanie sprawiło Ci tyle samo przyjemności, co mi pisanie tego dla Ciebie.