diff --git a/README.md b/README.md index b31f72af51b005d260bc07bbb28a1408e8ee91a6..adc2e8d4454d1584907d23dbda24087a603c68fc 100644 --- a/README.md +++ b/README.md @@ -228,14 +228,6 @@ curl -H "Content-Type:application/json" -X POST -d '{"url": "https://paddle-serv | Description | Get click probability from a feature vector of item | - -| Key | Value | -| :----------------- | :----------------------------------------------------------- | -| Model Name | DNN-CTR(with cube) | -| URL | https://paddle-serving.bj.bcebos.com/unittest/ctr_cube_unittest.tar.gz | -| Client/Server Code | https://github.com/PaddlePaddle/Serving/tree/develop/python/examples/criteo_ctr_with_cube | -| Description | Get click probability from a feature vector of item | -

Document

### New to Paddle Serving diff --git a/README_CN.md b/README_CN.md index 80c6041205ec91482f7d30157efa5e4e66a7c021..ddb06309a36337a1230bbbc7d9612ce7a407b2d2 100644 --- a/README_CN.md +++ b/README_CN.md @@ -268,14 +268,6 @@ curl -H "Content-Type:application/json" -X POST -d '{"url": "https://paddle-serv -| Key | Value | -| :----------------- | :----------------------------------------------------------- | -| 模型名 | DNN-CTR(with cube) | -| 下载链接 | https://paddle-serving.bj.bcebos.com/unittest/ctr_cube_unittest.tar.gz | -| 客户端/服务端代码 | https://github.com/PaddlePaddle/Serving/tree/develop/python/examples/criteo_ctr_with_cube | -| 介绍 | 从项目的特征向量中获得点击概率 | - -

文档

