Este repositorio crea un contenedor delgado de Python alrededor de OpenCCG utilizando la ontología del espacio GUM, listo para ejecutarse dentro de un contenedor acoplable. Puede encontrar una versión en vivo en litmus.informatik.uni-bremen.de/openccg.
Después de una docker-compose up
inicial, el servicio se puede consultar mediante una solicitud POST simple, por ejemplo, usando 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": ...}
El campo "gráficos" solo se incluye si el parámetro URL graphs
está presente.
Como ejemplo, usando solicitudes de 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 ())
Debido a la forma en que alojamos OpenCCG detrás de nginx en litmus, todas las URL para web-openccg tienen el prefijo "openccg". Sin embargo, para los dos puntos finales importantes ( /
para la GUI y /parse
para la API), existen redirecciones. Para curl esto significa curl -L --data "Take the cup." localhost/parse
también funcionará (tenga en cuenta el argumento -L
( --location
)).
Tenga en cuenta que no está listo para producción, ya que es muy lento y no está optimizado: en lugar de mantener una (o varias) instancias de OpenCCG en ejecución para consultarlas más rápido, cada solicitud genera una instancia individual de OpenCCG.
Para consultar el servicio visualmente, simplemente abra su navegador en http://localhost/openccg. De lo contrario, utilice solicitudes curl, wget o, por ejemplo, python para consultar web-openccg a través de la línea de comandos o su aplicación.
Si su cliente le permite crear el cuerpo de su solicitud manualmente, como curl, simplemente coloque la oración dentro:
curl --data "Take the cup." localhost/openccg/parse
Sin embargo, muchos marcos de alto nivel, como las solicitudes de Python, suelen utilizar un mecanismo de valor clave para los datos de publicación. En este caso, utilice la sentence
clave:
requests.post('http://localhost/openccg/parse', data={'sentence': 'Take the cup.'})
Para ver un ejemplo, consulte a continuación.
La respuesta es un objeto JSON y siempre contiene estos campos:
version
: La versión del objeto JSON.application
: Siempre "web-openccg", esto es útil si agrega análisis de diferentes servicios.uuid
: ID único para esta respuesta. Esto sólo será útil si planeas integrar la herramienta de alguna manera.http_status
: el estado HTTP de la solicitud.Si se proporcionó una oración durante la solicitud, estos campos están presentes:
sentence
: La frase de entrada limpia (toda en minúsculas, puntuación eliminada, ...).Si existe al menos un análisis exitoso, se incluyen estos campos:
parses
: un diccionario de identificadores de análisis (por ejemplo, "np") para análisis reales a medida que OpenCCG los genera.json_parses
: una versión de las salidas de OpenCCG en un JSON plano. Esto se produce mediante una gramática personalizada para TatSu. Para obtener más información, consulte a continuación. Cada valor individual del diccionario es una lista de Nominales, Variables y/o Roles.graphs
: un diccionario de identificadores de análisis de cadenas de puntos. Se pueden representar usando Graphviz: la GUI en línea los representa automáticamente. Nota: Las claves se comparten entre parses
, json_parses
y graphs
, por lo que puede buscar fácilmente la salida original de un análisis JSON y viceversa.
Si se produce un error, el campo de error está presente:
error
: una descripción del error.Versión actual: 2.3.0
El formato JSON para los análisis de OpenCCG se puede determinar a partir del ejemplo anterior o inspeccionando cuidadosamente el OpenCCG.ebnf completamente escrito.
Hay tres tipos diferentes de objetos: Nominal, Variable y Rol. La especificación semántica completa (el archivo JSON) puede ser una única entidad de cualquiera de los tres tipos o una lista de Nominales. Si encontramos análisis que son listas de variables o roles, la gramática se ampliará. Abra un problema si encuentra oraciones que no se pueden analizar correctamente.
Un nominal es como una variable especial, describe el "tema principal" de la oración. Como son prácticamente iguales (en realidad tienen reglas de análisis muy similares), el formato JSON los representa con una estructura idéntica:
{
"__class__" : " Variable " ,
"name" : " x1 " ,
"type" : " gum-OrientationChange " ,
"roles" : []
}
__class__
es Variable
o Nominal
.name
es la variable nombrada utilizada por OpenCCG, es una letra seguida de un número, por ejemplo x1
o w12
.type
es un especificador GUM que denota el tipo de variable. También puede ser null
, si no se especifica el tipo.roles
es una lista de roles como se describe a continuación. Un Rol define todas las propiedades que puede tener una Variable o Nominal. Sigue una estructura muy similar:
{
"__class__" : " Role " ,
"type" : " quant " ,
"target" : ...
}
__class__
: Role
.type
: El tipo de rol. Esto determina las posibilidades target
.target
: El valor del rol. Esto puede ser varias cosas diferentes, ver más abajo. Si el tipo es entity
, el objetivo será una instancia, como "cup" o "slm-Taking". Si el tipo tiene un prefijo seguido de un guión, por ejemplo, gs-hasSpatialModality
o gs-direction
, entonces el objetivo será una Variable
; en búho, esto sería una propiedad de objeto. Si el tipo es cualquier otra cadena, el objetivo será una cadena atómica, por ejemplo, el tipo det
puede tener el objetivo the
, mientras que el tipo quant
puede tener el objetivo singular
.
La mayoría de los servicios web utilizan el puerto 80 como puerto predeterminado, al igual que web-openccg.
Para cambiar el puerto, ajuste el archivo docker-compose y cambie la línea del puerto de "80:80"
a su puerto en el lado izquierdo (pero mantenga el 80 a la derecha), por ejemplo, para configurar el servicio en el puerto 9043. , lo cambiarías a "9043:80"
.
Antes de comenzar el desarrollo, debe crear el contenedor acoplable usando:
make build
Este paso también incluye algunos archivos descargados durante el proceso de compilación en su directorio local ./webopenccg/static. Las copias se realizan porque el servidor de desarrollo monta el directorio, lo que sobrescribe los archivos que sólo están disponibles dentro del contenedor pero no en el sistema host.
Para iniciar el contenedor acoplable de desarrollo, utilice el Makefile:
make run
El servidor de desarrollo se vincula al puerto 5000 y utiliza el entorno de depuración del matraz. Además, el contenedor acoplable iniciado con make run
vincula el directorio de la aplicación para que la recarga de flask funcione correctamente.
Para compilar la gramática OpenCCG.ebnf, ejecute:
make
Un ejemplo de respuesta para la oración "Toma la taza". es:
{
"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"
}
}
Visualización de ejemplo (solo se muestra lo principal):