{"componentChunkName":"component---src-templates-blog-detail-tsx","path":"/blog/2020-05-20-poems","result":{"data":{"currentBlog":{"id":"caebf2fd-ebd7-5972-a908-0ac7d00c5bd8","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/2020520/1589979656824-520.jpg","authors":["Anycodes"],"categories":["user-stories"],"date":"2020-05-20T00:00:00.000Z","title":"Serverless 的 AI 写诗，程序员浪漫起来谁能顶得住啊！","description":"本来来自 Serverless 社区成员的投稿，谢谢，有被撩到 :P","authorslink":["https://zhuanlan.zhihu.com/ServerlessGo"],"translators":null,"translatorslink":null,"tags":["深度学习","Serverless"],"keywords":"Serverless","outdated":true},"wordCount":{"words":172,"sentences":28,"paragraphs":28},"fileAbsolutePath":"/opt/build/repo/content/blog/2020-05-20-poems.md","fields":{"slug":"/blog/2020-05-20-poems/","keywords":["python","serverless","spa","云函数","model","古诗词","serverless","serverlesscloud"]},"html":"<p>古诗词是中国文化殿堂的瑰宝，记得曾经在韩国做 Exchange Student 的时候，看到他们学习我们的古诗词，有中文的还有翻译版的，自己发自内心的骄傲，甚至也会在某些时候背起一些耳熟能详的诗词。</p>\n<p>本文将会通过深度学习为我们生成一些古诗词，并将模型部署到 Serverless 架构上，实现基于 Serverless 的古诗词生成 API。</p>\n<p><img src=\"https://img.serverlesscloud.cn/2020520/1589979037720-%E6%9C%AA%E6%A0%87%E9%A2%98-1.jpg\"></p>\n<h2 id=\"项目构建\"><a href=\"#%E9%A1%B9%E7%9B%AE%E6%9E%84%E5%BB%BA\" aria-label=\"项目构建 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>项目构建</h2>\n<p>古诗词生成实际上是文本生成，或者说是生成式文本。关于基于深度学习的文本生成，最入门级的读物包括 Andrej Karpathy 的博客。他使用例子生动讲解了 Char-RNN (Character based Recurrent Neural Network) 如何用于从文本数据集里学习，然后自动生成像模像样的文本。</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/6-6-1.png\"></p>\n<p>上图直观展示了 Char-RNN 的原理。以要让模型学习写出「hello」为例，Char-RNN 的输入输出层都是以字符为单位。输入「h」，应该输出「e」；输入「e」，则应该输出后续的「l」。</p>\n<p>输入层我们可以用只有一个元素为1的向量来编码不同的字符，例如，「h」被编码为「1000」、「e」被编码为「0100」，而「l」被编码为「0010」。使用 RNN 的学习目标是，可以让生成的下一个字符尽量与训练样本里的目标输出一致。在图一的例子中，根据前两个字符产生的状态和第三个输入「l」预测出的下一个字符的向量为 &#x3C;0.1, 0.5, 1.9, -1.1>，最大的一维是第三维，对应的字符则为「0010」，正好是「l」。这就是一个正确的预测。但从第一个「h」得到的输出向量是第四维最大，对应的并不是「e」，这样就产生代价。</p>\n<p>学习的过程就是不断降低这个代价。学习到的模型，对任何输入字符可以很好地不断预测下一个字符，如此一来就能生成句子或段落。</p>\n<p>本文项目构建参考了 Github 已有项目：<a href=\"https://github.com/norybaby/poet\">https://github.com/norybaby/poet</a></p>\n<p>通过 Clone 代码，并且安装相关依赖：</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">pip3 install tensorflow==1.14 word2vec numpy</code></pre></div>\n<p>通过训练：</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">python3 train.py</code></pre></div>\n<p>可以看到训练结果：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/6-6-3.png\"></p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/6-6-4.png\"></p>\n<p>此时会生成多个模型在 output_poem 文件夹下，我们只需要保留最好的即可，例如我的训练之后生成的 json 文件：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"67436344642343340000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`{\n  &quot;best_model&quot;: &quot;output_poem/best_model/model-20390&quot;,\n  &quot;best_valid_ppl&quot;: 21.441762924194336,\n  &quot;latest_model&quot;: &quot;output_poem/save_model/model-20390&quot;,\n  &quot;params&quot;: {\n    &quot;batch_size&quot;: 16,\n    &quot;cell_type&quot;: &quot;lstm&quot;,\n    &quot;dropout&quot;: 0.0,\n    &quot;embedding_size&quot;: 128,\n    &quot;hidden_size&quot;: 128,\n    &quot;input_dropout&quot;: 0.0,\n    &quot;learning_rate&quot;: 0.005,\n    &quot;max_grad_norm&quot;: 5.0,\n    &quot;num_layers&quot;: 2,\n    &quot;num_unrollings&quot;: 64\n  },\n  &quot;test_ppl&quot;: 25.83984375\n}`, `67436344642343340000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"json\"><pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n  <span class=\"token property\">\"best_model\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"output_poem/best_model/model-20390\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"best_valid_ppl\"</span><span class=\"token operator\">:</span> <span class=\"token number\">21.441762924194336</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"latest_model\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"output_poem/save_model/model-20390\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"params\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token property\">\"batch_size\"</span><span class=\"token operator\">:</span> <span class=\"token number\">16</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"cell_type\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"lstm\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"dropout\"</span><span class=\"token operator\">:</span> <span class=\"token number\">0.0</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"embedding_size\"</span><span class=\"token operator\">:</span> <span class=\"token number\">128</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"hidden_size\"</span><span class=\"token operator\">:</span> <span class=\"token number\">128</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"input_dropout\"</span><span class=\"token operator\">:</span> <span class=\"token number\">0.0</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"learning_rate\"</span><span class=\"token operator\">:</span> <span class=\"token number\">0.005</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"max_grad_norm\"</span><span class=\"token operator\">:</span> <span class=\"token number\">5.0</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"num_layers\"</span><span class=\"token operator\">:</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"num_unrollings\"</span><span class=\"token operator\">:</span> <span class=\"token number\">64</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"test_ppl\"</span><span class=\"token operator\">:</span> <span class=\"token number\">25.83984375</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>此时，我只需要保存 <code class=\"language-text\">output_poem/best_model/model-20390</code> 模型即可。</p>\n<h2 id=\"部署上线\"><a href=\"#%E9%83%A8%E7%BD%B2%E4%B8%8A%E7%BA%BF\" aria-label=\"部署上线 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>部署上线</h2>\n<p>在项目目录下，安装必要依赖：</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">pip3 install word2vec numpy -t ./</code></pre></div>\n<p>由于 Tensorflow 等是腾讯云云函数内置的package，所以这里无需安装，另外 numpy 这个 package 需要在 CentOS+Python3.6 环境下打包。也可以通过之前制作的小工具打包：<a href=\"https://www.serverlesschina.com/35.html\">https://www.serverlesschina.com/35.html</a></p>\n<p>完成之后，编写函数入口文件：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"1722822693136794000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`import uuid, json\nfrom write_poem import WritePoem, start_model\n\nwriter = start_model()\n\n\ndef return_msg(error, msg):\n    return_data = {\n        &quot;uuid&quot;: str(uuid.uuid1()),\n        &quot;error&quot;: error,\n        &quot;message&quot;: msg\n    }\n    print(return_data)\n    return return_data\n\n\ndef main_handler(event, context):\n    # 类型\n    # 1： 自由\n    # 2： 押韵\n    # 3： 藏头押韵\n    # 4： 藏字押韵\n\n    style = json.loads(event[&quot;body&quot;])[&quot;style&quot;]\n    content = json.loads(event[&quot;body&quot;]).get(&quot;content&quot;, None)\n\n    if style in '34' and not content:\n        return return_msg(True, &quot;请输入content参数&quot;)\n\n    if style == '1':\n        return return_msg(False, writer.free_verse())\n    elif style == '2':\n        return return_msg(False, writer.rhyme_verse())\n    elif style == '3':\n        return return_msg(False, writer.cangtou(content))\n    elif style == '4':\n        return return_msg(False, writer.hide_words(content))\n    else:\n        return return_msg(True, &quot;请输入正确的style参数&quot;)`, `1722822693136794000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">import</span> uuid<span class=\"token punctuation\">,</span> json\n<span class=\"token keyword\">from</span> write_poem <span class=\"token keyword\">import</span> WritePoem<span class=\"token punctuation\">,</span> start_model\n\nwriter <span class=\"token operator\">=</span> start_model<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">return_msg</span><span class=\"token punctuation\">(</span>error<span class=\"token punctuation\">,</span> msg<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    return_data <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token string\">\"uuid\"</span><span class=\"token punctuation\">:</span> <span class=\"token builtin\">str</span><span class=\"token punctuation\">(</span>uuid<span class=\"token punctuation\">.</span>uuid1<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string\">\"error\"</span><span class=\"token punctuation\">:</span> error<span class=\"token punctuation\">,</span>\n        <span class=\"token string\">\"message\"</span><span class=\"token punctuation\">:</span> msg\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>return_data<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">return</span> return_data\n\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">main_handler</span><span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">,</span> context<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token comment\"># 类型</span>\n    <span class=\"token comment\"># 1： 自由</span>\n    <span class=\"token comment\"># 2： 押韵</span>\n    <span class=\"token comment\"># 3： 藏头押韵</span>\n    <span class=\"token comment\"># 4： 藏字押韵</span>\n\n    style <span class=\"token operator\">=</span> json<span class=\"token punctuation\">.</span>loads<span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">\"body\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"style\"</span><span class=\"token punctuation\">]</span>\n    content <span class=\"token operator\">=</span> json<span class=\"token punctuation\">.</span>loads<span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">\"body\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">\"content\"</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">None</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">if</span> style <span class=\"token keyword\">in</span> <span class=\"token string\">'34'</span> <span class=\"token keyword\">and</span> <span class=\"token keyword\">not</span> content<span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">return</span> return_msg<span class=\"token punctuation\">(</span><span class=\"token boolean\">True</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"请输入content参数\"</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">if</span> style <span class=\"token operator\">==</span> <span class=\"token string\">'1'</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">return</span> return_msg<span class=\"token punctuation\">(</span><span class=\"token boolean\">False</span><span class=\"token punctuation\">,</span> writer<span class=\"token punctuation\">.</span>free_verse<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">elif</span> style <span class=\"token operator\">==</span> <span class=\"token string\">'2'</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">return</span> return_msg<span class=\"token punctuation\">(</span><span class=\"token boolean\">False</span><span class=\"token punctuation\">,</span> writer<span class=\"token punctuation\">.</span>rhyme_verse<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">elif</span> style <span class=\"token operator\">==</span> <span class=\"token string\">'3'</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">return</span> return_msg<span class=\"token punctuation\">(</span><span class=\"token boolean\">False</span><span class=\"token punctuation\">,</span> writer<span class=\"token punctuation\">.</span>cangtou<span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">elif</span> style <span class=\"token operator\">==</span> <span class=\"token string\">'4'</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">return</span> return_msg<span class=\"token punctuation\">(</span><span class=\"token boolean\">False</span><span class=\"token punctuation\">,</span> writer<span class=\"token punctuation\">.</span>hide_words<span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">else</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">return</span> return_msg<span class=\"token punctuation\">(</span><span class=\"token boolean\">True</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"请输入正确的style参数\"</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>同时需要准备好 Yaml 文件：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"63968666986756290000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`getUserIp:\n  component: &quot;@serverless/tencent-scf&quot;\n  inputs:\n    name: autoPoem\n    codeUri: ./\n    exclude:\n      - .gitignore\n      - .git/**\n      - .serverless\n      - .env\n    handler: index.main_handler\n    runtime: Python3.6\n    region: ap-beijing\n    description: 自动古诗词撰写\n    namespace: serverless_tools\n    memorySize: 512\n    timeout: 10\n    events:\n      - apigw:\n          name: serverless\n          parameters:\n            serviceId: service-8d3fi753\n            protocols:\n              - http\n              - https\n            environment: release\n            endpoints:\n              - path: /auto/poem\n                description: 自动古诗词撰写\n                method: POST\n                enableCORS: true`, `63968666986756290000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"yaml\"><pre class=\"language-yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">getUserIp</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">component</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"@serverless/tencent-scf\"</span>\n  <span class=\"token key atrule\">inputs</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> autoPoem\n    <span class=\"token key atrule\">codeUri</span><span class=\"token punctuation\">:</span> ./\n    <span class=\"token key atrule\">exclude</span><span class=\"token punctuation\">:</span>\n      <span class=\"token punctuation\">-</span> .gitignore\n      <span class=\"token punctuation\">-</span> .git/**\n      <span class=\"token punctuation\">-</span> .serverless\n      <span class=\"token punctuation\">-</span> .env\n    <span class=\"token key atrule\">handler</span><span class=\"token punctuation\">:</span> index.main_handler\n    <span class=\"token key atrule\">runtime</span><span class=\"token punctuation\">:</span> Python3.6\n    <span class=\"token key atrule\">region</span><span class=\"token punctuation\">:</span> ap<span class=\"token punctuation\">-</span>beijing\n    <span class=\"token key atrule\">description</span><span class=\"token punctuation\">:</span> 自动古诗词撰写\n    <span class=\"token key atrule\">namespace</span><span class=\"token punctuation\">:</span> serverless_tools\n    <span class=\"token key atrule\">memorySize</span><span class=\"token punctuation\">:</span> <span class=\"token number\">512</span>\n    <span class=\"token key atrule\">timeout</span><span class=\"token punctuation\">:</span> <span class=\"token number\">10</span>\n    <span class=\"token key atrule\">events</span><span class=\"token punctuation\">:</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">apigw</span><span class=\"token punctuation\">:</span>\n          <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> serverless\n          <span class=\"token key atrule\">parameters</span><span class=\"token punctuation\">:</span>\n            <span class=\"token key atrule\">serviceId</span><span class=\"token punctuation\">:</span> service<span class=\"token punctuation\">-</span>8d3fi753\n            <span class=\"token key atrule\">protocols</span><span class=\"token punctuation\">:</span>\n              <span class=\"token punctuation\">-</span> http\n              <span class=\"token punctuation\">-</span> https\n            <span class=\"token key atrule\">environment</span><span class=\"token punctuation\">:</span> release\n            <span class=\"token key atrule\">endpoints</span><span class=\"token punctuation\">:</span>\n              <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">path</span><span class=\"token punctuation\">:</span> /auto/poem\n                <span class=\"token key atrule\">description</span><span class=\"token punctuation\">:</span> 自动古诗词撰写\n                <span class=\"token key atrule\">method</span><span class=\"token punctuation\">:</span> POST\n                <span class=\"token key atrule\">enableCORS</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span></code></pre></div>\n<p>此时，我们就可以通过 Serverless Framework CLI 部署项目。部署完成之后，我们可以通过 PostMan 测试我们的接口：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/6-6-6.png\"></p>\n<h2 id=\"总结\"><a href=\"#%E6%80%BB%E7%BB%93\" aria-label=\"总结 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>总结</h2>\n<p>本文通过已有的深度学习项目，在本地进行训练，保存模型，然后将项目部署在腾讯云云函数上，通过与 API 网关的联动，实现了一个基于深度学习的古诗词撰写的 API。</p>\n<p><img src=\"https://img.serverlesscloud.cn/2020520/1589975505211-IMG_1279.jpg\" alt=\"运行结果\"></p>\n<hr>\n<div id='scf-deploy-iframe-or-md'></div>\n<hr>\n<blockquote>\n<p><strong>传送门：</strong></p>\n<ul>\n<li>GitHub: <a href=\"https://github.com/serverless/serverless/blob/master/README_CN.md\">github.com/serverless</a></li>\n<li>官网：<a href=\"https://serverless.com/\">serverless.com</a></li>\n</ul>\n</blockquote>\n<p>欢迎访问：<a href=\"https://serverlesscloud.cn/\">Serverless 中文网</a>，您可以在 <a href=\"https://serverlesscloud.cn/best-practice\">最佳实践</a> 里体验更多关于 Serverless 应用的开发！</p>","tableOfContents":"<ul>\n<li><a href=\"/blog/2020-05-20-poems/#%E9%A1%B9%E7%9B%AE%E6%9E%84%E5%BB%BA\">项目构建</a></li>\n<li><a href=\"/blog/2020-05-20-poems/#%E9%83%A8%E7%BD%B2%E4%B8%8A%E7%BA%BF\">部署上线</a></li>\n<li><a href=\"/blog/2020-05-20-poems/#%E6%80%BB%E7%BB%93\">总结</a></li>\n</ul>"},"previousBlog":{"id":"a76c7573-dd0d-58ca-b60e-10642b13690f","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/2020720/1595233426309-1589442691416-%E6%B5%B7%E6%8A%A5%281%29-sketch_%E5%89%AF%E6%9C%AC%20%281%29.jpg","authors":["Serverless 社区"],"categories":["meetup"],"date":"2020-05-22T00:00:00.000Z","title":"Serverless 应用级监控能力 + SSR｜在线分享第二期","description":"本期直播，腾讯云高级产品经理将为您揭秘 Serverless 应用级监控能力的详细设计思路与应用","authorslink":["https://zhuanlan.zhihu.com/ServerlessGo"],"translators":null,"translatorslink":null,"tags":["Serverless","Meetup"],"keywords":"Serverless;Serverless监控","outdated":null},"wordCount":{"words":65,"sentences":9,"paragraphs":9},"fileAbsolutePath":"/opt/build/repo/content/blog/2020-05-22-ssr-dashboard-meetup.md","fields":{"slug":"/blog/2020-05-22-ssr-dashboard-meetup/","keywords":["serverless","Serverless","serverless","监控","serverlesscloud","应用","腾讯"]}},"nextBlog":{"id":"7cdbd3fc-5cc1-50eb-a9ac-21fb5de1cfeb","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/2020512/1589268598969-haibao.jpg","authors":["Serverless 社区"],"categories":["news"],"date":"2020-05-12T00:00:00.000Z","title":"大咖集结 | 首届 ServerlessDays · China 嘉宾阵容曝光","description":"大会不仅有 ServerlessDays 组织者 Ant Stanley、Serverless 白皮书作者 Johann Schleier-Smith 等全球顶级意见领袖分享 Serverless 前瞻，也有 Google、IBM、腾讯云等国内外一线厂商带来 Serverless 技术新风向，更有 BBC、滴滴、爱奇艺等企业的最佳实践指导！","authorslink":["https://zhuanlan.zhihu.com/ServerlessGo"],"translators":null,"translatorslink":null,"tags":["ServerlessDays","Meetup"],"keywords":"Serverless,ServerlessDays,ServerlessChina","outdated":null},"wordCount":{"words":84,"sentences":13,"paragraphs":13},"fileAbsolutePath":"/opt/build/repo/content/blog/2020-05-12-serverlessdays-poster.md","fields":{"slug":"/blog/2020-05-12-serverlessdays-poster/","keywords":["serverless","云原生","Serverless","ServerlessDays","serverless","serverlesscloud","技术"]}},"recommendBlogs":{"edges":[{"node":{"id":"4300b21c-7209-5256-86ff-0d38e3daec9b","frontmatter":{"thumbnail":"https://main.qcloudimg.com/raw/14f1c8eed372e76c1b139703b2f6d0fa.jpg","authors":["KieranMcCarthy"],"categories":["user-stories","engineering-culture"],"date":"2018-01-09T00:00:00.000Z","title":"我是如何在四年时间里，从厨师转行为 Serverless 应用开发者","description":"我是厨师出身，现在成为了一名 Serverless 应用开发者。","authorslink":["https://serverless.com/author/kieranmccarthy/"],"translators":["Aceyclee"],"translatorslink":["https://www.zhihu.com/people/Aceyclee"],"tags":["应用开发","Serverless"],"keywords":"Serverless 应用开发,Serverless 管理,厨师转行为 Serverless 应用开发者","outdated":null},"wordCount":{"words":285,"sentences":38,"paragraphs":36},"fileAbsolutePath":"/opt/build/repo/content/blog/2018-01-09-from-chef-to-serverless-developer-in-4-years.md","fields":{"slug":"/blog/2018-01-09-from-chef-to-serverless-developer-in-4-years/","keywords":["无服务器","无服务器开发","云函数","学习","Serverless","构建","Framework","开发者","服务器","应用","学位","简历"]}}},{"node":{"id":"713a0563-4bf9-5721-bacb-3b4ef609fe4a","frontmatter":{"thumbnail":"https://s3-us-west-2.amazonaws.com/assets.blog.serverless.com/camp-fire/camp-fire-housing-thumb.jpg","authors":["EricWyne"],"categories":["guides-and-tutorials","user-stories"],"date":"2018-12-05T00:00:00.000Z","title":"Serverless Twitter 机器人帮助为坎普山火受灾者安置住房","description":"加利福尼亚州的坎普山火致使数千人流离失所，为此，我构建了一个简单的 Serverless Twitter 机器人来帮助将受灾者安置在临时住房！","authorslink":["https://serverless.com/author/ericwyne/"],"translators":["Aceyclee"],"translatorslink":["zhihu.com/people/Aceyclee"],"tags":null,"keywords":null,"outdated":null},"wordCount":{"words":157,"sentences":26,"paragraphs":26},"fileAbsolutePath":"/opt/build/repo/content/blog/2018-12-05-serverless-twitter-camp-fire.md","fields":{"slug":"/blog/2018-12-05-serverless-twitter-camp-fire/","keywords":["serverless","无服务器","云函数","Serverless","org","住房","Twitter","函数","受灾","机器人","山火"]}}},{"node":{"id":"98602143-b837-5f50-a24f-3b1ec76044d7","frontmatter":{"thumbnail":"https://s3-us-west-2.amazonaws.com/assets.blog.serverless.com/sqquid/sqquid-serverless-thumb.jpg","authors":["RonPeled"],"categories":["user-stories"],"date":"2018-12-17T00:00:00.000Z","title":"SQQUID：100% 无服务器初创公司","description":"SQQUID 将 AWS Lambda 和无服务器框架用于其核心产品和营销网站。我们来看看一个完全无服务器的初创公司是怎样的。","authorslink":null,"translators":null,"translatorslink":null,"tags":null,"keywords":null,"outdated":null},"wordCount":{"words":266,"sentences":42,"paragraphs":42},"fileAbsolutePath":"/opt/build/repo/content/blog/2018-12-17-sqquid-one-hundred-percent-serverless.md","fields":{"slug":"/blog/2018-12-17-sqquid-one-hundred-percent-serverless/","keywords":["go","serverless","无服务器","无服务器架构","服务器","架构","Lambda","集成","FaaS","串行","系统"]}}},{"node":{"id":"29dc2e58-d2ba-56f9-aee1-d21b0bc62e0e","frontmatter":{"thumbnail":"https://s3-us-west-2.amazonaws.com/assets.blog.serverless.com/ao-com-story/ao-serverless-thumbnail.png","authors":["NickGottlieb"],"categories":["user-stories"],"date":"2019-04-24T00:00:00.000Z","title":"AO.com：逐渐转向无服务器优先","description":"AO.com 的 SCV 团队率先尝试无服务器服务。折服于无服务器框架的快速周转时间和低维护成本，整个团队逐渐转向无服务器优先。","authorslink":null,"translators":null,"translatorslink":null,"tags":null,"keywords":null,"outdated":null},"wordCount":{"words":236,"sentences":42,"paragraphs":35},"fileAbsolutePath":"/opt/build/repo/content/blog/2019-04-24-ao-serverless-first.md","fields":{"slug":"/blog/2019-04-24-ao-serverless-first/","keywords":["serverless","无服务器","服务器","团队","Lambda","功能","构建"]}}},{"node":{"id":"752d08d1-387a-5bde-acf3-98141baab294","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/2020414/1586871710979-%E5%85%AC%E5%85%B1%E7%94%A8.png","authors":["Anycodes"],"categories":["user-stories"],"date":"2019-06-20T00:00:00.000Z","title":"如何用 Serverless 为 Python 云函数打包依赖","description":"在使用无服务器云函数SCF时通常会遇到导入第三方库的问题，很多小伙伴比较头疼是：应该如何打包进去？这里，推荐几个不错的方法。","authorslink":["https://zhuanlan.zhihu.com/ServerlessGo"],"translators":null,"translatorslink":null,"tags":["云函数","Serverless"],"keywords":"Serverless,Serverless应用,无服务器云函数","outdated":null},"wordCount":{"words":81,"sentences":43,"paragraphs":43},"fileAbsolutePath":"/opt/build/repo/content/blog/2019-06-20-for-python-cloud-functions.md","fields":{"slug":"/blog/2019-06-20-for-python-cloud-functions/","keywords":["java","serverless","无服务器","无服务器云函数","云函数","serverlesscloud","安装","serverless","pillowtest"]}}},{"node":{"id":"2dc78814-9d77-555b-a1bb-ad202c8ec2d1","frontmatter":{"thumbnail":"https://s3-us-west-2.amazonaws.com/assets.blog.serverless.com/cloudforecast/thumbnail.png","authors":["FrancoisLagier"],"categories":["user-stories"],"date":"2019-08-07T00:00:00.000Z","title":"Serverless：初创企业的理想选择？（CloudForecast 案例分析）","description":"CloudForecast 是 2018 年成立的一家独立初创企业，本文将介绍他们决定选择 Serverless 的原因。","authorslink":["https://serverless.com/author/francoislagier/"],"translators":["Aceyclee"],"translatorslink":["zhihu.com/people/Aceyclee"],"tags":null,"keywords":null,"outdated":null},"wordCount":{"words":211,"sentences":29,"paragraphs":29},"fileAbsolutePath":"/opt/build/repo/content/blog/2019-08-07-serverless-for-startups.md","fields":{"slug":"/blog/2019-08-07-serverless-for-startups/","keywords":["serverless","云函数","serverless","函数","Serverless","utm","Framework","blog","CloudForecast","cloudforecast"]}}},{"node":{"id":"97450b07-658b-5207-8216-1c7b9b51b115","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/2020114/1578988490344-v2-8b2cd2c5275aa2c5a3c5083a148a7a9f_1200x500.jpg","authors":["Anycodes"],"categories":["user-stories"],"date":"2019-09-01T00:00:00.000Z","title":"如何通过 Serverless 与自然语言处理，让搜索引擎「看」到你的博客","description":"Serverless 与自然语言处理结合的一个小应用","authorslink":["https://www.zhihu.com/people/liuyu-43-97"],"translators":null,"translatorslink":null,"tags":["个人博客","serverless"],"keywords":"Serverless 自然语言处理","outdated":null},"wordCount":{"words":106,"sentences":34,"paragraphs":34},"fileAbsolutePath":"/opt/build/repo/content/blog/2019-09-01-search-engine-blog.md","fields":{"slug":"/blog/2019-09-01-search-engine-blog/","keywords":["serverless","云函数","keywords","serverlesscloud","summary"]}}},{"node":{"id":"ae4fd2f8-515c-5aec-b584-38427ef33f7e","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/2020114/1578989800047-part-00492-780.jpg","authors":["Anycodes"],"categories":["guides-and-tutorials","user-stories"],"date":"2019-09-16T00:00:00.000Z","title":"突破传统 OJ 瓶颈，「判题姬」接入云函数","description":"通过 Serverless 实现在线编程","authorslink":["https://www.zhihu.com/people/liuyu-43-97"],"translators":null,"translatorslink":null,"tags":["在线编程","云函数"],"keywords":"Serverless 在线编程,Serverless OJ","outdated":null},"wordCount":{"words":169,"sentences":30,"paragraphs":30},"fileAbsolutePath":"/opt/build/repo/content/blog/2019-09-16-online-Judge.md","fields":{"slug":"/blog/2019-09-16-online-Judge/","keywords":["python","serverless","云函数","代码","函数","serverless"]}}}],"totalCount":64}},"pageContext":{"isCreatedByStatefulCreatePages":false,"blogId":"caebf2fd-ebd7-5972-a908-0ac7d00c5bd8","previousBlogId":"a76c7573-dd0d-58ca-b60e-10642b13690f","nextBlogId":"7cdbd3fc-5cc1-50eb-a9ac-21fb5de1cfeb","categories":["user-stories"]}}}