### 新手教程 diff --git a/core/predictor/framework/infer.h b/core/predictor/framework/infer.h index 177b6274e3bde03ef082c77d168266e919d42735..f8bd7843706187c13d8f38c7d33c87b51369e5a0 100644 --- a/core/predictor/framework/infer.h +++ b/core/predictor/framework/infer.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "core/predictor/common/inner_common.h" #include "core/predictor/framework/bsf.h" @@ -588,12 +589,14 @@ class VersionedInferEngine : public InferEngine { LOG(ERROR) << "Failed generate engine with type:" << engine_type; return -1; } - + VLOG(2) << "FLGS_logtostderr " << FLAGS_logtostderr; + int tmp = FLAGS_logtostderr; if (engine->proc_initialize(conf, version) != 0) { LOG(ERROR) << "Failed initialize engine, type:" << engine_type; return -1; } - + VLOG(2) << "FLGS_logtostderr " << FLAGS_logtostderr; + FLAGS_logtostderr = tmp; auto r = _versions.insert(std::make_pair(engine->version(), engine)); if (!r.second) { LOG(ERROR) << "Failed insert item: " << engine->version() @@ -760,7 +763,6 @@ class InferManager { LOG(ERROR) << "failed load infer config, path: " << path << "/" << file; return -1; } - size_t engine_num = model_toolkit_conf.engines_size(); for (size_t ei = 0; ei < engine_num; ++ei) { std::string engine_name = model_toolkit_conf.engines(ei).name(); @@ -769,12 +771,10 @@ class InferManager { LOG(ERROR) << "Failed generate versioned engine: " << engine_name; return -1; } - if (engine->proc_initialize(model_toolkit_conf.engines(ei)) != 0) { LOG(ERROR) << "Failed initialize version engine, name:" << engine_name; return -1; } - auto r = _map.insert(std::make_pair(engine_name, engine)); if (!r.second) { LOG(ERROR) << "Failed insert item: " << engine_name; @@ -782,7 +782,6 @@ class InferManager { } LOG(WARNING) << "Succ proc initialize engine: " << engine_name; } - return 0; } diff --git a/doc/IMDB_GO_CLIENT.md b/doc/IMDB_GO_CLIENT.md index 5befc0226235dd599b980d98594dba78e54bf530..a9f610cfb154548ffe6f89820c1f61b114303351 100644 --- a/doc/IMDB_GO_CLIENT.md +++ b/doc/IMDB_GO_CLIENT.md @@ -21,37 +21,10 @@ wget https://paddle-serving.bj.bcebos.com/data/text_classification/imdb_serving_ tar -xzf imdb_serving_example.tar.gz ``` -### Server Side Code - -```python -# test_server_go.py -import os -import sys -from paddle_serving_server import OpMaker -from paddle_serving_server import OpSeqMaker -from paddle_serving_server import Server - -op_maker = OpMaker() -read_op = op_maker.create('general_text_reader') -general_infer_op = op_maker.create('general_infer') -general_response_op = op_maker.create('general_text_response') - -op_seq_maker = OpSeqMaker() -op_seq_maker.add_op(read_op) -op_seq_maker.add_op(general_infer_op) -op_seq_maker.add_op(general_response_op) - -server = Server() -server.set_op_sequence(op_seq_maker.get_op_sequence()) -server.load_model_config(sys.argv[1]) -server.prepare_server(workdir="work_dir1", port=9292, device="cpu") -server.run_server() -``` - ### Start Server ``` shell -python test_server_go.py ./serving_server_model/ 9292 +python -m paddle_serving_server.serve --model ./serving_server_model/ --port 9292 ``` ### Client code example diff --git a/doc/IMDB_GO_CLIENT_CN.md b/doc/IMDB_GO_CLIENT_CN.md index d14abe647038846aeeeebf9484f1c02e151b4275..bf55ef48399204b1e88fd5a4976a7ab659fb3e3e 100644 --- a/doc/IMDB_GO_CLIENT_CN.md +++ b/doc/IMDB_GO_CLIENT_CN.md @@ -20,106 +20,79 @@ wget https://paddle-serving.bj.bcebos.com/data/text_classification/imdb_serving_ tar -xzf imdb_serving_example.tar.gz ``` -### 服务器端代码 - -```python -# test_server_go.py -import os -import sys -from paddle_serving_server import OpMaker -from paddle_serving_server import OpSeqMaker -from paddle_serving_server import Server - -op_maker = OpMaker () -read_op = op_maker.create ('general_text_reader') -general_infer_op = op_maker.create ('general_infer') -general_response_op = op_maker.create ('general_text_response') - -op_seq_maker = OpSeqMaker () -op_seq_maker.add_op (read_op) -op_seq_maker.add_op (general_infer_op) -op_seq_maker.add_op (general_response_op) - -server = Server () -server.set_op_sequence (op_seq_maker.get_op_sequence ()) -server.load_model_config (sys.argv [1]) -server.prepare_server (workdir = "work_dir1", port = 9292, device = "cpu") -server.run_server () -``` - ### 启动服务器 ```shell -python test_server_go.py ./serving_server_model/ 9292 +python -m paddle_serving_server.serve --model ./serving_server_model/ --port 9292 ``` ### 客户端代码示例 -```go +``` go // imdb_client.go package main import ( -       "io" -       "fmt" -       "strings" -       "bufio" -       "strconv" -       "os" -       serving_client "github.com/PaddlePaddle/Serving/go/serving_client" + "io" + "fmt" + "strings" + "bufio" + "strconv" + "os" + serving_client "github.com/PaddlePaddle/Serving/go/serving_client" ) -func main () { -     var config_file_path string -     config_file_path = os.Args [1] -     handle: = serving_client.LoadModelConfig (config_file_path) -     handle = serving_client.Connect ("127.0.0.1", "9292", handle) - -     test_file_path: = os.Args [2] -     fi, err: = os.Open (test_file_path) -     if err! = nil { -     fmt.Print (err) -     } - -     defer fi.Close () -     br: = bufio.NewReader (fi) - -     fetch: = [] string {"cost", "acc", "prediction"} - -     var result map [string] [] float32 - -     for { -     line, err: = br.ReadString ('\ n') -if err == io.EOF { -break -} - -line = strings.Trim (line, "\ n") - -var words = [] int64 {} - -s: = strings.Split (line, "") -value, err: = strconv.Atoi (s [0]) -var feed_int_map map [string] [] int64 -        -for _, v: = range s [1: value + 1] { -int_v, _: = strconv.Atoi (v) -words = append (words, int64 (int_v)) -} - -label, err: = strconv.Atoi (s [len (s) -1]) - -if err! = nil { -panic (err) -} - -feed_int_map = map [string] [] int64 {} -feed_int_map ["words"] = words -feed_int_map ["label"] = [] int64 {int64 (label)} -Ranch -result = serving_client.Predict (handle, feed_int_map, fetch) -fmt.Println (result ["prediction"] [1], "\ t", int64 (label)) -    } +func main() { + var config_file_path string + config_file_path = os.Args[1] + handle := serving_client.LoadModelConfig(config_file_path) + handle = serving_client.Connect("127.0.0.1", "9292", handle) + + test_file_path := os.Args[2] + fi, err := os.Open(test_file_path) + if err != nil { + fmt.Print(err) + } + + defer fi.Close() + br := bufio.NewReader(fi) + + fetch := []string{"cost", "acc", "prediction"} + + var result map[string][]float32 + + for { + line, err := br.ReadString('\n') + if err == io.EOF { + break + } + + line = strings.Trim(line, "\n") + + var words = []int64{} + + s := strings.Split(line, " ") + value, err := strconv.Atoi(s[0]) + var feed_int_map map[string][]int64 + + for _, v := range s[1:value + 1] { + int_v, _ := strconv.Atoi(v) + words = append(words, int64(int_v)) + } + + label, err := strconv.Atoi(s[len(s)-1]) + + if err != nil { + panic(err) + } + + feed_int_map = map[string][]int64{} + feed_int_map["words"] = words + feed_int_map["label"] = []int64{int64(label)} + + result = serving_client.Predict(handle, feed_int_map, fetch) + fmt.Println(result["prediction"][1], "\t", int64(label)) + } } ``` diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d0c3cbf1020d5c292abdedf27627c6abe25e2293 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/doc/index.rst b/doc/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..0c0a0f0d7bcf0de8a4e87932585d1f37ff29b78f --- /dev/null +++ b/doc/index.rst @@ -0,0 +1,13 @@ +:github_url: https://github.com/PaddlePaddle/Serving + +.. mdinclude:: md/logo.md + +Paddle Serving +============== +.. toctree:: + :maxdepth: 1 + :caption: Readme + :hidden: + +.. _instruction: instruction.html + diff --git a/doc/markdown2rst.py b/doc/markdown2rst.py new file mode 100644 index 0000000000000000000000000000000000000000..1cab0c6c2a9f292177dcf3b4403340781bb9379e --- /dev/null +++ b/doc/markdown2rst.py @@ -0,0 +1,718 @@ +#!/usr/bin/env python3 +""" + markdown to rst +""" +# -*- coding: utf-8 -*- + +from __future__ import print_function, unicode_literals +import os +import os.path +import re +import sys +from argparse import ArgumentParser, Namespace + +from docutils import statemachine, nodes, io, utils +from docutils.parsers import rst +from docutils.core import ErrorString +from docutils.utils import SafeString, column_width +import mistune + +if sys.version_info < (3, ): + from codecs import open as _open + from urlparse import urlparse +else: + _open = open + from urllib.parse import urlparse + +__version__ = '0.2.1' +_is_sphinx = False +prolog = '''\ +.. role:: raw-html-m2r(raw) + :format: html + +''' + +# for command-line use +parser = ArgumentParser() +options = Namespace() +parser.add_argument( + 'input_file', nargs='*', help='files to convert to reST format') +parser.add_argument( + '--overwrite', + action='store_true', + default=False, + help='overwrite output file without confirmaion') +parser.add_argument( + '--dry-run', + action='store_true', + default=False, + help='print conversion result and not save output file') +parser.add_argument( + '--no-underscore-emphasis', + action='store_true', + default=False, + help='do not use underscore (_) for emphasis') +parser.add_argument( + '--parse-relative-links', + action='store_true', + default=False, + help='parse relative links into ref or doc directives') +parser.add_argument( + '--anonymous-references', + action='store_true', + default=False, + help='use anonymous references in generated rst') +parser.add_argument( + '--disable-inline-math', + action='store_true', + default=False, + help='disable parsing inline math') + + +def parse_options(): + """parse_options""" + parser.parse_known_args(namespace=options) + + +class RestBlockGrammar(mistune.BlockGrammar): + """RestBlockGrammar""" + directive = re.compile( + r'^( *\.\..*?)\n(?=\S)', + re.DOTALL | re.MULTILINE, ) + oneline_directive = re.compile( + r'^( *\.\..*?)$', + re.DOTALL | re.MULTILINE, ) + rest_code_block = re.compile( + r'^::\s*$', + re.DOTALL | re.MULTILINE, ) + + +class RestBlockLexer(mistune.BlockLexer): + """RestBlockLexer""" + grammar_class = RestBlockGrammar + default_rules = [ + 'directive', + 'oneline_directive', + 'rest_code_block', + ] + mistune.BlockLexer.default_rules + + def parse_directive(self, m): + """parse_directive""" + self.tokens.append({ + 'type': 'directive', + 'text': m.group(1), + }) + + def parse_oneline_directive(self, m): + """parse_oneline_directive""" + # reuse directive output + self.tokens.append({ + 'type': 'directive', + 'text': m.group(1), + }) + + def parse_rest_code_block(self, m): + """parse_rest_code_block""" + self.tokens.append({'type': 'rest_code_block', }) + + +class RestInlineGrammar(mistune.InlineGrammar): + """RestInlineGrammar""" + image_link = re.compile( + r'\[!\[(?P.*?)\]\((?P.*?)\).*?\]\((?P.*?)\)') + rest_role = re.compile(r':.*?:`.*?`|`[^`]+`:.*?:') + rest_link = re.compile(r'`[^`]*?`_') + inline_math = re.compile(r'.*\$(.*)?\$') + eol_literal_marker = re.compile(r'(\s+)?::\s*$') + # add colon and space as special text + text = re.compile(r'^[\s\S]+?(?=[\\[\s\S]+?)\1{2}(?!\1)') + # _word_ or *word* + emphasis = re.compile(r'^\b_((?:__|[^_])+?)_\b' # _word_ + r'|' + r'^\*(?P(?:\*\*|[^\*])+?)\*(?!\*)' # *word* + ) + + def no_underscore_emphasis(self): + """no_underscore_emphasis""" + self.double_emphasis = re.compile( + r'^\*{2}(?P[\s\S]+?)\*{2}(?!\*)' # **word** + ) + self.emphasis = re.compile( + r'^\*(?P(?:\*\*|[^\*])+?)\*(?!\*)' # *word* + ) + + +class RestInlineLexer(mistune.InlineLexer): + """RestInlineLexer""" + grammar_class = RestInlineGrammar + default_rules = [ + 'image_link', + 'rest_role', + 'rest_link', + 'eol_literal_marker', + ] + mistune.InlineLexer.default_rules + + def __init__(self, *args, **kwargs): + no_underscore_emphasis = kwargs.pop('no_underscore_emphasis', False) + disable_inline_math = kwargs.pop('disable_inline_math', False) + super(RestInlineLexer, self).__init__(*args, **kwargs) + if not _is_sphinx: + parse_options() + if no_underscore_emphasis or getattr(options, 'no_underscore_emphasis', + False): + self.rules.no_underscore_emphasis() + inline_maths = 'inline_math' in self.default_rules + if disable_inline_math or getattr(options, 'disable_inline_math', + False): + if inline_maths: + self.default_rules.remove('inline_math') + elif not inline_maths: + self.default_rules.insert(0, 'inline_math') + + def output_double_emphasis(self, m): + """output_double_emphasis""" + # may include code span + text = self.output(m.group('text')) + return self.renderer.double_emphasis(text) + + def output_emphasis(self, m): + """output_emphasis""" + # may include code span + text = self.output(m.group('text') or m.group(1)) + return self.renderer.emphasis(text) + + def output_image_link(self, m): + """Pass through rest role.""" + return self.renderer.image_link( + m.group('url'), m.group('target'), m.group('alt')) + + def output_rest_role(self, m): + """Pass through rest role.""" + return self.renderer.rest_role(m.group(0)) + + def output_rest_link(self, m): + """Pass through rest link.""" + return self.renderer.rest_link(m.group(0)) + + def output_inline_math(self, m): + """Pass through rest link.""" + return self.renderer.inline_math(m.group(0)) + + def output_eol_literal_marker(self, m): + """Pass through rest link.""" + marker = ':' if m.group(1) is None else '' + return self.renderer.eol_literal_marker(marker) + + +class RestRenderer(mistune.Renderer): + """RestRenderer""" + _include_raw_html = False + list_indent_re = re.compile(r'^(\s*(#\.|\*)\s)') + indent = ' ' * 3 + list_marker = '{#__rest_list_mark__#}' + hmarks = { + 1: '=', + 2: '-', + 3: '^', + 4: '~', + 5: '"', + 6: '#', + } + + def __init__(self, *args, **kwargs): + self.parse_relative_links = kwargs.pop('parse_relative_links', False) + self.anonymous_references = kwargs.pop('anonymous_references', False) + super(RestRenderer, self).__init__(*args, **kwargs) + if not _is_sphinx: + parse_options() + if getattr(options, 'parse_relative_links', False): + self.parse_relative_links = options.parse_relative_links + if getattr(options, 'anonymous_references', False): + self.anonymous_references = options.anonymous_references + + def _indent_block(self, block): + return '\n'.join(self.indent + line if line else '' + for line in block.splitlines()) + + def _raw_html(self, html): + self._include_raw_html = True + return '\ :raw-html-m2r:`{}`\ '.format(html) + + def block_code(self, code, lang=None): + """block_code""" + if lang == 'math': + first_line = '\n.. math::\n\n' + elif lang: + first_line = '\n.. code-block:: {}\n\n'.format(lang) + elif _is_sphinx: + first_line = '\n.. code-block:: guess\n\n' + else: + first_line = '\n.. code-block::\n\n' + return first_line + self._indent_block(code) + '\n' + + def block_quote(self, text): + """block_quote""" + # text includes some empty line + return '\n..\n\n{}\n\n'.format(self._indent_block(text.strip('\n'))) + + def block_html(self, html): + """Rendering block level pure html content. + + :param html: text content of the html snippet. + """ + return '\n\n.. raw:: html\n\n' + self._indent_block(html) + '\n\n' + + def header(self, text, level, raw=None): + """Rendering header/heading tags like ``

