Simple + dirty Python binding for Moses (SMT decoder)

I want to call Moses from python like below:

from moses import Moses
m = Moses("enth/model/moses.ini")
print m.decode("i eat rice")
# result: ฉัน กิน ข้าว

so i create this extension.

moses.cpp:
#include
#include “structmember.h”
#include “Parameter.h”
#include “StaticData.h”
#include “Manager.h”
#include “Hypothesis.h”
#include
#include
#include

typedef struct {
PyObject_HEAD
Parameter *param;
const StaticData *staticData;
vector *weights;
vector *inputFactorOrder, *outputFactorOrder;
FactorMask *inputFactorUsed;
long translation_id;
} Moses;

static int
Moses_traverse(Moses *self, visitproc visit, void *arg)
{
return 0;
}

static int
Moses_clear(Moses *self)
{
// FIXME
return 0;
}

static void
Moses_dealloc(Moses* self)
{
Moses_clear(self);
self->ob_type->tp_free((PyObject*)self);
}

static PyObject *
Moses_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
Moses *self;

self = (Moses *)type->tp_alloc(type, 0);

if (self != NULL) {
self->param = new Parameter();
if(self->param == 0) {
Py_DECREF(self);
return NULL;
}
self->staticData = &(StaticData::Instance());
if(self->staticData== 0) {
Py_DECREF(self);
return NULL;
}

self->weights = new vector;
if(self->weights == 0) {
Py_DECREF(self);
return NULL;
}

self->inputFactorOrder = new vector();
if(self->inputFactorOrder == NULL) {
Py_DECREF(self);
return NULL;
}

self->outputFactorOrder = new vector();
if(self->outputFactorOrder == NULL) {
Py_DECREF(self);
return NULL;
}

self->inputFactorUsed = new FactorMask();
if(self->inputFactorUsed == NULL) {
Py_DECREF(self);
return NULL;
}

self->translation_id = 0;

return (PyObject *)self;
}

static int
Moses_init(Moses *self, PyObject *args, PyObject *kwds)
{
const char *ini_path;

if(!PyArg_ParseTuple(args, “s”, &ini_path))
return -1;
if(!(self->param->LoadParam(std::string(ini_path))))
return -1;

if (!StaticData::LoadDataStatic(self->param))
return -1;

if(self->weights) {
delete self->weights;
self->weights = new vector(self->staticData->GetAllWeights());
}

if(self->weights->size() != self->staticData->GetScoreIndexManager().GetTotalNumberOfScores())
return -1;

if(self->inputFactorOrder && self->outputFactorOrder && self->inputFactorUsed) {
delete self->inputFactorOrder;
delete self->outputFactorOrder;
delete self->inputFactorUsed;
self->inputFactorOrder = new vector(self->staticData->GetInputFactorOrder());
self->outputFactorOrder = new vector(self->staticData->GetOutputFactorOrder());
self->inputFactorUsed = new FactorMask(*self->inputFactorOrder);
}
return 0;
}

static PyMemberDef Moses_members[] = {
/*
{“first”, T_OBJECT_EX, offsetof(Moses, first), 0,
“first name”},
{“last”, T_OBJECT_EX, offsetof(Moses, last), 0,
“last name”},
{“number”, T_INT, offsetof(Moses, number), 0,
“moses number”}, */
{NULL} /* Sentinel */
};

static PyObject *
Moses_decode(Moses* self, PyObject *args)
{
const char *source_sentence;
if(!PyArg_ParseTuple(args, “s”, &source_sentence))
return NULL;
std::stringstream s;
s < < source_sentence <inputFactorOrder)) {
if (long x = source.GetTranslationId()) {
if (x >= self->translation_id) {
self->translation_id = x + 1;
}
} else {
source.SetTranslationId(self->translation_id++);
}
Manager manager(source, self->staticData->GetSearchAlgorithm());
manager.ProcessSentence();
const Hypothesis *hypo = manager.GetBestHypothesis();
PyObject* result = PyList_New(0);
while(hypo != NULL) {
stringstream phrase_stream;
phrase_stream < GetCurrTargetPhrase();
PyList_Append(result,
PyString_FromString(phrase_stream.str().c_str()));
hypo = hypo->GetPrevHypo();
}
PyList_Reverse(result);
return result;
} else {
PyErr_SetString(PyExc_RuntimeError, “Input cannot be read properly”);
return NULL;
}
}

static PyMethodDef Moses_methods[] = {
{“decode”, (PyCFunction)Moses_decode, METH_VARARGS,
“Return decoded target language”},
{NULL} /* Sentinel */
};

static PyTypeObject MosesType = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
“moses.Moses”, /*tp_name*/
sizeof(Moses), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)Moses_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
“Moses objects”, /* tp_doc */
(traverseproc)Moses_traverse, /* tp_traverse */
(inquiry)Moses_clear, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
Moses_methods, /* tp_methods */
Moses_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)Moses_init, /* tp_init */
0, /* tp_alloc */
Moses_new, /* tp_new */
};

static PyMethodDef module_methods[] = {
{NULL} /* Sentinel */
};

#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC
initmoses(void)
{
PyObject* m;

if (PyType_Ready(&MosesType) < 0)
return;

m = Py_InitModule3("moses", module_methods,
"Example module that creates an extension type.");

if (m == NULL)
return;

Py_INCREF(&MosesType);
PyModule_AddObject(m, "Moses", (PyObject *)&MosesType);
}

setup.py:
from distutils.core import setup, Extension

module1 = Extension('moses',
define_macros = [('MAJOR_VERSION', '0'),
('MINOR_VERSION', '1')],
include_dirs = ['../moses/src'],
libraries = ['moses', 'z', 'oolm', 'dstruct', 'misc'],
library_dirs = ['../moses/src'],
sources = ['moses.cpp'])

setup (name = 'moses',
version = '0.1',
description = 'This is a demo package',
author = 'Vee Satayamas',
author_email = 'vsatayamas@gmail.com',
url = 'http://www.python.org/doc/current/ext/building.html&#039;,
long_description = '''
This is really just a demo package.
''',
ext_modules = [module1])

One thought on “Simple + dirty Python binding for Moses (SMT decoder)

ใส่ความเห็น

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / เปลี่ยนแปลง )

Twitter picture

You are commenting using your Twitter account. Log Out / เปลี่ยนแปลง )

Facebook photo

You are commenting using your Facebook account. Log Out / เปลี่ยนแปลง )

Google+ photo

You are commenting using your Google+ account. Log Out / เปลี่ยนแปลง )

Connecting to %s