Commit 1598586a authored by Cha DaEun's avatar Cha DaEun

update demo

parent a8d217f5
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PublishConfigData">
<serverData>
<paths name="chadaeun57@nlplab.iptime.org:32222">
<serverdata>
<mappings>
<mapping deploy="/home/chadaeun57/kr_stack_pointer_demo/kr_stack_ointer_server/demo_server_cgi" local="$PROJECT_DIR$/demo/demo_server_cgi" web="/" />
</mappings>
</serverdata>
</paths>
</serverData>
</component>
</project>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredPackages">
<value>
<list size="1">
<item index="0" class="java.lang.String" itemvalue="Werkzeug" />
</list>
</value>
</option>
</inspection_tool>
</profile>
</component>
\ No newline at end of file
"""
Author: Sam Thomson (sthomson@cs.cmu.edu)
Lingpeng Kong (lingpenk@cs.cmu.edu)
"""
import json
from subprocess import Popen, PIPE
import sys
import os
from threading import Lock
from settings import KR_STACK_POINTER_HOME, TEST, KR_STACK_POINTER_LIB, KR_STACK_POINTER_MODEL_PATH
from utils import timer
NUM_CONLL_FIELDS = 4
class KrStackPointerClient(object): # TODO writing and testing
"""
A client for retrieving dependency parses from a Korean Stack Pointer server
"""
def __init__(self):
self._lock = Lock()
python_path = os.environ.get('PYTHONPATH', '')
if KR_STACK_POINTER_LIB not in python_path:
os.environ['PYTHONPATH'] = python_path + ':' + ':'.join(KR_STACK_POINTER_LIB)
# start up parser
self._parser = Popen(['python',
'%s/server.py' % KR_STACK_POINTER_HOME,
'--model_path=%s' % KR_STACK_POINTER_MODEL_PATH,
'--cwd=%s' % KR_STACK_POINTER_HOME],
stdin=PIPE,
stdout=PIPE)
def get_parses(self, sentences):
"""
Gets frame-semantic parses as a list of dicts from a list of sentence
strings.
"""
with timer() as dep_timer:
sentences = self.get_dep_parses(sentences)
return {
"sentences": sentences,
"debug_info": {
"dependency_parser_elapsed_seconds": dep_timer['seconds'],
},
}
def get_dep_parses(self, sentences):
""" Gets dependency parses as conll from a list of sentences. """
sys.stderr.write("running Korean Stack Pointer Network...\n")
results = []
for sentence in sentences:
if sentence.strip():
results.append(self._request_one_sentence(sentence))
sys.stderr.write("parsing done.\n")
return results
def _request_one_sentence(self, sentence):
"""
Gets one dependency parse as conll from a pos tagged conll sentence.
"""
# one thread at a time, so stdin/out don't get mangled
with self._lock:
self._parser.stdin.write(sentence.strip().encode('utf8') + '\n')
self._parser.stdin.flush()
line = self._parser.stdout.readline()
while not line.strip():
line = self._parser.stdout.readline()
# Turbo only returns the first 8 columns, so add back cols 9-10
result_str = line.strip().decode('utf8')
result_json = json.loads(result_str)
if TEST:
self._test_json_format(result_json)
if self._parser.poll() is not None:
self._parser = Popen(['python',
'%s/server.py' % KR_STACK_POINTER_HOME,
'--model_path=%s' % KR_STACK_POINTER_MODEL_PATH,
'--cwd=%s' % KR_STACK_POINTER_HOME],
stdin=PIPE,
stdout=PIPE)
return result_json
def _test_json_format(self, result_json):
# test codes
assert set(result_json.keys()) == {'conll', 'entities', 'frames', 'relations', 'text', 'tokens',
'sentence_offsets', 'token_offsets'}
# conll (sejong for here)
assert isinstance(result_json['conll'], unicode), type(result_json['conll'])
for conll_line in result_json['conll'].splitlines():
if conll_line.strip():
assert len(conll_line.split('\t')) == NUM_CONLL_FIELDS
# entities
assert isinstance(result_json['entities'], list)
for entity in result_json['entities']:
assert isinstance(entity, list)
assert isinstance(entity[0], unicode)
assert isinstance(entity[1], unicode)
assert isinstance(entity[2], list)
assert len(entity[2]) == 1
assert isinstance(entity[2][0], list)
assert len(entity[2][0]) == 2
assert isinstance(entity[2][0][0], int)
assert isinstance(entity[2][0][1], int)
# relations
assert isinstance(result_json['relations'], list)
for entity in result_json['relations']:
assert isinstance(entity, list)
assert isinstance(entity[0], unicode)
assert isinstance(entity[1], unicode)
assert isinstance(entity[2], list)
assert len(entity[2]) == 2
assert isinstance(entity[2][0], list)
assert len(entity[2][0]) == 2
assert isinstance(entity[2][0][0], unicode)
assert entity[2][0][0] == 'Arg1'
assert isinstance(entity[2][0][1], unicode)
assert isinstance(entity[2][1][0], unicode)
assert entity[2][1][0] == 'Arg2'
assert isinstance(entity[2][1][1], unicode)
# text
assert isinstance(result_json['text'], unicode)
# tokens
assert isinstance(result_json['tokens'], list)
for token in result_json['tokens']:
assert isinstance(token, unicode)
# sentence_offsets
assert result_json['sentence_offsets'] == [0, len(result_json['text'])]
# token_offsets
assert isinstance(result_json['token_offsets'], list)
for offset in result_json['token_offsets']:
assert isinstance(offset, list)
assert len(offset) == 2
\ No newline at end of file
# Demo server settings
HOST = '0.0.0.0'
PORT = 5000
# Parser settings
KR_STACK_POINTER_HOME = '../parser_server'
KR_STACK_POINTER_LIB = ['../../lib', 'NEURO_NLP_PATH']
KR_STACK_POINTER_MODEL_PATH = 'MODEL_PATH'
# Test
TEST = True
\ No newline at end of file
###
SemViz
A visualizer for Semafor parses
Requires jQuery, mustache
Author: Sam Thomson (sthomson@cs.cmu.edu)
###
# Mustache template for the frame visualization table
FRAME_TABLE_TEMPLATE = """
<table id=frame_table>
<tr>
<thead>
<th></th>
{{#targetHeaders}}
<th class="target">
<a href={{getUrl}}>{{label}}</a>
</th>
{{/targetHeaders}}
</thead>
</tr>
{{#rows}}
<tr id="token_{{token.idx}}">
<th>{{token.label}}</th>
{{#frames}}
<td rowspan={{spanLength}}
{{#isFrameElement}}
class="annotation frame_element"
{{/isFrameElement}}
{{#isTarget}}
class="annotation target"
{{/isTarget}}
>
{{label}}
</td>
{{/frames}}
</tr>
{{/rows}}
</table>
"""
# link to the docs for a frame
FRAMENET_FRAME_URL_TEMPLATE = 'https://framenet2.icsi.berkeley.edu/fnReports/data/frame/{{name}}.xml'
# url of api endpoint to parse a sentence
PARSE_URL = document.location.protocol + "//" + document.location.host + "/api/v1/parse"
# PARSE_URL = document.location.protocol + "//" + document.location.host + document.location.pathname + "/api/v1/parse"
# the input textarea inwhich the user types the sentence to parse
INPUT_BOX_SELECTOR = "textarea[name=sentence]"
# the div in which to put the rendered html table representing the frame-semantic parse
DEPENDENCY_CONTAINER_SELECTOR = '#dependency_parse'
DEPENDENCY_DISPLAY_ID = 'brat_parse'
DEPENDENCY_FORMAT_DISPLAY_ID = '#conll_parse'
# the div in which to put the rendered html table representing the frame-semantic parse
FRAME_CONTAINER_SELECTOR = '#frame_semantic_parse'
FRAME_DISPLAY_SELECTOR = '#parse_table'
SPINNER_SELECTOR = "#spinner"
# Different types of cells in the table
class Cell
constructor: (@label = '', @spanLength = 1) ->
class Header extends Cell
constructor: (label, @idx) ->
super(label = label)
class AnnotationCell extends Cell
constructor: (span, @frameId) ->
super(label = span.name, spanLength = span.end - span.start)
@spanStart = span.start
class TargetCell extends AnnotationCell
constructor: (target, frameId) ->
super(target, frameId)
@isTarget = true
getUrl: () ->
Mustache.to_html(FRAMENET_FRAME_URL_TEMPLATE, {name: @label})
class FrameElementCell extends AnnotationCell
constructor: (fe, frameId) ->
super(fe, frameId)
@isFrameElement = true
BLANK = new Cell()
###
Main functionality of the Semafor visualization demo
###
class SemViz
constructor: (
@parseUrl = PARSE_URL,
@inputArea = INPUT_BOX_SELECTOR
) ->
###
Clears room for the given span if it is a multiword span.
###
makeRoom: (table, span, frameId) ->
spanLength = span.end - span.start
# mark cells that this cell covers to be deleted
if spanLength > 1
for offset in [1...spanLength]
table[span.start+offset][frameId] = undefined
###
Sorts the targets and frame elements of the given annotated sentence into
a table.
Their row in the table is determined by the start of their span.
Their column is based on their frame.
###
sortIntoTable: (sentence) ->
numTokens = sentence.tokens.length
numFrames = sentence.frames.length
# initialize a 2d array with filler cells
table = ((BLANK for x in [0...numFrames]) for y in [0...numTokens])
[table.width, table.height] = [numFrames, numTokens]
# drop each target and frame element into the appropriate spot in the
# table, clearing room if necessary
# NB: this could be problematic if some overlap
for frame, frameId in sentence.frames
for fe in frame.annotationSets[0].frameElements
table[fe.start][frameId] = new FrameElementCell(fe, frameId)
@makeRoom(table, fe, frameId)
target = frame.target
table[target.start][frameId] = new TargetCell(target, frameId)
@makeRoom(table, target, frameId)
table
###
Takes the given semafor parse and renders it to html
###
render: (sentence) ->
table = @sortIntoTable(sentence)
#remove null cells
for row, i in table
table[i] = (x for x in row when x?)
targetHeaders = (
new TargetCell(frame.target, i) for frame, i in sentence.frames
)
tokenHeaders = (
new Header(token, i) for token, i in sentence.tokens
)
rows = ({token: tokenHeaders[i], frames: row} for row, i in table)
Mustache.to_html(
FRAME_TABLE_TEMPLATE,
{rows: rows, targetHeaders: targetHeaders}
)
###
Renders the given dependency-parsed sentence using brat
###
renderDependencyParse: (sentence) ->
# for some reason brat doesn't work twice on the same div
$("#"+DEPENDENCY_DISPLAY_ID).remove();
$(DEPENDENCY_CONTAINER_SELECTOR).append('<div id="'+DEPENDENCY_DISPLAY_ID+'">')
# render (unstyled) to div using brat
Util.embed(DEPENDENCY_DISPLAY_ID, {}, sentence, [])
$(DEPENDENCY_FORMAT_DISPLAY_ID).text(sentence.conll)
$(DEPENDENCY_FORMAT_DISPLAY_ID).show()
###
Submits the content of the input textarea to the parse API endpoint,
and then renders and displays the response.
###
submitSentence: ->
sentence = $(@inputArea).val()
spinner = $(SPINNER_SELECTOR)
spinner.show()
$(FRAME_CONTAINER_SELECTOR).hide()
$(DEPENDENCY_CONTAINER_SELECTOR).hide()
$.ajax(
url: @parseUrl,
data: {sentence: sentence},
success: (data) =>
spinner.hide()
sentence = data.sentences[0] # TODO: multiple sentences
$(FRAME_DISPLAY_SELECTOR).html(@render(sentence))
@renderDependencyParse(sentence)
$(FRAME_CONTAINER_SELECTOR).show()
$(DEPENDENCY_CONTAINER_SELECTOR).show()
error: (data) =>
spinner.hide()
$(FRAME_DISPLAY_SELECTOR).text("Error")
$(DEPENDENCY_CONTAINER_SELECTOR).text("Error")
$(FRAME_CONTAINER_SELECTOR).show()
$(DEPENDENCY_CONTAINER_SELECTOR).show()
)
# Make SemViz globally visible
if typeof module != "undefined" && module.exports
#On a server
globalObject = exports
else
#On a client
globalObject = window
globalObject.SemViz = SemViz
globalObject.semViz = new SemViz()
// Generated by CoffeeScript 1.9.3
/*
SemViz
A visualizer for Semafor parses
Requires jQuery, mustache
Author: Sam Thomson (sthomson@cs.cmu.edu)
*/
(function() {
var AnnotationCell, BLANK, Cell, DEPENDENCY_CONTAINER_SELECTOR, DEPENDENCY_DISPLAY_ID, DEPENDENCY_FORMAT_DISPLAY_ID, FRAMENET_FRAME_URL_TEMPLATE, FRAME_CONTAINER_SELECTOR, FRAME_DISPLAY_SELECTOR, FRAME_TABLE_TEMPLATE, FrameElementCell, Header, INPUT_BOX_SELECTOR, PARSE_URL, SPINNER_SELECTOR, SemViz, TargetCell, globalObject,
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty;
FRAME_TABLE_TEMPLATE = "<table id=frame_table>\n <tr>\n <thead>\n <th></th>\n {{#targetHeaders}}\n <th class=\"target\">\n <a href={{getUrl}}>{{label}}</a>\n </th>\n {{/targetHeaders}}\n </thead>\n </tr>\n {{#rows}}\n <tr id=\"token_{{token.idx}}\">\n <th>{{token.label}}</th>\n {{#frames}}\n <td rowspan={{spanLength}}\n {{#isFrameElement}}\n class=\"annotation frame_element\"\n {{/isFrameElement}}\n {{#isTarget}}\n class=\"annotation target\"\n {{/isTarget}}\n >\n {{label}}\n </td>\n {{/frames}}\n </tr>\n {{/rows}}\n</table>";
FRAMENET_FRAME_URL_TEMPLATE = 'https://framenet2.icsi.berkeley.edu/fnReports/data/frame/{{name}}.xml';
PARSE_URL = document.location.protocol + "//" + document.location.host + "/api/v1/parse";
INPUT_BOX_SELECTOR = "textarea[name=sentence]";
DEPENDENCY_CONTAINER_SELECTOR = '#dependency_parse';
DEPENDENCY_DISPLAY_ID = 'brat_parse';
DEPENDENCY_FORMAT_DISPLAY_ID = '#conll_parse';
FRAME_CONTAINER_SELECTOR = '#frame_semantic_parse';
FRAME_DISPLAY_SELECTOR = '#parse_table';
SPINNER_SELECTOR = "#spinner";
Cell = (function() {
function Cell(label1, spanLength1) {
this.label = label1 != null ? label1 : '';
this.spanLength = spanLength1 != null ? spanLength1 : 1;
}
return Cell;
})();
Header = (function(superClass) {
extend(Header, superClass);
function Header(label, idx) {
this.idx = idx;
Header.__super__.constructor.call(this, label = label);
}
return Header;
})(Cell);
AnnotationCell = (function(superClass) {
extend(AnnotationCell, superClass);
function AnnotationCell(span, frameId1) {
var label, spanLength;
this.frameId = frameId1;
AnnotationCell.__super__.constructor.call(this, label = span.name, spanLength = span.end - span.start);
this.spanStart = span.start;
}
return AnnotationCell;
})(Cell);
TargetCell = (function(superClass) {
extend(TargetCell, superClass);
function TargetCell(target, frameId) {
TargetCell.__super__.constructor.call(this, target, frameId);
this.isTarget = true;
}
TargetCell.prototype.getUrl = function() {
return Mustache.to_html(FRAMENET_FRAME_URL_TEMPLATE, {
name: this.label
});
};
return TargetCell;
})(AnnotationCell);
FrameElementCell = (function(superClass) {
extend(FrameElementCell, superClass);
function FrameElementCell(fe, frameId) {
FrameElementCell.__super__.constructor.call(this, fe, frameId);
this.isFrameElement = true;
}
return FrameElementCell;
})(AnnotationCell);
BLANK = new Cell();
/*
Main functionality of the Semafor visualization demo
*/
SemViz = (function() {
function SemViz(parseUrl, inputArea) {
this.parseUrl = parseUrl != null ? parseUrl : PARSE_URL;
this.inputArea = inputArea != null ? inputArea : INPUT_BOX_SELECTOR;
}
/*