`` ``

``. + + :param text: rendered text content for the header. + :param level: a number for the header level, for example: 1. + :param raw: raw text content of the header. + """ + return '\n{0}\n{1}\n'.format(text, + self.hmarks[level] * column_width(text)) + + def hrule(self): + """Rendering method for ``
`` tag.""" + return '\n----\n' + + def list(self, body, ordered=True): + """Rendering list tags like ``
    `` and ``
      ``. + + :param body: body contents of the list. + :param ordered: whether this list is ordered or not. + """ + mark = '#. ' if ordered else '* ' + lines = body.splitlines() + for i, line in enumerate(lines): + if line and not line.startswith(self.list_marker): + lines[i] = ' ' * len(mark) + line + return '\n{}\n'.format('\n'.join(lines)).replace(self.list_marker, mark) + + def list_item(self, text): + """Rendering list item snippet. Like ``
    1. ``.""" + return '\n' + self.list_marker + text + + def paragraph(self, text): + """Rendering paragraph tags. Like ``

      ``.""" + return '\n' + text + '\n' + + def table(self, header, body): + """Rendering table element. Wrap header and body in it. + + :param header: header part of the table. + :param body: body part of the table. + """ + table = '\n.. list-table::\n' + if header and not header.isspace(): + table = (table + self.indent + ':header-rows: 1\n\n' + + self._indent_block(header) + '\n') + else: + table = table + '\n' + table = table + self._indent_block(body) + '\n\n' + return table + + def table_row(self, content): + """Rendering a table row. Like ````. + + :param content: content of current table row. + """ + contents = content.splitlines() + if not contents: + return '' + clist = ['* ' + contents[0]] + if len(contents) > 1: + for c in contents[1:]: + clist.append(' ' + c) + return '\n'.join(clist) + '\n' + + def table_cell(self, content, **flags): + """Rendering a table cell. Like ```` ````. + + :param content: content of current table cell. + :param header: whether this is header or not. + :param align: align of current table cell. + """ + return '- ' + content + '\n' + + def double_emphasis(self, text): + """Rendering **strong** text. + + :param text: text content for emphasis. + """ + return '\ **{}**\ '.format(text) + + def emphasis(self, text): + """Rendering *emphasis* text. + + :param text: text content for emphasis. + """ + return '\ *{}*\ '.format(text) + + def codespan(self, text): + """Rendering inline `code` text. + + :param text: text content for inline code. + """ + if '``' not in text: + return '\ ``{}``\ '.format(text) + else: + # actually, docutils split spaces in literal + return self._raw_html('' + '{}' + ''.format(text.replace('`', '`'))) + + def linebreak(self): + """Rendering line break like ``
      ``.""" + if self.options.get('use_xhtml'): + return self._raw_html('
      ') + '\n' + return self._raw_html('
      ') + '\n' + + def strikethrough(self, text): + """Rendering ~~strikethrough~~ text. + + :param text: text content for strikethrough. + """ + return self._raw_html('{}'.format(text)) + + def text(self, text): + """Rendering unformatted text. + + :param text: text content. + """ + return text + + def autolink(self, link, is_email=False): + """Rendering a given link or email address. + + :param link: link content or email address. + :param is_email: whether this is an email or not. + """ + return link + + def link(self, link, title, text): + """Rendering a given link with content and title. + + :param link: href link for ```` tag. + :param title: title content for `title` attribute. + :param text: text content for description. + """ + if self.anonymous_references: + underscore = '__' + else: + underscore = '_' + if title: + return self._raw_html( + '{text}'.format( + link=link, title=title, text=text)) + if not self.parse_relative_links: + return '\ `{text} <{target}>`{underscore}\ '.format( + target=link, text=text, underscore=underscore) + else: + url_info = urlparse(link) + if url_info.scheme: + return '\ `{text} <{target}>`{underscore}\ '.format( + target=link, text=text, underscore=underscore) + else: + link_type = 'doc' + anchor = url_info.fragment + if url_info.fragment: + if url_info.path: + # Can't link to anchors via doc directive. + anchor = '' + else: + # Example: [text](#anchor) + link_type = 'ref' + doc_link = '{doc_name}{anchor}'.format( + # splittext approach works whether or not path is set. It + # will return an empty string if unset, which leads to + # anchor only ref. + doc_name=os.path.splitext(url_info.path)[0], + anchor=anchor) + return '\ :{link_type}:`{text} <{doc_link}>`\ '.format( + link_type=link_type, doc_link=doc_link, text=text) + + def image(self, src, title, text): + """Rendering a image with title and text. + + :param src: source link of the image. + :param title: title text of the image. + :param text: alt text of the image. + """ + # rst does not support title option + # and I couldn't find title attribute in HTML standard + return '\n'.join([ + '', + '.. image:: {}'.format(src), + ' :target: {}'.format(src), + ' :alt: {}'.format(text), + '', + ]) + + def inline_html(self, html): + """Rendering span level pure html content. + + :param html: text content of the html snippet. + """ + return self._raw_html(html) + + def newline(self): + """Rendering newline element.""" + return '' + + def footnote_ref(self, key, index): + """Rendering the ref anchor of a footnote. + + :param key: identity key for the footnote. + :param index: the index count of current footnote. + """ + return '\ [#fn-{}]_\ '.format(key) + + def footnote_item(self, key, text): + """Rendering a footnote item. + + :param key: identity key for the footnote. + :param text: text content of the footnote. + """ + return '.. [#fn-{0}] {1}\n'.format(key, text.strip()) + + def footnotes(self, text): + """Wrapper for all footnotes. + + :param text: contents of all footnotes. + """ + if text: + return '\n\n' + text + else: + return '' + + """Below outputs are for rst.""" + + def image_link(self, url, target, alt): + """image_link""" + return '\n'.join([ + '', + '.. image:: {}'.format(url), + ' :target: {}'.format(target), + ' :alt: {}'.format(alt), + '', + ]) + + def rest_role(self, text): + """rest_role""" + return text + + def rest_link(self, text): + """rest_link""" + return text + + def inline_math(self, math): + """Extension of recommonmark""" + return re.sub(r'\$(.*?)\$', + lambda x: '\ :math:`{}`\ '.format(x.group(1)), math) + + def eol_literal_marker(self, marker): + """Extension of recommonmark""" + return marker + + def directive(self, text): + """directive""" + return '\n' + text + '\n' + + def rest_code_block(self): + """rest_code_block""" + return '\n\n' + + +class M2R(mistune.Markdown): + """M2R""" + + def __init__(self, + renderer=None, + inline=RestInlineLexer, + block=RestBlockLexer, + **kwargs): + if renderer is None: + renderer = RestRenderer(**kwargs) + super(M2R, self).__init__( + renderer, inline=inline, block=block, **kwargs) + + def parse(self, text): + """parse""" + output = super(M2R, self).parse(text) + return self.post_process(output) + + def output_directive(self): + """output_directive""" + return self.renderer.directive(self.token['text']) + + def output_rest_code_block(self): + """output_rest_code_block""" + return self.renderer.rest_code_block() + + def post_process(self, text): + """post_process""" + output = (text.replace('\\ \n', '\n').replace('\n\\ ', '\n') + .replace(' \\ ', ' ').replace('\\ ', ' ') + .replace('\\ .', '.')) + if self.renderer._include_raw_html: + return prolog + output + else: + return output + + +class M2RParser(rst.Parser, object): + """M2RParser""" + # Explicitly tell supported formats to sphinx + supported = ('markdown', 'md', 'mkd') + + def parse(self, inputstrings, document): + """parse""" + if isinstance(inputstrings, statemachine.StringList): + inputstring = '\n'.join(inputstrings) + else: + inputstring = inputstrings + config = document.settings.env.config + converter = M2R(no_underscore_emphasis=config.no_underscore_emphasis, + parse_relative_links=config.m2r_parse_relative_links, + anonymous_references=config.m2r_anonymous_references, + disable_inline_math=config.m2r_disable_inline_math) + super(M2RParser, self).parse(converter(inputstring), document) + + +class MdInclude(rst.Directive): + """Directive class to include markdown in sphinx. + + Load a file and convert it to rst and insert as a node. Currently + directive-specific options are not implemented. + """ + required_arguments = 1 + optional_arguments = 0 + option_spec = { + 'start-line': int, + 'end-line': int, + } + + def run(self): + """Most of this method is from ``docutils.parser.rst.Directive``. + + docutils version: 0.12 + """ + if not self.state.document.settings.file_insertion_enabled: + raise self.warning('"%s" directive disabled.' % self.name) + source = self.state_machine.input_lines.source( + self.lineno - self.state_machine.input_offset - 1) + source_dir = os.path.dirname(os.path.abspath(source)) + path = rst.directives.path(self.arguments[0]) + path = os.path.normpath(os.path.join(source_dir, path)) + path = utils.relative_path(None, path) + path = nodes.reprunicode(path) + + # get options (currently not use directive-specific options) + encoding = self.options.get('encoding', + self.state.document.settings.input_encoding) + e_handler = self.state.document.settings.input_encoding_error_handler + tab_width = self.options.get('tab-width', + self.state.document.settings.tab_width) + + # open the including file + try: + self.state.document.settings.record_dependencies.add(path) + include_file = io.FileInput( + source_path=path, encoding=encoding, error_handler=e_handler) + except UnicodeEncodeError as error: + raise self.severe('Problems with "%s" directive path:\n' + 'Cannot encode input file path "%s" ' + '(wrong locale?).' % + (self.name, SafeString(path))) + except IOError as error: + raise self.severe('Problems with "%s" directive path:\n%s.' % + (self.name, ErrorString(error))) + + # read from the file + startline = self.options.get('start-line', None) + endline = self.options.get('end-line', None) + try: + if startline or (endline is not None): + lines = include_file.readlines() + rawtext = ''.join(lines[startline:endline]) + else: + rawtext = include_file.read() + except UnicodeError as error: + raise self.severe('Problem with "%s" directive:\n%s' % + (self.name, ErrorString(error))) + + config = self.state.document.settings.env.config + converter = M2R(no_underscore_emphasis=config.no_underscore_emphasis, + parse_relative_links=config.m2r_parse_relative_links, + anonymous_references=config.m2r_anonymous_references, + disable_inline_math=config.m2r_disable_inline_math) + include_lines = statemachine.string2lines( + converter(rawtext), tab_width, convert_whitespace=True) + self.state_machine.insert_input(include_lines, path) + return [] + + +def setup(app): + """When used for sphinx extension.""" + global _is_sphinx + _is_sphinx = True + app.add_config_value('no_underscore_emphasis', False, 'env') + app.add_config_value('m2r_parse_relative_links', False, 'env') + app.add_config_value('m2r_anonymous_references', False, 'env') + app.add_config_value('m2r_disable_inline_math', False, 'env') + app.add_source_parser('.md', M2RParser) + app.add_directive('mdinclude', MdInclude) + metadata = dict( + version=__version__, + parallel_read_safe=True, + parallel_write_safe=True, ) + return metadata + + +def convert(text, **kwargs): + """convert""" + return M2R(**kwargs)(text) + + +def parse_from_file(file, encoding='utf-8', **kwargs): + """parse_from_file""" + if not os.path.exists(file): + raise OSError('No such file exists: {}'.format(file)) + with _open(file, encoding=encoding) as f: + src = f.read() + output = convert(src, **kwargs) + return output + + +def save_to_file(file, src, encoding='utf-8', **kwargs): + """save_to_file""" + target = os.path.splitext(file)[0] + '.rst' + if not options.overwrite and os.path.exists(target): + confirm = input('{} already exists. overwrite it? [y/n]: '.format( + target)) + if confirm.upper() not in ('Y', 'YES'): + print('skip {}'.format(file)) + return + with _open(target, 'w', encoding=encoding) as f: + f.write(src) + + +def main(): + """main""" + parse_options() # parse cli options + if not options.input_file: + parser.print_help() + parser.exit(0) + for file in options.input_file: + output = parse_from_file(file) + if options.dry_run: + print(output) + else: + save_to_file(file, output) + + +if __name__ == '__main__': + main() diff --git a/doc/requirements.txt b/doc/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..1560ebc5f9d74fbae773ac5bc45c5b42b044287a --- /dev/null +++ b/doc/requirements.txt @@ -0,0 +1,4 @@ +sphinx==2.1.0 +mistune +sphinx_rtd_theme +paddlepaddle>=1.6 diff --git a/go/client_app/imdb_client.go b/go/client_app/imdb_client.go index 079ddbbda50ce159b29b9835f947a47ce7d47791..aef823ed2c5209217d4f60f93d19006e67dca35d 100644 --- a/go/client_app/imdb_client.go +++ b/go/client_app/imdb_client.go @@ -28,7 +28,7 @@ func main() { var config_file_path string config_file_path = os.Args[1] handle := serving_client.LoadModelConfig(config_file_path) - handle = serving_client.Connect("127.0.0.1", "9393", handle) + handle = serving_client.Connect("127.0.0.1", "9292", handle) test_file_path := os.Args[2] fi, err := os.Open(test_file_path) diff --git a/python/examples/imdb/benchmark_batch.py b/python/examples/imdb/benchmark_batch.py index d36704a7631e963fd51220aa3c3d9a350515ebfd..99b8ec56ca74e72cb58d81f3a55b0fe7c19e4902 100644 --- a/python/examples/imdb/benchmark_batch.py +++ b/python/examples/imdb/benchmark_batch.py @@ -61,4 +61,7 @@ def single_func(idx, resource): multi_thread_runner = MultiThreadRunner() result = multi_thread_runner.run(single_func, args.thread, {}) -print(result) +avg_cost = 0 +for cost in result[0]: + avg_cost += cost +print("total cost of each thread".format(avg_cost / args.thread)) diff --git a/python/paddle_serving_client/__init__.py b/python/paddle_serving_client/__init__.py index f3d6a9a661e494bbf8f3ea9995c8e9139fd102d5..ef1c2bfbfb63d40914bd5109380b96a607fc38e9 100644 --- a/python/paddle_serving_client/__init__.py +++ b/python/paddle_serving_client/__init__.py @@ -93,7 +93,7 @@ class Client(object): lib_path = os.path.dirname(paddle_serving_client.__file__) client_path = os.path.join(lib_path, 'serving_client.so') lib_path = os.path.join(lib_path, 'lib') - os.popen('patchelf --set-rpath {} {}'.format(lib_path, client_path)) + os.system('patchelf --set-rpath {} {}'.format(lib_path, client_path)) def load_client_config(self, path): from .serving_client import PredictorClient diff --git a/python/paddle_serving_client/version.py b/python/paddle_serving_client/version.py index e65b5b17784307b7121a0ec86c810612a78ff4b2..99322ee8280a66a54371b296905d54f0766b016d 100644 --- a/python/paddle_serving_client/version.py +++ b/python/paddle_serving_client/version.py @@ -12,6 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. """ Paddle Serving Client version string """ -serving_client_version = "0.1.3" -serving_server_version = "0.1.3" -module_proto_version = "0.1.3" +serving_client_version = "0.2.0" +serving_server_version = "0.2.0" +module_proto_version = "0.2.0" diff --git a/python/paddle_serving_server/__init__.py b/python/paddle_serving_server/__init__.py index d893861e2b0cc1615701191a66aa6ff0bcb53305..08f3febc14ecd0d3c3cde7dc54f17bd143f9d5b3 100644 --- a/python/paddle_serving_server/__init__.py +++ b/python/paddle_serving_server/__init__.py @@ -211,6 +211,7 @@ class Server(object): tar_name = floder_name + ".tar.gz" bin_url = "https://paddle-serving.bj.bcebos.com/bin/" + tar_name self.server_path = os.path.join(self.module_path, floder_name) + if not os.path.exists(self.server_path): print('Frist time run, downloading PaddleServing components ...') r = os.system('wget ' + bin_url + ' --no-check-certificate') diff --git a/python/paddle_serving_server/version.py b/python/paddle_serving_server/version.py index e65b5b17784307b7121a0ec86c810612a78ff4b2..99322ee8280a66a54371b296905d54f0766b016d 100644 --- a/python/paddle_serving_server/version.py +++ b/python/paddle_serving_server/version.py @@ -12,6 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. """ Paddle Serving Client version string """ -serving_client_version = "0.1.3" -serving_server_version = "0.1.3" -module_proto_version = "0.1.3" +serving_client_version = "0.2.0" +serving_server_version = "0.2.0" +module_proto_version = "0.2.0" diff --git a/python/paddle_serving_server_gpu/__init__.py b/python/paddle_serving_server_gpu/__init__.py index 3dd330b18921c81cf17601ff7e52d860f0322f95..6f0ece74eeccc40eaf9676738e15e7b52b9da9ce 100644 --- a/python/paddle_serving_server_gpu/__init__.py +++ b/python/paddle_serving_server_gpu/__init__.py @@ -20,6 +20,7 @@ import google.protobuf.text_format import tarfile import socket import paddle_serving_server_gpu as paddle_serving_server +import time from .version import serving_server_version from contextlib import closing import argparse @@ -115,6 +116,7 @@ class Server(object): self.reload_interval_s = 10 self.module_path = os.path.dirname(paddle_serving_server.__file__) self.cur_path = os.getcwd() + self.check_cuda self.use_local_bin = False self.gpuid = 0 @@ -141,6 +143,13 @@ class Server(object): self.use_local_bin = True self.bin_path = os.environ["SERVING_BIN"] + def check_cuda(self): + r = os.system("whereis cuda") + if r != 0: + raise SystemExit( + "CUDA not found, please check your environment or use cpu version by \"pip install paddle_serving_server\"" + ) + def set_gpuid(self, gpuid=0): self.gpuid = gpuid @@ -215,11 +224,21 @@ class Server(object): os.chdir(self.module_path) need_download = False device_version = "serving-gpu-" - floder_name = device_version + serving_server_version - tar_name = floder_name + ".tar.gz" + folder_name = device_version + serving_server_version + tar_name = folder_name + ".tar.gz" bin_url = "https://paddle-serving.bj.bcebos.com/bin/" + tar_name - self.server_path = os.path.join(self.module_path, floder_name) + self.server_path = os.path.join(self.module_path, folder_name) + + download_flag = "{}/{}.is_download".format(self.module_path, + folder_name) + if os.path.exists(download_flag): + os.chdir(self.cur_path) + self.bin_path = self.server_path + "/serving" + return + if not os.path.exists(self.server_path): + os.system("touch {}/{}.is_download".format(self.module_path, + folder_name)) print('Frist time run, downloading PaddleServing components ...') r = os.system('wget ' + bin_url + ' --no-check-certificate') if r != 0: @@ -318,4 +337,8 @@ class Server(object): self.gpuid,) print("Going to Run Comand") print(command) + # wait for other process to download server bin + while not os.path.exists(self.server_path): + time.sleep(1) + os.system(command) diff --git a/python/paddle_serving_server_gpu/version.py b/python/paddle_serving_server_gpu/version.py index e65b5b17784307b7121a0ec86c810612a78ff4b2..99322ee8280a66a54371b296905d54f0766b016d 100644 --- a/python/paddle_serving_server_gpu/version.py +++ b/python/paddle_serving_server_gpu/version.py @@ -12,6 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. """ Paddle Serving Client version string """ -serving_client_version = "0.1.3" -serving_server_version = "0.1.3" -module_proto_version = "0.1.3" +serving_client_version = "0.2.0" +serving_server_version = "0.2.0" +module_proto_version = "0.2.0" diff --git a/python/paddle_serving_server_gpu/web_service.py b/python/paddle_serving_server_gpu/web_service.py index db0db25d749728dc99dc1e65c278741d4b4bd5ae..5d507c9475047d6c7eb65a2b2c5799221cf194b5 100755 --- a/python/paddle_serving_server_gpu/web_service.py +++ b/python/paddle_serving_server_gpu/web_service.py @@ -66,6 +66,12 @@ class WebService(object): return server def _launch_rpc_service(self, service_idx): + if service_idx == 0: + self.rpc_service_list[service_idx].check_local_bin() + if not self.rpc_service_list[service_idx].use_local_bin: + self.rpc_service_list[service_idx].download_bin() + else: + time.sleep(3) self.rpc_service_list[service_idx].run_server() def prepare_server(self, workdir="", port=9393, device="gpu", gpuid=0): @@ -160,15 +166,6 @@ class WebService(object): if not isinstance(result, dict) and result == -1: result = {"result": "Request Value Error"} return result - ''' - feed, fetch = self.preprocess(request.json, request.json["fetch"]) - if "fetch" in feed: - del feed["fetch"] - fetch_map = client.predict(feed=feed, fetch=fetch) - fetch_map = self.postprocess( - feed=request.json, fetch=fetch, fetch_map=fetch_map) - return fetch_map - ''' app_instance.run(host="0.0.0.0", port=self.port, diff --git a/tools/serving_build.sh b/tools/serving_build.sh index fa7b98e4eb5dc470178360d0a7fbf81c2010a7af..14858bc710ba392ca1cc5e22dc2e14add5dee406 100644 --- a/tools/serving_build.sh +++ b/tools/serving_build.sh @@ -176,6 +176,7 @@ function python_run_criteo_ctr_with_cube() { local TYPE=$1 yum install -y bc >/dev/null cd criteo_ctr_with_cube # pwd: /Serving/python/examples/criteo_ctr_with_cube + export SERVING_BIN=${SERVING_WORKDIR}/build-server-${TYPE}/core/general-server/serving case $TYPE in CPU) check_cmd "wget https://paddle-serving.bj.bcebos.com/unittest/ctr_cube_unittest.tar.gz" @@ -191,6 +192,7 @@ function python_run_criteo_ctr_with_cube() { sh cube_prepare.sh & check_cmd "mkdir work_dir1 && cp cube/conf/cube.conf ./work_dir1/" python test_server.py ctr_serving_model_kv & + sleep 5 check_cmd "python test_client.py ctr_client_conf/serving_client_conf.prototxt ./ut_data >score" tail -n 2 score AUC=$(tail -n 2 score | awk 'NR==1') @@ -217,6 +219,7 @@ function python_run_criteo_ctr_with_cube() { sh cube_prepare.sh & check_cmd "mkdir work_dir1 && cp cube/conf/cube.conf ./work_dir1/" python test_server_gpu.py ctr_serving_model_kv & + sleep 5 check_cmd "python test_client.py ctr_client_conf/serving_client_conf.prototxt ./ut_data >score" tail -n 2 score | awk 'NR==1' AUC=$(tail -n 2 score | awk 'NR==1') @@ -235,6 +238,7 @@ function python_run_criteo_ctr_with_cube() { exit 1 ;; esac + unset SERVING_BIN echo "test criteo_ctr_with_cube $TYPE part finished as expected." cd .. # pwd: /Serving/python/examples }