Skip to content

Docker image #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jun 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.git*
14 changes: 14 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM python:3.6.8-alpine3.9

WORKDIR /usr/src/app

# Install build dependencies such as gcc
RUN apk update && apk add build-base

COPY requirements.txt .
RUN pip install --upgrade pip && pip install -r requirements.txt

COPY . .

CMD python main.py
EXPOSE 80
35 changes: 30 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,34 @@
# pythainlp-webdemo
# PyThaiNLP Web Demo
![](https://img.shields.io/docker/pulls/pythainlp/demo.svg)
<div align="center">
<img src="https://i.imgur.com/C6FhLfD.png"/>
<p>
PyThaiNLP Web Demo is a web application containing several algorithms implemented in PyThaiNLP.
It is an interface that allows users test those algorithms before actually adopting them in their usecases or applications.
</p>
</div>

Web demo for PyThaiNLP
## Run via Docker (recommended)
```
# The command below starts the web that can be accessed
# via http://127.0.0.1:8080
> docker run -i -p 8080:80 pythainlp/demo
* Serving Flask app "main" (lazy loading)
```

run : python main.py
## Run locally
```
# Please make sure that all dependencies are installed
# via pip install -r requirements.txt
> python main.py
```

## note
## Development

สามารถ fork ตัวโปรเจค https://github.com/PyThaiNLP/pythainlp-webdemo ไปพัฒนาต่อแล้วส่ง pull requests กลับมาได้ครับ ไม่จำกัดเครื่องมือและภาษาที่ใช้งานครับ
### Build Docker image
```
docker build -t pythainlp/demo .
```

## Contributions
We're more than happy to receive issues and pull-requests.
24 changes: 24 additions & 0 deletions config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
tokenisation_algorithms:
- newmm
- longest
text_samples:
short: >-
คนที่ฝึกภาษาอังกฤษ แม้ว่าต่างคนจะต่างความต้องการ แต่อย่างหนึ่งที่ดูจะเหมือนกัน คือ
อยากอ่านข่าวภาษาอังกฤษได้คล่องเหมือนอ่านข่าวภาษาไทย
ผมสรุปอย่างนี้เพราะมี 2 บทความในเว็บนี้ที่ท่านผู้อ่านเข้าไปอ่านมากทีเดียว
soundex: >-
รถ

รด

รส
news: >-
“อนุทิน” บอกอย่าห่วงปมสอบ “เสี่ยโต้ง” ขอกันยังมากกว่า
เมื่อเวลา 08.20 น. วันที่ 19 มิถุนายน ที่หอประชุมใหญ่ทีโอที ถ.แจ้งวัฒนะ นายอนุทิน ชาญวีรกูล หัวหน้าพรรคภูมิใจไทย
ให้สัมภาษณ์ถึงความคืบหน้า การสอบสวนกรณีนายสิริพงศ์ อังคสกุลเกียรติ ส.ส.ศรีสะเกษ
ที่โหวตสวนมติพรรคในการเลือกนายกฯ หัวหน้าพรรคภูมิใจไทย กล่าวว่า ยังไม่คืบหน้า อย่าไปกังวล
ทุกอย่างทำตามระเบียบพรรค เรื่องแค่นี้ขอกันกินยังมากกว่า ทั้งนี้ ตนไม่ทราบว่านายสิริพงศ์
ได้ชี้แจงต่อคณะกรรมการสอบสวนของพรรคแล้วหรือไม่ แต่ได้โทรศัพท์คุยกันก็ยังเป็นปกติ
ไม่มีปัญหาเป็นเอกสิทธิ์ของส.ส.ก็ต้องเคารพ เพราะเขาใช้เอกสิทธิ์ของเขา
ส่วนมติพรรคก็เป็นเรื่องของมติพรรค อย่างไรก็ตาม คงไม่มีการกำชับส.ส.ของพรรคในเรื่องนี้
เพราะทุกคนมีวุฒิภาวะ และคงพูดกันรู้เรื่อง แต่กรณีที่เกิดขึ้นในครั้งที่ผ่านมาอาจจะเผลอไป
93 changes: 63 additions & 30 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,33 @@
พัฒนาโดย นาย วรรณพงษ์ ภัททิยไพบูลย์
"""
import logging
from flask import Flask, render_template, abort, request,jsonify
import json
import os

from flask import Flask, render_template, abort, request, jsonify
from flask import redirect, url_for

from datetime import datetime

import pythainlp
from pythainlp.tokenize import word_tokenize
from pythainlp.tokenize import tcc
#from pythainlp.word_vector import thai2vec
from pythainlp.tokenize import tcc, syllable_tokenize
from pythainlp.tag import pos_tag
from pythainlp.sentiment import sentiment
from pythainlp.soundex import LK82,Udom83
import json
from pythainlp.tag.named_entity import ThaiNameTagger
from pythainlp.soundex import lk82, udom83

import yaml

with open("./config.yaml", 'r') as stream:
app_config = yaml.safe_load(stream)

port = os.environ.get("PORT", 80)

app = Flask(__name__)

@app.route('/')
def home():
return render_template('index.html', name='Home')
return redirect(url_for('word_tokenizer_web'))

@app.route('/word_tokenizer')
def word_tokenizer_web():
Expand All @@ -43,28 +57,40 @@ def soundex_web():
def tcc_web():
return render_template('tcc.html', name='TCC')

@app.route('/about')
def about_web():
return render_template('about.html', name='About')
@app.route('/syllable')
def syllable_web():
return render_template('syllable.html', name='Syllable')

@app.route('/api/word_tokenizer', methods=["GET"])
def word_tokenizer_api():
txt=""
try:
sent = request.args.get('sent', 0, type=str)
engine = request.args.get('engine', 0, type=str)
txt='|'.join(word_tokenize(sent,engine)).replace('|<|br|>|','<br>').replace('<|br|>','<br>')
except:
txt="Error"
return jsonify(result=txt)

sent = request.args.get('sent', 0, type=str)
engine = request.args.get('engine', 0, type=str)

tokenised = word_tokenize(sent, engine=engine)

return jsonify(result='|'.join(tokenised))

@app.route('/api/tcc', methods=["GET"])
def tcc_api():
sent = request.args.get('sent', 0, type=str)
txt=""
for i in sent.split('<br>'):
txt+=tcc.tcc(i)+"<br>"
return jsonify(result=txt)
txt = request.args.get('sent', 0, type=str)
res = "~".join(tcc.tcc(txt.strip()))
return jsonify(result=res)

@app.route('/api/syllable', methods=["GET"])
def syllable_api():
txt = request.args.get('sent', 0, type=str)
res = "~".join(syllable_tokenize(txt.strip()))
return jsonify(result=res)

@app.route('/api/ner', methods=["GET"])
def ner_api():
ner = ThaiNameTagger()
txt = request.args.get('sent', 0, type=str)
print(txt)
res = ner.get_ner(txt, pos=False)

return jsonify(result=res)

@app.route('/api/pos_tag', methods=["GET"])
def pos_tag_api():
Expand All @@ -79,21 +105,28 @@ def soundex_api():
sent = request.args.get('sent', 0, type=str)
txt=""
for i in sent.split('<br>'):
txt+="<b>Word : </b>"+i+"<br><p>กฎการเข้ารหัสซาวน์เด็กซ์ของ วิชิตหล่อจีระชุณห์กุล และ เจริญ คุวินทร์พันธุ์ - LK82 : "+LK82(i)+"<br>กฎการเข้ารหัสซาวน์เด็กซ์ของ วรรณี อุดมพาณิชย์ - Udom83 : "+Udom83(i)+"</p><br>"
txt += "<b>Word : </b>"+i+"<br><p>กฎการเข้ารหัสซาวน์เด็กซ์ของ วิชิตหล่อจีระชุณห์กุล และ เจริญ คุวินทร์พันธุ์ - LK82 : "+ lk82(i) +"<br>กฎการเข้ารหัสซาวน์เด็กซ์ของ วรรณี อุดมพาณิชย์ - Udom83 : "+ udom83(i)+"</p><br>"
return jsonify(result=txt)

@app.errorhandler(500)
def server_error(e):
logging.exception('An error occurred during a request.')
return """
An internal error occurred: <pre>{}</pre>
See logs for full stacktrace.
""".format(e), 500
logging.exception('An error occurred during a request.')
return """
An internal error occurred: <pre>{}</pre>
See logs for full stacktrace.
""".format(e), 500

@app.errorhandler(404)
def not_found(e):
return "404 NOT FOUND"

@app.context_processor
def inject_stuff():
return dict(
pythainlp_version=pythainlp.__version__,
now=datetime.now(),
app_config=app_config
)

if __name__ == '__main__':
app.run(host='127.0.0.1', port=8080, debug=True)
app.run(host='0.0.0.0', port=port, debug=True)
28 changes: 25 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
pythainlp
gunicorn
flask
artagger==0.1.0.3
certifi==2019.3.9
chardet==3.0.4
Click==7.0
dill==0.2.9
Flask==1.0.3
gunicorn==19.9.0
idna==2.8
itsdangerous==1.1.0
Jinja2==2.10.1
marisa-trie==0.7.5
MarkupSafe==1.1.1
nltk==3.4.1
pythainlp==2.0.5
python-crfsuite==0.9.6
pytz==2019.1
PyYAML==5.1
requests==2.22.0
six==1.12.0
sklearn-crfsuite==0.3.6
tabulate==0.8.3
tinydb==3.13.0
tqdm==4.32.1
urllib3==1.25.3
Werkzeug==0.15.4
3 changes: 3 additions & 0 deletions scripts/docker-build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

docker build -t pythainlp/demo:latest .
3 changes: 3 additions & 0 deletions scripts/docker-push.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

docker push pythainlp/demo
14 changes: 13 additions & 1 deletion static/css/main.css
Original file line number Diff line number Diff line change
@@ -1 +1,13 @@
body {padding-top: 3.5rem;}@media print {#ghostery-purple-box {display:none !important}}
body {
padding-top: 3.5rem;
}

@media print {
#ghostery-purple-box {
display: none !important
}
}

footer {
text-align: center;
}
12 changes: 0 additions & 12 deletions templates/about.html

This file was deleted.

35 changes: 33 additions & 2 deletions templates/ner.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,40 @@
{% extends "templates.html" %}
{% block body %}
<div class="container">
<h1>Hello</h1>
<h1>Name Entity Recognition</h1>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label for="exampleFormControlTextarea1">Input Thai sentence</label>
<textarea class="form-control" id="sent_text" rows="9">{{ app_config.text_samples["news"] }}</textarea>
<br>
<button type="button" class="btn btn-primary" id="send_word">Send</button>
</div>
</div>
<div class="col-sm-6 other">
<div class="panel panel-primary">
<div class="card bg-light text-dark"><div class="card-body" id="show_word"></div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block runjs %}
<script></script>
<script>
$("#send_word").click(function() {
var txt =$('#sent_text').val().replace(/\n/g,'<br>');
$.getJSON('/api/ner', { sent: txt }, function(data) {
let txt = data.result.map( t => {
if(t[1] == "O") {
return t[0]
} else {
return "[" + t[0] + "::" + t[1] + "]"
}
}).join("");
console.log(txt);

$("#show_word").html(txt);
});
});
</script>
{% endblock %}
16 changes: 9 additions & 7 deletions templates/pos_tag.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ <h1>POS Tag</h1>
<div class="col-sm-6">
<div class="form-group">
<label for="exampleFormControlTextarea1">Input Thai sentence</label>
<textarea class="form-control" id="sent_text" rows="9"></textarea><br>
<textarea class="form-control" id="sent_text" rows="9">
{{ app_config.text_samples["short"] }}
</textarea><br>
<button type="button" class="btn btn-primary" id="send_word">Send</button>
</div>
</div>
Expand All @@ -20,12 +22,12 @@ <h1>POS Tag</h1>
{% endblock %}
{% block runjs %}
<script>
$("#send_word").click(function() {
var txt =$('#sent_text').val().replace(/\n/g,'<br>');
$.getJSON('/api/pos_tag', {
sent: txt,
$("#send_word").click(function() {
$.getJSON('/api/pos_tag', {
sent: $('#sent_text').val()
}, function(data) {
$("#show_word").html(data.result);
$("#show_word").html(data.result);
});
});</script>
});
</script>
{% endblock %}
3 changes: 2 additions & 1 deletion templates/soundex.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ <h1>Soundex</h1>
<div class="col-sm-6">
<div class="form-group">
<label for="exampleFormControlTextarea1">Input Thai word</label>
<textarea class="form-control" id="sent_text" rows="9"></textarea><br>
<textarea class="form-control" id="sent_text" rows="9">{{ app_config.text_samples["soundex"] }}</textarea>
<br>
<button type="button" class="btn btn-primary" id="send_word">Send</button>
</div>
</div>
Expand Down
Loading