Этот репозиторий создает тонкую оболочку Python вокруг OpenCCG с использованием онтологии GUM-пространства, готовую к запуску внутри Docker-контейнера. Вы можете найти действующую версию по адресуlitmus.informatik.uni-bremen.de/openccg.
После первоначального docker-compose up
сервис можно запросить с помощью простого запроса POST, например, с помощью Curl:
$ curl --data "Take the cup." "localhost/openccg/parse?graphs"
{"version": "2.2.0", "application": "web-openccg", "uuid": "3bafdaf8-cc9c-4fdf-b455-c9687babba49", "sentence": "take the cup", "parses": ..., "http_status": 200, "json_parses": ..., "graphs": ...}
Поле «графики» включается только в том случае, если присутствует URL-параметр graphs
».
В качестве примера использования запросов Python:
import requests
# Without graphs
print ( requests . post ( 'http://localhost/openccg/parse' , data = { 'sentence' : 'Take the cup.' }). json ())
# With graphs
print ( requests . post ( 'http://localhost/openccg/parse' ,
data = { 'sentence' : 'Take the cup.' },
params = { 'graphs' : True }). json ())
Из-за того, что мы размещаем OpenCCG за nginx в компании Lacmus, все URL-адреса web-openccg имеют префикс «openccg». Однако для двух важных конечных точек ( /
для графического интерфейса и /parse
для API) существуют перенаправления. Для Curl это означает curl -L --data "Take the cup." localhost/parse
также будет работать (обратите внимание на аргумент -L
( --location
)).
Обратите внимание, что он не готов к работе, поскольку он очень медленный и неоптимизирован: вместо того, чтобы поддерживать один (или несколько) экземпляров OpenCCG в рабочем состоянии для более быстрого выполнения запросов, каждый запрос порождает отдельный экземпляр OpenCCG.
Чтобы запросить службу визуально, просто откройте браузер по адресу http://localhost/openccg. В противном случае используйте запросы curl, wget или, например, Python для запроса web-openccg через командную строку или ваше приложение.
Если ваш клиент позволяет вручную создавать тело запроса, например, Curl, просто поместите внутрь предложение:
curl --data "Take the cup." localhost/openccg/parse
Однако многие фреймворки высокого уровня, такие как запросы Python, обычно используют механизм «ключ-значение» для почтовых данных. В этом случае используйте ключевое sentence
:
requests.post('http://localhost/openccg/parse', data={'sentence': 'Take the cup.'})
Пример см. ниже.
Ответ представляет собой объект JSON и всегда содержит следующие поля:
version
: версия объекта JSON.application
: Всегда «web-openccg», это полезно, если вы объединяете анализы из разных сервисов.uuid
: уникальный идентификатор этого ответа. Это будет полезно только в том случае, если вы планируете каким-либо образом интегрировать этот инструмент.http_status
: HTTP-статус запроса.Если во время запроса было предоставлено предложение, присутствуют следующие поля:
sentence
: Очищенное входное предложение (все строчные буквы, пунктуация удалена, ...).Если существует хотя бы один успешный анализ, включаются следующие поля:
parses
: словарь идентификаторов синтаксического анализа (например, «np») для фактических анализов, выдаваемых OpenCCG.json_parses
: версия выходных данных OpenCCG в плоском формате JSON. Это создается с помощью специальной грамматики для TatSu. Подробности см. ниже. Каждое отдельное значение словаря представляет собой список номиналов, переменных и/или ролей.graphs
: словарь идентификаторов синтаксического анализа для строк с точками. Их можно визуализировать с помощью Graphviz — графический интерфейс пользователя отображает их автоматически. Примечание. Ключи являются общими для parses
, json_parses
и graphs
, поэтому вы можете легко найти исходный результат анализа JSON и наоборот.
При возникновении ошибки поле ошибки присутствует:
error
: Описание ошибки.Текущая версия: 2.3.0
Формат JSON для анализа OpenCCG можно определить на основе приведенного выше примера или путем тщательной проверки полностью типизированного файла OpenCCG.ebnf.
Существует три различных типа объектов: номинальный, переменный и роль. Полная семантическая спецификация (файл JSON) может представлять собой либо один объект любого из трех типов, либо список номиналов. Если мы найдем анализы, представляющие собой списки переменных или ролей, грамматика будет расширена. Пожалуйста, откройте проблему, если вы обнаружите предложения, которые невозможно правильно проанализировать.
Номинал – это как особая переменная, он описывает «главную тему» предложения. Поскольку они практически одинаковы (на самом деле у них очень похожие правила синтаксического анализа), формат JSON представляет их с идентичной структурой:
{
"__class__" : " Variable " ,
"name" : " x1 " ,
"type" : " gum-OrientationChange " ,
"roles" : []
}
__class__
— это либо Variable
, либо Nominal
.name
— это переменная с именем, используемая OpenCCG. Это буква, за которой следует число, например x1
или w12
.type
— спецификатор GUM, обозначающий тип переменной. Оно также может быть null
, если тип не указан.roles
— это список ролей, как описано ниже. Роль определяет все свойства, которые может иметь переменная или номинал. Он имеет очень похожую структуру:
{
"__class__" : " Role " ,
"type" : " quant " ,
"target" : ...
}
__class__
: Role
.type
: Тип роли. Это определяет target
возможности.target
: значение роли. Это может быть несколько разных вещей, см. ниже. Если тип entity
, целью будет экземпляр, например «cup» или «slm-Taking». Если тип имеет префикс, за которым следует тире, например gs-hasSpatialModality
или gs-direction
, то целью будет Variable
; в сове это будет ObjectProperty. Если типом является любая другая строка, целью будет атомарная строка, например, тип det
может иметь цель the
, а тип quant
может иметь цель singular
.
Большинство веб-сервисов используют порт 80 в качестве порта по умолчанию, как и web-openccg.
Чтобы изменить порт, настройте файл docker-compose и измените строку порта с "80:80"
на ваш порт слева (но оставьте 80 справа), например, чтобы настроить службу на порту 9043. , вы бы изменили его на "9043:80"
.
Прежде чем начать разработку, вам необходимо собрать Docker-контейнер, используя:
make build
Этот шаг также включает в себя некоторые файлы, загруженные в процессе сборки в ваш локальный каталог ./webopenccg/static. Копии выполняются, потому что сервер разработки монтирует каталог, который перезаписывает файлы, доступные только внутри контейнера, но не в хост-системе.
Чтобы запустить Docker-контейнер разработки, используйте Makefile:
make run
Сервер разработки привязывается к порту 5000 и использует среду отладки flask. Кроме того, Docker-контейнер, запущенный с помощью make run
привязывает каталог приложения, чтобы перезагрузка flask работала правильно.
Чтобы скомпилировать грамматику OpenCCG.ebnf, запустите:
make
Пример ответа на предложение «Возьми чашку». является:
{
"version" : " 2.2.0 " ,
"application" : " web-openccg " ,
"uuid" : " ecae8222-af9b-4185-a508-efa8be33c7e6 " ,
"sentence" : " take the cup " ,
"parses" : {
"smain" : " @x1:gum-OrientationChange( <mood>imp ^ <gs-direction>(x2:gs-GeneralizedLocation ^ <gs-hasSpatialModality>(w2:slm-Cup ^ cup ^ <det>the ^ <ident>specific ^ <quant>singular)) ^ <gum-processInConfiguration>(w0:slm-Moving ^ slm-Taking)) " ,
"smain/0" : " @x1:gum-OrientationChange( <mood>imp ^ <gs-direction>(x2:gs-GeneralizedLocation ^ <gs-hasSpatialModality>(w2:slm-Cup ^ cup ^ <det>the ^ <ident>specific ^ <quant>singular)) ^ <gum-processInConfiguration>(w0:slm-Taking ^ slm-Taking)) " ,
"smain/.r" : " @x1:gs-AffectingDirectedMotion( <mood>imperative ^ <gs-route>x2 ^ <gum-actee>(w2:slm-Cup ^ cup ^ <det>the ^ <ident>specific ^ <quant>singular) ^ <gum-processInConfiguration>(w0:slm-Moving ^ slm-Taking)) " ,
"smain/.r/0" : " @x1:gs-AffectingDirectedMotion( <mood>imperative ^ <gs-route>x2 ^ <gum-actee>(w2:slm-Cup ^ cup ^ <det>the ^ <ident>specific ^ <quant>singular) ^ <gum-processInConfiguration>(w0:slm-Taking ^ slm-Taking)) "
},
"http_status" : 200 ,
"json_parses" : {
"smain" : {
"__class__" : " Nominal " ,
"type" : " gum-OrientationChange " ,
"name" : " x1 " ,
"roles" : [
{
"__class__" : " Role " ,
"type" : " mood " ,
"target" : " imp "
},
{
"__class__" : " Role " ,
"type" : " gs-direction " ,
"target" : {
"__class__" : " Variable " ,
"type" : " gs-GeneralizedLocation " ,
"name" : " x2 " ,
"roles" : [
{
"__class__" : " Role " ,
"type" : " gs-hasSpatialModality " ,
"target" : {
"__class__" : " Variable " ,
"type" : " slm-Cup " ,
"name" : " w2 " ,
"roles" : [
{
"__class__" : " Role " ,
"type" : " entity " ,
"target" : " cup "
},
{
"__class__" : " Role " ,
"type" : " det " ,
"target" : " the "
},
{
"__class__" : " Role " ,
"type" : " ident " ,
"target" : " specific "
},
{
"__class__" : " Role " ,
"type" : " quant " ,
"target" : " singular "
}
]
}
}
]
}
},
{
"__class__" : " Role " ,
"type" : " gum-processInConfiguration " ,
"target" : {
"__class__" : " Variable " ,
"type" : " slm-Moving " ,
"name" : " w0 " ,
"roles" : [
{
"__class__" : " Role " ,
"type" : " entity " ,
"target" : " slm-Taking "
}
]
}
}
]
},
"smain/0" : {
"__class__" : " Nominal " ,
"type" : " gum-OrientationChange " ,
"name" : " x1 " ,
"roles" : [
{
"__class__" : " Role " ,
"type" : " mood " ,
"target" : " imp "
},
{
"__class__" : " Role " ,
"type" : " gs-direction " ,
"target" : {
"__class__" : " Variable " ,
"type" : " gs-GeneralizedLocation " ,
"name" : " x2 " ,
"roles" : [
{
"__class__" : " Role " ,
"type" : " gs-hasSpatialModality " ,
"target" : {
"__class__" : " Variable " ,
"type" : " slm-Cup " ,
"name" : " w2 " ,
"roles" : [
{
"__class__" : " Role " ,
"type" : " entity " ,
"target" : " cup "
},
{
"__class__" : " Role " ,
"type" : " det " ,
"target" : " the "
},
{
"__class__" : " Role " ,
"type" : " ident " ,
"target" : " specific "
},
{
"__class__" : " Role " ,
"type" : " quant " ,
"target" : " singular "
}
]
}
}
]
}
},
{
"__class__" : " Role " ,
"type" : " gum-processInConfiguration " ,
"target" : {
"__class__" : " Variable " ,
"type" : " slm-Taking " ,
"name" : " w0 " ,
"roles" : [
{
"__class__" : " Role " ,
"type" : " entity " ,
"target" : " slm-Taking "
}
]
}
}
]
},
"smain/.r" : {
"__class__" : " Nominal " ,
"type" : " gs-AffectingDirectedMotion " ,
"name" : " x1 " ,
"roles" : [
{
"__class__" : " Role " ,
"type" : " mood " ,
"target" : " imperative "
},
{
"__class__" : " Role " ,
"type" : " gs-route " ,
"target" : {
"__class__" : " Variable " ,
"type" : null ,
"name" : " x2 " ,
"roles" : [
{
"__class__" : " Role " ,
"type" : " gum-actee " ,
"target" : {
"__class__" : " Variable " ,
"type" : " slm-Cup " ,
"name" : " w2 " ,
"roles" : [
{
"__class__" : " Role " ,
"type" : " entity " ,
"target" : " cup "
},
{
"__class__" : " Role " ,
"type" : " det " ,
"target" : " the "
},
{
"__class__" : " Role " ,
"type" : " ident " ,
"target" : " specific "
},
{
"__class__" : " Role " ,
"type" : " quant " ,
"target" : " singular "
}
]
}
},
{
"__class__" : " Role " ,
"type" : " gum-processInConfiguration " ,
"target" : {
"__class__" : " Variable " ,
"type" : " slm-Moving " ,
"name" : " w0 " ,
"roles" : [
{
"__class__" : " Role " ,
"type" : " entity " ,
"target" : " slm-Taking "
}
]
}
}
]
}
}
]
},
"smain/.r/0" : {
"__class__" : " Nominal " ,
"type" : " gs-AffectingDirectedMotion " ,
"name" : " x1 " ,
"roles" : [
{
"__class__" : " Role " ,
"type" : " mood " ,
"target" : " imperative "
},
{
"__class__" : " Role " ,
"type" : " gs-route " ,
"target" : {
"__class__" : " Variable " ,
"type" : null ,
"name" : " x2 " ,
"roles" : [
{
"__class__" : " Role " ,
"type" : " gum-actee " ,
"target" : {
"__class__" : " Variable " ,
"type" : " slm-Cup " ,
"name" : " w2 " ,
"roles" : [
{
"__class__" : " Role " ,
"type" : " entity " ,
"target" : " cup "
},
{
"__class__" : " Role " ,
"type" : " det " ,
"target" : " the "
},
{
"__class__" : " Role " ,
"type" : " ident " ,
"target" : " specific "
},
{
"__class__" : " Role " ,
"type" : " quant " ,
"target" : " singular "
}
]
}
},
{
"__class__" : " Role " ,
"type" : " gum-processInConfiguration " ,
"target" : {
"__class__" : " Variable " ,
"type" : " slm-Taking " ,
"name" : " w0 " ,
"roles" : [
{
"__class__" : " Role " ,
"type" : " entity " ,
"target" : " slm-Taking "
}
]
}
}
]
}
}
]
}
},
"graphs" : {
"smain": "strict graph "" {ntnode [label="\N"];ntsubgraph cluster_x1 {nttgraph [fillcolor=lightskyblue,ntttlabel="x1: gum-OrientationChange",ntttstyle=filledntt];nttsubgraph "cluster_gs-direction" {ntttgraph [fillcolor=honeydew,nttttlabel="gs-direction",nttttstyle=fillednttt];ntttsubgraph cluster_x2 {nttttgraph [fillcolor=lightblue,ntttttlabel="x2: gs-GeneralizedLocation",ntttttstyle=filledntttt];nttttsubgraph "cluster_gs-hasSpatialModality" {ntttttgraph [fillcolor=honeydew,nttttttlabel="gs-hasSpatialModality",nttttttstyle=fillednttttt];ntttttsubgraph cluster_w2 {nttttttgraph [fillcolor=lightblue,ntttttttlabel="w2: slm-Cup",ntttttttstyle=filledntttttt];nttttttw2tttttt [fillcolor=aliceblue,ntttttttlabel="{<entity> cup|<det> the|<ident> specific|<quant> singular}",ntttttttshape=Mrecord,ntttttttstyle=filled];nttttt}ntttt}nttt}ntt}nttsubgraph "cluster_gum-processInConfiguration" {ntttgraph [fillcolor=honeydew,nttttlabel="gum-processInConfiguration",nttttstyle=fillednttt];ntttsubgraph cluster_w0 {nttttgraph [fillcolor=lightblue,ntttttlabel="w0: slm-Moving",ntttttstyle=filledntttt];nttttw0tttt [fillcolor=aliceblue,ntttttlabel="{<entity> slm-Taking}",ntttttshape=Mrecord,ntttttstyle=filled];nttt}ntt}nttx1tt [fillcolor=aliceblue,ntttlabel="{<mood> imp}",ntttshape=Mrecord,ntttstyle=filled];nt}n}n",
"smain/0": "strict graph "" {ntnode [label="\N"];ntsubgraph cluster_x1 {nttgraph [fillcolor=lightskyblue,ntttlabel="x1: gum-OrientationChange",ntttstyle=filledntt];nttsubgraph "cluster_gs-direction" {ntttgraph [fillcolor=honeydew,nttttlabel="gs-direction",nttttstyle=fillednttt];ntttsubgraph cluster_x2 {nttttgraph [fillcolor=lightblue,ntttttlabel="x2: gs-GeneralizedLocation",ntttttstyle=filledntttt];nttttsubgraph "cluster_gs-hasSpatialModality" {ntttttgraph [fillcolor=honeydew,nttttttlabel="gs-hasSpatialModality",nttttttstyle=fillednttttt];ntttttsubgraph cluster_w2 {nttttttgraph [fillcolor=lightblue,ntttttttlabel="w2: slm-Cup",ntttttttstyle=filledntttttt];nttttttw2tttttt [fillcolor=aliceblue,ntttttttlabel="{<entity> cup|<det> the|<ident> specific|<quant> singular}",ntttttttshape=Mrecord,ntttttttstyle=filled];nttttt}ntttt}nttt}ntt}nttsubgraph "cluster_gum-processInConfiguration" {ntttgraph [fillcolor=honeydew,nttttlabel="gum-processInConfiguration",nttttstyle=fillednttt];ntttsubgraph cluster_w0 {nttttgraph [fillcolor=lightblue,ntttttlabel="w0: slm-Taking",ntttttstyle=filledntttt];nttttw0tttt [fillcolor=aliceblue,ntttttlabel="{<entity> slm-Taking}",ntttttshape=Mrecord,ntttttstyle=filled];nttt}ntt}nttx1tt [fillcolor=aliceblue,ntttlabel="{<mood> imp}",ntttshape=Mrecord,ntttstyle=filled];nt}n}n",
"smain/.r": "strict graph "" {ntnode [label="\N"];ntsubgraph cluster_x1 {nttgraph [fillcolor=lightskyblue,ntttlabel="x1: gs-AffectingDirectedMotion",ntttstyle=filledntt];nttsubgraph "cluster_gs-route" {ntttgraph [fillcolor=honeydew,nttttlabel="gs-route",nttttstyle=fillednttt];ntttsubgraph cluster_x2 {nttttgraph [fillcolor=lightblue,ntttttlabel=None,ntttttstyle=filledntttt];nttttsubgraph "cluster_gum-actee" {ntttttgraph [fillcolor=honeydew,nttttttlabel="gum-actee",nttttttstyle=fillednttttt];ntttttsubgraph cluster_w2 {nttttttgraph [fillcolor=lightblue,ntttttttlabel="w2: slm-Cup",ntttttttstyle=filledntttttt];nttttttw2tttttt [fillcolor=aliceblue,ntttttttlabel="{<entity> cup|<det> the|<ident> specific|<quant> singular}",ntttttttshape=Mrecord,ntttttttstyle=filled];nttttt}ntttt}nttttsubgraph "cluster_gum-processInConfiguration" {ntttttgraph [fillcolor=honeydew,nttttttlabel="gum-processInConfiguration",nttttttstyle=fillednttttt];ntttttsubgraph cluster_w0 {nttttttgraph [fillcolor=lightblue,ntttttttlabel="w0: slm-Moving",ntttttttstyle=filledntttttt];nttttttw0tttttt [fillcolor=aliceblue,ntttttttlabel="{<entity> slm-Taking}",ntttttttshape=Mrecord,ntttttttstyle=filled];nttttt}ntttt}nttt}ntt}nttx1tt [fillcolor=aliceblue,ntttlabel="{<mood> imperative}",ntttshape=Mrecord,ntttstyle=filled];nt}n}n",
"smain/.r/0": "strict graph "" {ntnode [label="\N"];ntsubgraph cluster_x1 {nttgraph [fillcolor=lightskyblue,ntttlabel="x1: gs-AffectingDirectedMotion",ntttstyle=filledntt];nttsubgraph "cluster_gs-route" {ntttgraph [fillcolor=honeydew,nttttlabel="gs-route",nttttstyle=fillednttt];ntttsubgraph cluster_x2 {nttttgraph [fillcolor=lightblue,ntttttlabel=None,ntttttstyle=filledntttt];nttttsubgraph "cluster_gum-actee" {ntttttgraph [fillcolor=honeydew,nttttttlabel="gum-actee",nttttttstyle=fillednttttt];ntttttsubgraph cluster_w2 {nttttttgraph [fillcolor=lightblue,ntttttttlabel="w2: slm-Cup",ntttttttstyle=filledntttttt];nttttttw2tttttt [fillcolor=aliceblue,ntttttttlabel="{<entity> cup|<det> the|<ident> specific|<quant> singular}",ntttttttshape=Mrecord,ntttttttstyle=filled];nttttt}ntttt}nttttsubgraph "cluster_gum-processInConfiguration" {ntttttgraph [fillcolor=honeydew,nttttttlabel="gum-processInConfiguration",nttttttstyle=fillednttttt];ntttttsubgraph cluster_w0 {nttttttgraph [fillcolor=lightblue,ntttttttlabel="w0: slm-Taking",ntttttttstyle=filledntttttt];nttttttw0tttttt [fillcolor=aliceblue,ntttttttlabel="{<entity> slm-Taking}",ntttttttshape=Mrecord,ntttttttstyle=filled];nttttt}ntttt}nttt}ntt}nttx1tt [fillcolor=aliceblue,ntttlabel="{<mood> imperative}",ntttshape=Mrecord,ntttstyle=filled];nt}n}n"
}
}
Пример визуализации (показан только smain):