[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"similar-ShannonAI--service-streamer":3,"tool-ShannonAI--service-streamer":61},[4,18,26,36,44,53],{"id":5,"name":6,"github_repo":7,"description_zh":8,"stars":9,"difficulty_score":10,"last_commit_at":11,"category_tags":12,"status":17},4358,"openclaw","openclaw\u002Fopenclaw","OpenClaw 是一款专为个人打造的本地化 AI 助手，旨在让你在自己的设备上拥有完全可控的智能伙伴。它打破了传统 AI 助手局限于特定网页或应用的束缚，能够直接接入你日常使用的各类通讯渠道，包括微信、WhatsApp、Telegram、Discord、iMessage 等数十种平台。无论你在哪个聊天软件中发送消息，OpenClaw 都能即时响应，甚至支持在 macOS、iOS 和 Android 设备上进行语音交互，并提供实时的画布渲染功能供你操控。\n\n这款工具主要解决了用户对数据隐私、响应速度以及“始终在线”体验的需求。通过将 AI 部署在本地，用户无需依赖云端服务即可享受快速、私密的智能辅助，真正实现了“你的数据，你做主”。其独特的技术亮点在于强大的网关架构，将控制平面与核心助手分离，确保跨平台通信的流畅性与扩展性。\n\nOpenClaw 非常适合希望构建个性化工作流的技术爱好者、开发者，以及注重隐私保护且不愿被单一生态绑定的普通用户。只要具备基础的终端操作能力（支持 macOS、Linux 及 Windows WSL2），即可通过简单的命令行引导完成部署。如果你渴望拥有一个懂你",349277,3,"2026-04-06T06:32:30",[13,14,15,16],"Agent","开发框架","图像","数据工具","ready",{"id":19,"name":20,"github_repo":21,"description_zh":22,"stars":23,"difficulty_score":10,"last_commit_at":24,"category_tags":25,"status":17},3808,"stable-diffusion-webui","AUTOMATIC1111\u002Fstable-diffusion-webui","stable-diffusion-webui 是一个基于 Gradio 构建的网页版操作界面，旨在让用户能够轻松地在本地运行和使用强大的 Stable Diffusion 图像生成模型。它解决了原始模型依赖命令行、操作门槛高且功能分散的痛点，将复杂的 AI 绘图流程整合进一个直观易用的图形化平台。\n\n无论是希望快速上手的普通创作者、需要精细控制画面细节的设计师，还是想要深入探索模型潜力的开发者与研究人员，都能从中获益。其核心亮点在于极高的功能丰富度：不仅支持文生图、图生图、局部重绘（Inpainting）和外绘（Outpainting）等基础模式，还独创了注意力机制调整、提示词矩阵、负向提示词以及“高清修复”等高级功能。此外，它内置了 GFPGAN 和 CodeFormer 等人脸修复工具，支持多种神经网络放大算法，并允许用户通过插件系统无限扩展能力。即使是显存有限的设备，stable-diffusion-webui 也提供了相应的优化选项，让高质量的 AI 艺术创作变得触手可及。",162132,"2026-04-05T11:01:52",[14,15,13],{"id":27,"name":28,"github_repo":29,"description_zh":30,"stars":31,"difficulty_score":32,"last_commit_at":33,"category_tags":34,"status":17},1381,"everything-claude-code","affaan-m\u002Feverything-claude-code","everything-claude-code 是一套专为 AI 编程助手（如 Claude Code、Codex、Cursor 等）打造的高性能优化系统。它不仅仅是一组配置文件，而是一个经过长期实战打磨的完整框架，旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。\n\n通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能，everything-claude-code 能显著提升 AI 在复杂任务中的表现，帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略，使得模型响应更快、成本更低，同时有效防御潜在的攻击向量。\n\n这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库，还是需要 AI 协助进行安全审计与自动化测试，everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目，它融合了多语言支持与丰富的实战钩子（hooks），让 AI 真正成长为懂上",155373,2,"2026-04-14T11:34:08",[14,13,35],"语言模型",{"id":37,"name":38,"github_repo":39,"description_zh":40,"stars":41,"difficulty_score":32,"last_commit_at":42,"category_tags":43,"status":17},2271,"ComfyUI","Comfy-Org\u002FComfyUI","ComfyUI 是一款功能强大且高度模块化的视觉 AI 引擎，专为设计和执行复杂的 Stable Diffusion 图像生成流程而打造。它摒弃了传统的代码编写模式，采用直观的节点式流程图界面，让用户通过连接不同的功能模块即可构建个性化的生成管线。\n\n这一设计巧妙解决了高级 AI 绘图工作流配置复杂、灵活性不足的痛点。用户无需具备编程背景，也能自由组合模型、调整参数并实时预览效果，轻松实现从基础文生图到多步骤高清修复等各类复杂任务。ComfyUI 拥有极佳的兼容性，不仅支持 Windows、macOS 和 Linux 全平台，还广泛适配 NVIDIA、AMD、Intel 及苹果 Silicon 等多种硬件架构，并率先支持 SDXL、Flux、SD3 等前沿模型。\n\n无论是希望深入探索算法潜力的研究人员和开发者，还是追求极致创作自由度的设计师与资深 AI 绘画爱好者，ComfyUI 都能提供强大的支持。其独特的模块化架构允许社区不断扩展新功能，使其成为当前最灵活、生态最丰富的开源扩散模型工具之一，帮助用户将创意高效转化为现实。",108322,"2026-04-10T11:39:34",[14,15,13],{"id":45,"name":46,"github_repo":47,"description_zh":48,"stars":49,"difficulty_score":32,"last_commit_at":50,"category_tags":51,"status":17},6121,"gemini-cli","google-gemini\u002Fgemini-cli","gemini-cli 是一款由谷歌推出的开源 AI 命令行工具，它将强大的 Gemini 大模型能力直接集成到用户的终端环境中。对于习惯在命令行工作的开发者而言，它提供了一条从输入提示词到获取模型响应的最短路径，无需切换窗口即可享受智能辅助。\n\n这款工具主要解决了开发过程中频繁上下文切换的痛点，让用户能在熟悉的终端界面内直接完成代码理解、生成、调试以及自动化运维任务。无论是查询大型代码库、根据草图生成应用，还是执行复杂的 Git 操作，gemini-cli 都能通过自然语言指令高效处理。\n\n它特别适合广大软件工程师、DevOps 人员及技术研究人员使用。其核心亮点包括支持高达 100 万 token 的超长上下文窗口，具备出色的逻辑推理能力；内置 Google 搜索、文件操作及 Shell 命令执行等实用工具；更独特的是，它支持 MCP（模型上下文协议），允许用户灵活扩展自定义集成，连接如图像生成等外部能力。此外，个人谷歌账号即可享受免费的额度支持，且项目基于 Apache 2.0 协议完全开源，是提升终端工作效率的理想助手。",100752,"2026-04-10T01:20:03",[52,13,15,14],"插件",{"id":54,"name":55,"github_repo":56,"description_zh":57,"stars":58,"difficulty_score":32,"last_commit_at":59,"category_tags":60,"status":17},4721,"markitdown","microsoft\u002Fmarkitdown","MarkItDown 是一款由微软 AutoGen 团队打造的轻量级 Python 工具，专为将各类文件高效转换为 Markdown 格式而设计。它支持 PDF、Word、Excel、PPT、图片（含 OCR）、音频（含语音转录）、HTML 乃至 YouTube 链接等多种格式的解析，能够精准提取文档中的标题、列表、表格和链接等关键结构信息。\n\n在人工智能应用日益普及的今天，大语言模型（LLM）虽擅长处理文本，却难以直接读取复杂的二进制办公文档。MarkItDown 恰好解决了这一痛点，它将非结构化或半结构化的文件转化为模型“原生理解”且 Token 效率极高的 Markdown 格式，成为连接本地文件与 AI 分析 pipeline 的理想桥梁。此外，它还提供了 MCP（模型上下文协议）服务器，可无缝集成到 Claude Desktop 等 LLM 应用中。\n\n这款工具特别适合开发者、数据科学家及 AI 研究人员使用，尤其是那些需要构建文档检索增强生成（RAG）系统、进行批量文本分析或希望让 AI 助手直接“阅读”本地文件的用户。虽然生成的内容也具备一定可读性，但其核心优势在于为机器",93400,"2026-04-06T19:52:38",[52,14],{"id":62,"github_repo":63,"name":64,"description_en":65,"description_zh":66,"ai_summary_zh":67,"readme_en":68,"readme_zh":69,"quickstart_zh":70,"use_case_zh":71,"hero_image_url":72,"owner_login":73,"owner_name":73,"owner_avatar_url":74,"owner_bio":75,"owner_company":76,"owner_location":76,"owner_email":76,"owner_twitter":76,"owner_website":76,"owner_url":77,"languages":78,"stars":87,"forks":88,"last_commit_at":89,"license":90,"difficulty_score":32,"env_os":91,"env_gpu":92,"env_ram":91,"env_deps":93,"category_tags":103,"github_topics":104,"view_count":32,"oss_zip_url":76,"oss_zip_packed_at":76,"status":17,"created_at":111,"updated_at":112,"faqs":113,"releases":144},7562,"ShannonAI\u002Fservice-streamer","service-streamer","Boosting your Web Services of Deep Learning Applications. ","Service Streamer 是一款专为深度学习 Web 服务设计的中间件，旨在显著提升模型在线推理的性能。在传统的 Web 服务架构中，用户请求通常是离散且逐个到达的，这导致拥有强大并行计算能力的 GPU 在处理单个请求时处于闲置状态，不仅资源利用率低，而且在高并发场景下延迟会线性增加。\n\nService Streamer 巧妙地解决了这一痛点。它通过在服务端引入队列机制，将来自不同用户的离散请求自动收集并组装成“小批量”（mini-batch）数据，再统一送入深度学习模型进行计算。这种机制充分利用了 GPU 的并行处理优势，在不改变原有模型逻辑的前提下，大幅提高了吞吐量并降低了响应延迟。官方测试显示，仅需对代码进行微调，即可使模型处理速度提升十倍。\n\n该工具非常适合需要将 NLP、图像识别等深度学习模型部署为在线服务的开发者和研究人员。其核心亮点在于极高的易用性与兼容性：它与任何 Web 框架（如 Flask、Django）及深度学习框架均能无缝协作，支持快速集成；同时具备良好的扩展性，能轻松适配多 GPU 环境以应对海量请求。如果你希望以最小成本优化现有 AI 服务的效率，S","Service Streamer 是一款专为深度学习 Web 服务设计的中间件，旨在显著提升模型在线推理的性能。在传统的 Web 服务架构中，用户请求通常是离散且逐个到达的，这导致拥有强大并行计算能力的 GPU 在处理单个请求时处于闲置状态，不仅资源利用率低，而且在高并发场景下延迟会线性增加。\n\nService Streamer 巧妙地解决了这一痛点。它通过在服务端引入队列机制，将来自不同用户的离散请求自动收集并组装成“小批量”（mini-batch）数据，再统一送入深度学习模型进行计算。这种机制充分利用了 GPU 的并行处理优势，在不改变原有模型逻辑的前提下，大幅提高了吞吐量并降低了响应延迟。官方测试显示，仅需对代码进行微调，即可使模型处理速度提升十倍。\n\n该工具非常适合需要将 NLP、图像识别等深度学习模型部署为在线服务的开发者和研究人员。其核心亮点在于极高的易用性与兼容性：它与任何 Web 框架（如 Flask、Django）及深度学习框架均能无缝协作，支持快速集成；同时具备良好的扩展性，能轻松适配多 GPU 环境以应对海量请求。如果你希望以最小成本优化现有 AI 服务的效率，Service Streamer 是一个值得尝试的专业方案。","\u003Ch1 align=\"center\">Service Streamer\u003C\u002Fh1>\n\n\u003Cp align=\"center\">\nBoosting your Web Services of Deep Learning Applications. \n\u003Ca href=\".\u002FREADME_zh.md\">中文README\u003C\u002Fa>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n  \u003Ca href=\"#what-is-service-streamer-\">What is Service Streamer ?\u003C\u002Fa> •\n  \u003Ca href=\"#highlights\">Highlights\u003C\u002Fa> •\n  \u003Ca href=\"#installation\">Installation\u003C\u002Fa> •\n  \u003Ca href=\"#develop-bert-service-in-5-minutes\">Develop BERT Service in 5 Minutes\u003C\u002Fa> •\n  \u003Ca href=\"#api\">API\u003C\u002Fa> •\n  \u003Ca href=\"#benchmark\">Benchmark\u003C\u002Fa> •\n  \u003Ca href=\"#faq\">FAQ\u003C\u002Fa> •\n\u003C\u002Fp>\n\n\u003Ch6 align=\"center\">\n    \u003Ca href=\"https:\u002F\u002Ftravis-ci.org\u002FShannonAI\u002Fservice-streamer\">\n        \u003Cimg src=\"https:\u002F\u002Ftravis-ci.org\u002FShannonAI\u002Fservice-streamer.svg?branch=master\" alt=\"Build status\">\n    \u003C\u002Fa>\n • Made by ShannonAI • :globe_with_meridians: \u003Ca href=\"http:\u002F\u002Fwww.shannonai.com\u002F\">http:\u002F\u002Fwww.shannonai.com\u002F\u003C\u002Fa>\n\u003C\u002Fh6>\n\n\n\u003Ch2 align=\"center\">What is Service Streamer ?\u003C\u002Fh2>\n\nA mini-batch collects data samples and is usually used in deep learning models. In this way, models can utilize the parallel computing capability of GPUs. However, requests from users for web services are usually discrete. If using conventional loop server or threaded server, GPUs will be idle dealing with one request at a time. And the latency time will be linearly increasing when there are concurrent user requests. \n\nServiceStreamer is a middleware for web service of machine learning applications. Queue requests from users are sampled into mini-batches. ServiceStreamer can significantly enhance the overall performance of the system by improving GPU utilization. \n\n\u003Ch2 align=\"center\">Highlights\u003C\u002Fh2>\n\n- :hatching_chick: **Easy to use**: Minor changes can speed up the model ten times. \n- :zap: **Fast processing speed**: Low latency for online inference of machine learning models. \n- :octopus: **Good expandability**: Easy to be applied to multi-GPU scenarios for handling enormous requests.\n- :crossed_swords: **Applicability**: Used with any web frameworks and\u002For deep learning frameworks. \n\n\n\u003Ch2 align=\"center\">Installation\u003C\u002Fh2>\n\nInstall ServiceStream by using `pip`，requires **Python >= 3.5** :\n```bash\npip install service_streamer \n```\n\n\u003Ch2 align=\"center\">Develop BERT Service in 5 Minutes\u003C\u002Fh2>\n\nWe provide a step-by-step tutorial for you to bring BERT online in 5 minutes. The service processes 1400 sentences per second.  \n\n``Text Infilling`` is a task in natural language processing: given a sentence with several words randomly removed, the model predicts those words removed through the given context. \n\n``BERT`` has attracted a lot of attention in these two years and it achieves State-Of-The-Art results across many nlp tasks. BERT utilizes \"Masked Language Model (MLM)\" as one of the pre-training objectives. MLM models randomly mask some of the tokens from the input, and the objective is to predict the original vocabulary id of the masked word based on its context. MLM has similarities with text infilling. It is natural to introduce BERT to text infilling task. \n\n\n1. First, we define a model for text filling task [bert_model.py](.\u002Fexample\u002Fbert_model.py). The `predict` function accepts a batch of sentences and returns predicted position results of the `[MASK]` token. \n\n    ```python\n    class TextInfillingModel(object):\n        ...\n\n\n    batch = [\"twinkle twinkle [MASK] star.\",\n             \"Happy birthday to [MASK].\",\n             'the answer to life, the [MASK], and everything.']\n    model = TextInfillingModel()\n    outputs = model.predict(batch)\n    print(outputs)\n    # ['little', 'you', 'universe']\n    ```\n    **Note**: Please download pre-trained BERT model at first. \n\n\n2. Second, utilize [Flask](https:\u002F\u002Fgithub.com\u002Fpallets\u002Fflask) to pack predicting interfaces to Web service. [flask_example.py](.\u002Fexample\u002Fflask_example.py)\n\n\n    ```python\n    model = TextInfillingModel()\n    @app.route(\"\u002Fnaive\", methods=[\"POST\"])\n    def naive_predict():\n        inputs = request.form.getlist(\"s\")\n        outputs = model.predict(inputs)\n        return jsonify(outputs)\n     \n    app.run(port=5005)\n    ```\n    \n    Please run [flask_example.py](.\u002Fexample\u002Fflask_example.py), then you will get a vanilla Web server. \n\n    ```bash\n    curl -X POST http:\u002F\u002Flocalhost:5005\u002Fnaive -d 's=Happy birthday to [MASK].' \n    [\"you\"]\n    ```\n\n    At this time, your web server can only serve 12 requests per second. Please see [benchmark](#benchmark) for more details.\n\n\n3. Third, encapsulate model functions through `service_streamer`. Three lines of code make the prediction speed of BERT service reach 200+ sentences per second (16x faster).\n\n    ```python\n    from service_streamer import ThreadedStreamer\n    streamer = ThreadedStreamer(model.predict, batch_size=64, max_latency=0.1)\n\n    @app.route(\"\u002Fstream\", methods=[\"POST\"])\n    def stream_predict():\n        inputs = request.form.getlist(\"s\")\n        outputs = streamer.predict(inputs)\n        return jsonify(outputs)\n\n    app.run(port=5005, debug=False)\n    ```\n\n    Run [flask_example.py](.\u002Fexample\u002Fflask_example.py) and test the performance with [wrk](https:\u002F\u002Fgithub.com\u002Fwg\u002Fwrk). \n\n    ```bash\n    wrk -t 2 -c 128 -d 20s --timeout=10s -s benchmark.lua http:\u002F\u002F127.0.0.1:5005\u002Fstream\n    ...\n    Requests\u002Fsec:    200.31\n    ```\n\n4. Finally, encapsulate models through ``Streamer`` and start service workers on multiple GPUs. ``Streamer`` further accelerates inference speed and achieves 1000+ sentences per second (80x faster). \n\n\n\n    ```python\n    from service_streamer import ManagedModel, Streamer\n\n    class ManagedBertModel(ManagedModel):\n\n        def init_model(self):\n            self.model = TextInfillingModel()\n\n        def predict(self, batch):\n            return self.model.predict(batch)\n\n    streamer = Streamer(ManagedBertModel, batch_size=64, max_latency=0.1, worker_num=8, cuda_devices=(0, 1, 2, 3))\n    app.run(port=5005, debug=False)\n    ```\n\n    8 gpu workers can be started and evenly distributed on 4 GPUs.\n\n\n\u003Ch2 align=\"center\">API\u003C\u002Fh2>\n\n#### Quick Start\n\nIn general, the inference speed will be faster by utilizing parallel computing.\n\n```python\noutputs = model.predict(batch_inputs)\n```\n\n**ServiceStreamer** is a middleware for web service of machine learning applications. Queue requests from users are scheduled into mini-batches and forward into GPU workers. ServiceStreamer sacrifices a certain delay (default maximum is 0.1s) and enhance the overall performance by improving the ratio of GPU utilization. \n\n\n```python\nfrom service_streamer import ThreadedStreamer\n\n# Encapsulate batch_predict function with Streamer\n\nstreamer = ThreadedStreamer(model.predict, batch_size=64, max_latency=0.1)\n\n# Replace model.predict with streamer.predict\n\noutputs = streamer.predict(batch_inputs)\n```\n\nStart web server on multi-threading (or coordination). Your server can usually achieve 10x (```batch_size\u002Fbatch_per_request```) times faster by adding a few lines of code.\n\n\n#### Distributed GPU worker\n\nThe performance of web server (QPS) in practice is much higher than that of GPU model. We also support one web server with multiple GPU worker processes.\n\n```python\nfrom service_streamer import Streamer\n\n# Spawn releases 4 gpu worker processes\nstreamer = Streamer(model.predict, 64, 0.1, worker_num=4)\noutputs = streamer.predict(batch)\n```\n\n\n``Streamer`` uses ``spawn`` subprocesses to run gpu workers by default. ``Streamer`` uses interprocess queues to communicate and queue. It can distribute a large number of requests to multiple workers for processing.\n\nThen the prediction results of the model are returned to the corresponding web server in batches. And results are forwarded to the corresponding http response.\n\n```\n+-----------------------------------------------------------------------------+\n| NVIDIA-SMI 390.116                Driver Version: 390.116                   |\n|-------------------------------+----------------------+----------------------+\n...\n+-----------------------------------------------------------------------------+\n| Processes:                                                       GPU Memory |\n|  GPU       PID   Type   Process name                             Usage      |\n|=============================================================================|\n|    0      7574      C   \u002Fhome\u002Fliuxin\u002Fnlp\u002Fvenv\u002Fbin\u002Fpython            1889MiB |\n|    1      7575      C   \u002Fhome\u002Fliuxin\u002Fnlp\u002Fvenv\u002Fbin\u002Fpython            1889MiB |\n|    2      7576      C   \u002Fhome\u002Fliuxin\u002Fnlp\u002Fvenv\u002Fbin\u002Fpython            1889MiB |\n|    3      7577      C   \u002Fhome\u002Fliuxin\u002Fnlp\u002Fvenv\u002Fbin\u002Fpython            1889MiB |\n+-----------------------------------------------------------------------------+\n\n```\n\nThe above method is simple to define, but the main process initialization model takes up an extra portion of memory. And the model can only run on the same GPU.\nTherefore, we have provided the ```ManagedModel``` class to facilitate model lazy initialization and migration while supporting multiple GPUs.\n\n```python\nfrom service_streamer import ManagedModel\n\nclass ManagedBertModel(ManagedModel):\n\n    def init_model(self):\n        self.model = Model()\n\n    def predict(self, batch):\n        return self.model.predict(batch)\n\n\n# Spawn produces 4 gpu worker processes, which are evenly distributed on 0\u002F1\u002F2\u002F3 GPU\nstreamer = Streamer(ManagedBertModel, 64, 0.1, worker_num=4, cuda_devices=(0, 1, 2, 3))\noutputs = streamer.predict(batch)\n```\n\n#### Distributed Web Server\n\nSome cpu-intensive calculations, such as image and text preprocessing, need to be done first in web server. The preprocessed data is then forward into GPU worker for predictions. CPU resources often become performance bottlenecks in practice. Therefore, we also provide the mode of multi-web servers matching (single or multiple) gpu workers.\n\n\nUse ```RedisStream``` to specify a unique Redis address for all web servers and gpu workers. \n\n\n```python\n# default parameters can be omitted and localhost:6379 is used.\nstreamer = RedisStreamer(redis_broker=\"172.22.22.22:6379\")\n```\n\nWe make use of ``gunicorn`` or ``uwsgi`` to implement reverse proxy and load balancing.\n\n```bash\ncd example\ngunicorn -c redis_streamer_gunicorn.py flask_example:app\n```\n\nEach request will be load balanced to each web server for cpu preprocessing, and then evenly distributed to gpu worker for model prediction.\n\n\n### Future API\n\nYou might be familiar with `future` if you have used any concurrent library. \nYou can use the Future API directly if you want to use ``service_streamer`` for queueing requests or distributed GPU computing and using scenario is not web service. \n\n\n```python\nfrom service_streamer import ThreadedStreamer\nstreamer = ThreadedStreamer(model.predict, 64, 0.1)\n\nxs = []\nfor i in range(200):\n    future = streamer.submit([[\"How\", \"are\", \"you\", \"?\"], [\"Fine\", \".\"], [\"Thank\", \"you\", \".\"]])\n    xs.append(future)\n\n\n# Get all instances of future object and wait for asynchronous responses. \nfor future in xs:\n    outputs = future.result()\n    print(outputs)\n```\n\n\u003Ch2 align=\"center\">Benchmark\u003C\u002Fh2>\n\n### Benchmark\n\nWe utilize [wrk](https:\u002F\u002Fgithub.com\u002Fwg\u002Fwrk) to conduct benchmark test.\n\nTest examples and scripts can be found in [example](.\u002Fexample).\n\n\n### Environment\n\n*   gpu: Titan Xp\n*   cuda: 9.0\n*   pytorch: 1.1   \n\n### Single GPU process\n\n```bash\n# start flask threaded server\npython example\u002Fflask_example.py\n\n# benchmark naive api without service_streamer\nwrk -t 4 -c 128 -d 20s --timeout=10s -s benchmark.lua http:\u002F\u002F127.0.0.1:5005\u002Fnaive\n# benchmark stream api with service_streamer\nwrk -t 4 -c 128 -d 20s --timeout=10s -s benchmark.lua http:\u002F\u002F127.0.0.1:5005\u002Fstream\n```\n\n| |Naive|ThreaedStreamer|Streamer|RedisStreamer\n|-|-|-|-|-|\n| qps | 12.78 | 207.59 | 321.70 | 372.45 |\n| latency  | 8440ms | 603.35ms | 392.66ms | 340.74ms |\n\n### Multiple GPU processes\n\nThe performance loss of the communications and load balancing mechanism of multi-gpu workers are verified compared with a single web server process.\n\nWe adopt gevent server because multi-threaded Flask server has become a performance bottleneck. Please refer to the [flask_multigpu_example.py](example\u002Fflask_multigpu_example.py)\n\n\n```bash\nwrk -t 8 -c 512 -d 20s --timeout=10s -s benchmark.lua http:\u002F\u002F127.0.0.1:5005\u002Fstream\n```\n\n| gpu_worker_num | Naive | ThreadedStreamer |Streamer|RedisStreamer\n|-|-|-|-|-|\n|1|11.62|211.02|362.69|365.80|\n|2|N\u002FA|N\u002FA|488.40|609.63|\n|4|N\u002FA|N\u002FA|494.20|1034.57|\n\n\n* ``Threaded Streamer`` Due to the limitation of Python GIL, multi-worker is meaningless. We conduct comparison studies using single GPU worker. \n\n* ``Streamer`` Performance improvement is not linear when it is greater than 2 gpu worker.\nThe utilization rate of CPU reaches 100. The bottleneck is CPU at this time and the performance issue of flask is the obstacle.  \n\n\n### Utilize Future API to start multiple GPU processes\n\nWe adopt [Future API](#future-api) to conduct multi-GPU benchmeark test locally in order to reduce the performance influence of web server. Please refer to code example in [future_example.py](example\u002Ffuture_example.py)\n\n\n| gpu_worker_num | Batched | ThreadedStreamer |Streamer|RedisStreamer\n|-|-|-|-|-|\n|1|422.883|401.01|399.26|384.79|\n|2|N\u002FA|N\u002FA|742.16|714.781|\n|4|N\u002FA|N\u002FA|1400.12|1356.47|\n\nIt can be seen that the performance of ``service_streamer`` is almost linearly related to the number of gpu workers. Communications of inter-process in ``service_streamer`` is more efficient than redis. \n\n\u003Ch2 align=\"center\">FAQ\u003C\u002Fh2>\n\n**Q:** using a model trained from [allennlp](https:\u002F\u002Fgithub.com\u002Fallenai\u002Fallennlp),set ``worker_num=4`` of [Streamer](.\u002Fservice_streamer\u002Fservice_streamer.py) during inference, what's the reason that 16-core cpu is full and speed is slower than [Streamer](.\u002Fservice_streamer\u002Fservice_streamer.py) with ``worker_num=1``?\n\n**A:** for multi-process inference, if the model process data using numpy with multi-thread, it may cause cpu overheads, resulting in a multi-core computing speed that slower than a single core. This kind of problem may occur when using third-party libraries such as alennlp, spacy, etc. It could be solved by setting ``numpy threads``environment variables.\n   ```python\n   import os\n   os.environ[\"MKL_NUM_THREADS\"] = \"1\"  # export MKL_NUM_THREADS=1 \n   os.environ[\"NUMEXPR_NUM_THREADS\"] = \"1\"  # export NUMEXPR_NUM_THREADS=1 \n   os.environ[\"OMP_NUM_THREADS\"] = \"1\"  # export OMP_NUM_THREADS=1\n   import numpy\n   ```\n   make sure putting environment variables before ``import numpy``.\n\n**Q:** When using RedisStreamer, if there are only one redis broker and more than one model, the input batches may have different structure. How to deal with such situation?  \n\n**A:** Specify the prefix when initializing worker and streamer, each streamer will use a unique channel.  \n\nexample of initialiazing workers:  \n    \n```python\nfrom service_streamer import run_redis_workers_forever\nfrom bert_model import ManagedBertModel\n\nif __name__ == \"__main__\":\n    from multiprocessing import freeze_support\n    freeze_support()\n    run_redis_workers_forever(ManagedBertModel, 64, prefix='channel_1')\n    run_redis_workers_forever(ManagedBertModel, 64, prefix='channel_2')\n```\n\nexample of using streamer to have result:  \n    \n```python\nfrom service_streamer import RedisStreamer\n\nstreamer_1 = RedisStreaemr(prefix='channel_1')\nstreamer_2 = RedisStreaemr(prefix='channel_2')\n\n# predict\noutput_1 = streamer_1.predict(batch)\noutput_2 = streamer_2.predict(batch)\n```\n\n\n","\u003Ch1 align=\"center\">服务流处理器\u003C\u002Fh1>\n\n\u003Cp align=\"center\">\n助力您的深度学习应用Web服务。\n\u003Ca href=\".\u002FREADME_zh.md\">中文README\u003C\u002Fa>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n  \u003Ca href=\"#what-is-service-streamer-\">什么是服务流处理器？\u003C\u002Fa> •\n  \u003Ca href=\"#highlights\">亮点\u003C\u002Fa> •\n  \u003Ca href=\"#installation\">安装\u003C\u002Fa> •\n  \u003Ca href=\"#develop-bert-service-in-5-minutes\">5分钟开发BERT服务\u003C\u002Fa> •\n  \u003Ca href=\"#api\">API\u003C\u002Fa> •\n  \u003Ca href=\"#benchmark\">基准测试\u003C\u002Fa> •\n  \u003Ca href=\"#faq\">常见问题解答\u003C\u002Fa> •\n\u003C\u002Fp>\n\n\u003Ch6 align=\"center\">\n    \u003Ca href=\"https:\u002F\u002Ftravis-ci.org\u002FShannonAI\u002Fservice-streamer\">\n        \u003Cimg src=\"https:\u002F\u002Ftravis-ci.org\u002FShannonAI\u002Fservice-streamer.svg?branch=master\" alt=\"构建状态\">\n    \u003C\u002Fa>\n • 由ShannonAI制作 • :globe_with_meridians: \u003Ca href=\"http:\u002F\u002Fwww.shannonai.com\u002F\">http:\u002F\u002Fwww.shannonai.com\u002F\u003C\u002Fa>\n\u003C\u002Fh6>\n\n\n\u003Ch2 align=\"center\">什么是服务流处理器？\u003C\u002Fh2>\n\n在深度学习模型中，通常会将数据样本收集为一个“小批量”进行处理。这样可以充分利用GPU的并行计算能力。然而，用户对Web服务的请求通常是离散的。如果使用传统的循环服务器或线程服务器，GPU每次只能处理一个请求，导致空闲时间增加，并且在有并发请求时，延迟会线性增长。\n\nServiceStreamer是一款用于机器学习应用Web服务的中间件。它能够将用户的请求排队并采样成小批量，通过提高GPU利用率来显著提升系统的整体性能。\n\n\u003Ch2 align=\"center\">亮点\u003C\u002Fh2>\n\n- :hatching_chick: **易于使用**：只需少量改动，即可使模型加速十倍。\n- :zap: **处理速度快**：降低机器学习模型在线推理的延迟。\n- :octopus: **扩展性强**：易于应用于多GPU场景，以处理海量请求。\n- :crossed_swords: **适用性广**：可与任何Web框架和\u002F或深度学习框架配合使用。\n\n\n\u003Ch2 align=\"center\">安装\u003C\u002Fh2>\n\n使用`pip`安装ServiceStream，需要**Python >= 3.5**：\n```bash\npip install service_streamer \n```\n\n\u003Ch2 align=\"center\">5分钟开发BERT服务\u003C\u002Fh2>\n\n我们提供了一个分步教程，帮助您在5分钟内将BERT部署上线。该服务每秒可处理1400个句子。\n\n“文本补全”是自然语言处理中的一个任务：给定一个随机缺失了若干单词的句子，模型需要根据上下文预测这些被删除的单词。\n\n“BERT”在过去两年中备受关注，在许多NLP任务上都取得了最先进的成果。BERT利用“掩码语言模型（MLM）”作为其预训练目标之一。MLM会随机遮盖输入中的部分标记，目标是根据上下文预测被遮盖单词的原始词汇ID。MLM与文本补全任务有相似之处，因此将BERT引入文本补全任务是非常自然的选择。\n\n\n1. 首先，我们为文本补全任务定义一个模型[bert_model.py](.\u002Fexample\u002Fbert_model.py)。`predict`函数接受一批句子，并返回`[MASK]`标记的预测位置结果。\n\n    ```python\n    class TextInfillingModel(object):\n        ...\n\n\n    batch = [\"twinkle twinkle [MASK] star.\",\n             \"Happy birthday to [MASK].\",\n             'the answer to life, the [MASK], and everything.']\n    model = TextInfillingModel()\n    outputs = model.predict(batch)\n    print(outputs)\n    # ['little', 'you', 'universe']\n    ```\n    **注意**：请先下载预训练的BERT模型。\n\n\n2. 其次，利用[Flask](https:\u002F\u002Fgithub.com\u002Fpallets\u002Fflask)将预测接口封装成Web服务。[flask_example.py](.\u002Fexample\u002Fflask_example.py)\n\n\n    ```python\n    model = TextInfillingModel()\n    @app.route(\"\u002Fnaive\", methods=[\"POST\"])\n    def naive_predict():\n        inputs = request.form.getlist(\"s\")\n        outputs = model.predict(inputs)\n        return jsonify(outputs)\n     \n    app.run(port=5005)\n    ```\n    \n    请运行[flask_example.py](.\u002Fexample\u002Fflask_example.py)，您将得到一个基础的Web服务器。\n\n    ```bash\n    curl -X POST http:\u002F\u002Flocalhost:5005\u002Fnaive -d 's=Happy birthday to [MASK].' \n    [\"you\"]\n    ```\n\n    此时，您的Web服务器每秒只能处理12个请求。更多细节请参见[基准测试](#benchmark)。\n\n\n3. 第三，通过`service_streamer`封装模型函数。仅需三行代码，BERT服务的预测速度就能达到每秒200+个句子（快了16倍）。\n\n    ```python\n    from service_streamer import ThreadedStreamer\n    streamer = ThreadedStreamer(model.predict, batch_size=64, max_latency=0.1)\n\n    @app.route(\"\u002Fstream\", methods=[\"POST\"])\n    def stream_predict():\n        inputs = request.form.getlist(\"s\")\n        outputs = streamer.predict(inputs)\n        return jsonify(outputs)\n\n    app.run(port=5005, debug=False)\n    ```\n\n    运行[flask_example.py](.\u002Fexample\u002Fflask_example.py)，然后使用[wrk](https:\u002F\u002Fgithub.com\u002Fwg\u002Fwrk)测试性能。\n\n    ```bash\n    wrk -t 2 -c 128 -d 20s --timeout=10s -s benchmark.lua http:\u002F\u002F127.0.0.1:5005\u002Fstream\n    ...\n    Requests\u002Fsec:    200.31\n    ```\n\n4. 最后，通过`Streamer`封装模型，并在多个GPU上启动服务工作进程。`Streamer`进一步提升了推理速度，使服务达到每秒1000+个句子（快了80倍）。\n\n\n\n    ```python\n    from service_streamer import ManagedModel, Streamer\n\n    class ManagedBertModel(ManagedModel):\n\n        def init_model(self):\n            self.model = TextInfillingModel()\n\n        def predict(self, batch):\n            return self.model.predict(batch)\n\n    streamer = Streamer(ManagedBertModel, batch_size=64, max_latency=0.1, worker_num=8, cuda_devices=(0, 1, 2, 3))\n    app.run(port=5005, debug=False)\n    ```\n\n    可以启动8个GPU工作进程，并均匀分配到4个GPU上。\n\n\n\u003Ch2 align=\"center\">API\u003C\u002Fh2>\n\n#### 快速入门\n\n一般来说，利用并行计算可以加快推理速度。\n\n```python\noutputs = model.predict(batch_inputs)\n```\n\n**ServiceStreamer**是用于机器学习应用Web服务的中间件。它会将用户的请求排队并调度成小批量，然后转发到GPU工作进程中。ServiceStreamer会在一定程度上牺牲延迟（默认最大为0.1秒），并通过提高GPU利用率来提升整体性能。\n\n\n```python\nfrom service_streamer import ThreadedStreamer\n\n# 使用Streamer封装batch_predict函数\n\nstreamer = ThreadedStreamer(model.predict, batch_size=64, max_latency=0.1)\n\n# 将 model.predict 替换为 streamer.predict\n\noutputs = streamer.predict(batch_inputs)\n```\n\n在多线程（或协程）环境下启动 Web 服务器。只需添加几行代码，您的服务器通常就能提升 10 倍（```batch_size\u002Fbatch_per_request```）的处理速度。\n\n\n#### 分布式 GPU 工作进程\n\n实际应用中，Web 服务器的性能（QPS）远高于 GPU 模型本身。我们还支持一个 Web 服务器搭配多个 GPU 工作进程。\n\n```python\nfrom service_streamer import Streamer\n\n# 使用 spawn 启动 4 个 GPU 工作进程\nstreamer = Streamer(model.predict, 64, 0.1, worker_num=4)\noutputs = streamer.predict(batch)\n```\n\n\n``Streamer`` 默认使用 ``spawn`` 子进程来运行 GPU 工作进程。它通过进程间队列进行通信和任务排队，能够将大量请求分发到多个工作进程进行处理。\n\n随后，模型的预测结果会批量返回给对应的 Web 服务器，并进一步转发到相应的 HTTP 响应中。\n\n```\n+-----------------------------------------------------------------------------+\n| NVIDIA-SMI 390.116                Driver Version: 390.116                   |\n|-------------------------------+----------------------+----------------------+\n...\n+-----------------------------------------------------------------------------+\n| Processes:                                                       GPU Memory |\n|  GPU       PID   Type   Process name                             Usage      |\n|=============================================================================|\n|    0      7574      C   \u002Fhome\u002Fliuxin\u002Fnlp\u002Fvenv\u002Fbin\u002Fpython            1889MiB |\n|    1      7575      C   \u002Fhome\u002Fliuxin\u002Fnlp\u002Fvenv\u002Fbin\u002Fpython            1889MiB |\n|    2      7576      C   \u002Fhome\u002Fliuxin\u002Fnlp\u002Fvenv\u002Fbin\u002Fpython            1889MiB |\n|    3      7577      C   \u002Fhome\u002Fliuxin\u002Fnlp\u002Fvenv\u002Fbin\u002Fpython            1889MiB |\n+-----------------------------------------------------------------------------+\n\n```\n\n上述方法定义简单，但主进程需要初始化模型，这会额外占用一部分内存。而且模型只能运行在同一个 GPU 上。因此，我们提供了 ```ManagedModel``` 类，以方便模型的延迟初始化和迁移，同时支持多 GPU 运行。\n\n```python\nfrom service_streamer import ManagedModel\n\nclass ManagedBertModel(ManagedModel):\n\n    def init_model(self):\n        self.model = Model()\n\n    def predict(self, batch):\n        return self.model.predict(batch)\n\n\n# 使用 spawn 启动 4 个 GPU 工作进程，并均匀分配到 0\u002F1\u002F2\u002F3 号 GPU\nstreamer = Streamer(ManagedBertModel, 64, 0.1, worker_num=4, cuda_devices=(0, 1, 2, 3))\noutputs = streamer.predict(batch)\n```\n\n#### 分布式 Web 服务器\n\n一些 CPU 密集型计算，例如图像和文本预处理，通常需要先在 Web 服务器中完成。预处理后的数据再传递给 GPU 工作进程进行预测。然而，在实际应用中，CPU 资源往往会成为性能瓶颈。为此，我们也提供了多台 Web 服务器与单个或多个 GPU 工作进程相匹配的模式。\n\n\n使用 ```RedisStream``` 为所有 Web 服务器和 GPU 工作进程指定一个唯一的 Redis 地址。\n\n\n```python\n# 默认参数可以省略，默认使用 localhost:6379。\nstreamer = RedisStreamer(redis_broker=\"172.22.22.22:6379\")\n```\n\n我们利用 ``gunicorn`` 或 ``uwsgi`` 实现反向代理和负载均衡。\n\n```bash\ncd example\ngunicorn -c redis_streamer_gunicorn.py flask_example:app\n```\n\n每个请求都会被负载均衡到不同的 Web 服务器进行 CPU 预处理，然后再均匀分配到 GPU 工作进程进行模型预测。\n\n\n### Future API\n\n如果您使用过任何并发库，应该对 `future` 不陌生。如果希望将 ``service_streamer`` 用于请求排队或分布式 GPU 计算，且应用场景并非 Web 服务，可以直接使用 Future API。\n\n\n```python\nfrom service_streamer import ThreadedStreamer\nstreamer = ThreadedStreamer(model.predict, 64, 0.1)\n\nxs = []\nfor i in range 200:\n    future = streamer.submit([[\"How\", \"are\", \"you\", \"?\"], [\"Fine\", \".\"], [\"Thank\", \"you\", \".\"]])\n    xs.append(future)\n\n\n# 获取所有 Future 对象实例并等待异步响应。\nfor future in xs:\n    outputs = future.result()\n    print(outputs)\n```\n\n\u003Ch2 align=\"center\">基准测试\u003C\u002Fh2>\n\n### 基准测试\n\n我们使用 [wrk](https:\u002F\u002Fgithub.com\u002Fwg\u002Fwrk) 进行基准测试。\n\n测试示例和脚本可在 [example](.\u002Fexample) 中找到。\n\n### 环境\n\n*   GPU：Titan Xp\n*   CUDA：9.0\n*   PyTorch：1.1   \n\n### 单 GPU 进程\n\n```bash\n# 启动 Flask 多线程服务器\npython example\u002Fflask_example.py\n\n# 测试无 service_streamer 的原生 API\nwrk -t 4 -c 128 -d 20s --timeout=10s -s benchmark.lua http:\u002F\u002F127.0.0.1:5005\u002Fnaive\n# 测试带有 service_streamer 的流式 API\nwrk -t 4 -c 128 -d 20s --timeout=10s -s benchmark.lua http:\u002F\u002F127.0.0.1:5005\u002Fstream\n```\n\n| |Naive|ThreaedStreamer|Streamer|RedisStreamer\n|-|-|-|-|-|\n| qps | 12.78 | 207.59 | 321.70 | 372.45 |\n| 延迟  | 8440ms | 603.35ms | 392.66ms | 340.74ms |\n\n### 多 GPU 进程\n\n与单个 Web 服务器进程相比，多 GPU 工作进程的通信和负载均衡机制会导致一定的性能损失。由于多线程 Flask 服务器已成为性能瓶颈，我们采用了 gevent 服务器。请参阅 [flask_multigpu_example.py](example\u002Fflask_multigpu_example.py)。\n\n\n```bash\nwrk -t 8 -c 512 -d 20s --timeout=10s -s benchmark.lua http:\u002F\u002F127.0.0.1:5005\u002Fstream\n```\n\n| gpu_worker_num | Naive | ThreadedStreamer |Streamer|RedisStreamer\n|-|-|-|-|-|\n|1|11.62|211.02|362.69|365.80|\n|2|N\u002FA|N\u002FA|488.40|609.63|\n|4|N\u002FA|N\u002FA|494.20|1034.57|\n\n\n* ``Threaded Streamer`` 由于 Python GIL 的限制，多工作进程并无意义。我们仅使用单 GPU 工作进程进行对比研究。\n\n* ``Streamer`` 在超过 2 个 GPU 工作进程时，性能提升不再线性。此时 CPU 利用率达到 100%，瓶颈在于 CPU，Flask 的性能问题也成为阻碍。\n\n### 使用 Future API 启动多 GPU 进程\n\n我们采用 [Future API](#future-api) 在本地进行多 GPU 基准测试，以减少 Web 服务器对性能的影响。请参考 [future_example.py](example\u002Ffuture_example.py) 中的代码示例。\n\n\n| gpu_worker_num | 批量处理 | ThreadedStreamer | Streamer | RedisStreamer |\n|-|-|-|-|-|\n|1|422.883|401.01|399.26|384.79|\n|2|无|无|742.16|714.781|\n|4|无|无|1400.12|1356.47|\n\n可以看出，``service_streamer`` 的性能几乎与 GPU 工作进程的数量呈线性关系。在 ``service_streamer`` 中，进程间通信比使用 Redis 更高效。\n\n\u003Ch2 align=\"center\">常见问题解答\u003C\u002Fh2>\n\n**问：** 使用从 [allennlp](https:\u002F\u002Fgithub.com\u002Fallenai\u002Fallennlp) 训练的模型，在推理时将 [Streamer](.\u002Fservice_streamer\u002Fservice_streamer.py) 的 ``worker_num=4``，为什么会出现 16 核 CPU 被打满，且速度反而比 ``worker_num=1`` 的 [Streamer](.\u002Fservice_streamer\u002Fservice_streamer.py) 还慢的情况？\n\n**答：** 对于多进程推理，如果模型在处理数据时使用了多线程的 NumPy 操作，可能会导致较高的 CPU 开销，从而使得多核并行计算的速度反而不如单核。这类问题在使用 alennlp、spacy 等第三方库时较为常见。可以通过设置 ``numpy threads`` 相关环境变量来解决。\n   ```python\n   import os\n   os.environ[\"MKL_NUM_THREADS\"] = \"1\"  # export MKL_NUM_THREADS=1 \n   os.environ[\"NUMEXPR_NUM_THREADS\"] = \"1\"  # export NUMEXPR_NUM_THREADS=1 \n   os.environ[\"OMP_NUM_THREADS\"] = \"1\"  # export OMP_NUM_THREADS=1\n   import numpy\n   ```\n   请注意，必须在 ``import numpy`` 之前设置这些环境变量。\n\n**问：** 使用 RedisStreamer 时，如果只有一个 Redis 代理，但有多个模型，输入批次的结构可能不同。如何处理这种情况？\n\n**答：** 在初始化工作进程和流式处理器时指定前缀，每个流式处理器将使用唯一的通道。\n\n初始化工作进程的示例：\n    \n```python\nfrom service_streamer import run_redis_workers_forever\nfrom bert_model import ManagedBertModel\n\nif __name__ == \"__main__\":\n    from multiprocessing import freeze_support\n    freeze_support()\n    run_redis_workers_forever(ManagedBertModel, 64, prefix='channel_1')\n    run_redis_workers_forever(ManagedBertModel, 64, prefix='channel_2')\n```\n\n使用流式处理器获取结果的示例：\n    \n```python\nfrom service_streamer import RedisStreamer\n\nstreamer_1 = RedisStreaemr(prefix='channel_1')\nstreamer_2 = RedisStreaemr(prefix='channel_2')\n\n# 预测\noutput_1 = streamer_1.predict(batch)\noutput_2 = streamer_2.predict(batch)\n```","# Service Streamer 快速上手指南\n\nService Streamer 是一款专为深度学习 Web 服务设计的中间件。它通过将离散的用户请求自动聚合成 mini-batch，充分利用 GPU 的并行计算能力，从而显著提升模型推理的吞吐量（QPS）并降低延迟。\n\n## 环境准备\n\n在开始之前，请确保您的开发环境满足以下要求：\n\n*   **操作系统**：Linux \u002F macOS \u002F Windows\n*   **Python 版本**：>= 3.5\n*   **硬件依赖**：推荐使用配备 NVIDIA GPU 的环境以发挥最大性能（CPU 环境亦可运行）\n*   **前置框架**：已安装任意深度学习框架（如 PyTorch, TensorFlow）及 Web 框架（如 Flask, FastAPI）\n\n## 安装步骤\n\n使用 `pip` 进行安装。国内开发者建议使用清华源或阿里源以加速下载：\n\n```bash\n# 使用默认源\npip install service_streamer\n\n# 或使用国内镜像源（推荐）\npip install service_streamer -i https:\u002F\u002Fpypi.tuna.tsinghua.edu.cn\u002Fsimple\n```\n\n## 基本使用\n\n只需几行代码即可将现有的模型预测函数升级为支持高并发的流式服务。以下以 Flask + BERT 文本填充任务为例。\n\n### 1. 定义模型\n首先定义一个标准的模型类，包含 `predict` 方法，该方法接收一个列表（batch）并返回结果。\n\n```python\nclass TextInfillingModel(object):\n    def __init__(self):\n        # 初始化你的深度学习模型，例如加载 BERT 权重\n        pass\n\n    def predict(self, batch):\n        # batch 是一个字符串列表，例如 [\"Hello [MASK].\", \"World [MASK].\"]\n        # 执行模型推理并返回结果列表\n        results = [] \n        # ... 模型推理逻辑 ...\n        return results\n\nmodel = TextInfillingModel()\n```\n\n### 2. 集成 Service Streamer\n引入 `ThreadedStreamer`，将模型的 `predict` 方法包装起来。设置合适的 `batch_size`（批大小）和 `max_latency`（最大等待延迟，单位秒）。\n\n```python\nfrom service_streamer import ThreadedStreamer\n\n# 初始化 Streamer\n# batch_size: 每次推理的最大样本数\n# max_latency: 请求在队列中等待的最大时间（秒），超时即强制推理\nstreamer = ThreadedStreamer(model.predict, batch_size=64, max_latency=0.1)\n```\n\n### 3. 部署 Web 服务\n在 Web 框架（如 Flask）中，用 `streamer.predict` 替换原有的 `model.predict`。\n\n```python\nfrom flask import Flask, request, jsonify\n\napp = Flask(__name__)\n\n@app.route(\"\u002Fpredict\", methods=[\"POST\"])\ndef stream_predict():\n    # 获取请求中的多个句子\n    inputs = request.form.getlist(\"s\")\n    \n    # 使用 streamer 进行预测（自动 batching）\n    outputs = streamer.predict(inputs)\n    \n    return jsonify(outputs)\n\nif __name__ == \"__main__\":\n    # 生产环境建议关闭 debug 模式\n    app.run(port=5005, debug=False)\n```\n\n### 进阶：多 GPU 分布式部署\n若需利用多张 GPU 进一步提升性能，可使用 `Streamer` 配合 `ManagedModel` 启动多个工作进程：\n\n```python\nfrom service_streamer import ManagedModel, Streamer\n\nclass ManagedBertModel(ManagedModel):\n    def init_model(self):\n        # 在每个子进程中独立初始化模型\n        self.model = TextInfillingModel()\n\n    def predict(self, batch):\n        return self.model.predict(batch)\n\n# 启动 8 个工作进程，均匀分布在 4 张 GPU 上\nstreamer = Streamer(\n    ManagedBertModel, \n    batch_size=64, \n    max_latency=0.1, \n    worker_num=8, \n    cuda_devices=(0, 1, 2, 3)\n)\n```\n\n通过以上步骤，您的服务即可实现高吞吐量的模型推理。","某电商平台的智能客服团队正在部署基于 BERT 模型的自动回复系统，需实时处理成千上万条用户咨询文本以生成精准回答。\n\n### 没有 service-streamer 时\n- **GPU 资源严重浪费**：用户请求是离散到达的，传统服务器逐个处理请求，导致昂贵的 GPU 大部分时间处于空闲等待状态。\n- **高并发下延迟激增**：当促销活动期间流量洪峰到来，排队请求线性增加，用户收到回复的等待时间从毫秒级飙升至数秒。\n- **吞吐量遭遇瓶颈**：单线程或简单多线程模式无法利用深度学习模型的批处理（Mini-batch）特性，系统每秒仅能处理极少量句子。\n- **扩容成本高昂**：为了维持响应速度，不得不堆砌更多服务器实例，导致硬件和运维成本大幅上升。\n\n### 使用 service-streamer 后\n- **GPU 利用率最大化**：service-streamer 作为中间件，自动将离散的用户请求动态聚合成 Mini-batch，让 GPU 始终满负荷并行计算。\n- **低延迟稳定响应**：即使在数万并发请求下，通过高效的队列采样机制，系统仍能保持毫秒级的在线推理延迟。\n- **吞吐量提升十倍**：借助批处理优势，单节点处理速度从每秒几百句跃升至数千句（如官方案例中的 1400 句\u002F秒），轻松应对流量高峰。\n- **无缝集成与扩展**：无需重构现有的 Flask 或 Django 代码，仅需微小改动即可接入，并轻松扩展至多 GPU 集群场景。\n\nservice-streamer 通过将离散请求转化为批量计算，彻底解决了深度学习 Web 服务中 GPU 闲置与高并发延迟的矛盾，以极低改造成本实现了性能的数量级飞跃。","https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002FShannonAI_service-streamer_8cfb01a3.png","ShannonAI","https:\u002F\u002Foss.gittoolsai.com\u002Favatars\u002FShannonAI_f27e460f.jpg","",null,"https:\u002F\u002Fgithub.com\u002FShannonAI",[79,83],{"name":80,"color":81,"percentage":82},"Python","#3572A5",97.6,{"name":84,"color":85,"percentage":86},"Lua","#000080",2.4,1245,188,"2026-04-12T02:22:19","Apache-2.0","未说明","需要 NVIDIA GPU (示例中使用了 Titan Xp)，需安装 CUDA (示例环境为 CUDA 9.0)，支持多 GPU 部署",{"notes":94,"python":95,"dependencies":96},"该工具是一个中间件，旨在通过将离散请求聚集成 mini-batch 来提高深度学习 Web 服务的 GPU 利用率和吞吐量。支持单线程、多进程（多 GPU）以及基于 Redis 的分布式部署模式。示例中使用了 BERT 模型，实际运行前需自行下载预训练模型。在分布式模式下，主进程初始化模型会占用额外内存，建议使用 ManagedModel 类实现模型的懒加载和多 GPU 均衡分配。",">=3.5",[97,98,99,100,101,102],"service_streamer","Flask","PyTorch (示例版本 1.1)","Redis (用于 RedisStreamer 模式)","gunicorn 或 uwsgi (用于分布式 Web 服务器)","wrk (用于基准测试)",[35,14],[105,106,107,108,109,110],"deep-learning","web","pytorch","model-deployment","tensorflow","bert","2026-03-27T02:49:30.150509","2026-04-15T07:11:43.137382",[114,119,124,129,134,139],{"id":115,"question_zh":116,"answer_zh":117,"source_url":118},33889,"使用 TensorFlow\u002FKeras 模型时遇到 'Tensor is not an element of this graph' 或多线程报错怎么办？","这是因为 TensorFlow 在多线程环境下需要指定计算图（graph）。解决方案是确保在 streamer 所在的进程内初始化模型，不要在 main 函数外部初始化。如果使用 Tornado 等框架，请在 main 方法中初始化 Streamer，然后在控制器方法中调用 predict。对于某些情况，可能需要在模型预测代码块中使用 `with graph.as_default():` 包裹。","https:\u002F\u002Fgithub.com\u002FShannonAI\u002Fservice-streamer\u002Fissues\u002F20",{"id":120,"question_zh":121,"answer_zh":122,"source_url":123},33890,"如何在多卡和单卡环境下正确选择 Streamer 类型以避免 pickle 错误或性能问题？","正确的解决方案是：如果有多张显卡，请使用多进程模式 `Streamer` 配合 `ManagedModel`；如果是单卡，请使用 `ThreadedStreamer`。前提条件是模型必须在 streamer 所在的进程内进行初始化。此外，注意 `mp.Queue` 在处理大的 numpy 数组（如图像）时 pickle 和 unpickle 的开销很大，如果使用 torch.Tensor 则没有问题，因为传递的是句柄（handle）。","https:\u002F\u002Fgithub.com\u002FShannonAI\u002Fservice-streamer\u002Fissues\u002F55",{"id":125,"question_zh":126,"answer_zh":127,"source_url":128},33891,"在使用 ManagedModel 和 TensorFlow 时出现 RuntimeError 或 CUDA 设备初始化失败如何解决？","尝试设置 `mp_start_method=\"fork\"`。这通常是因为在 spawn 新进程时，某些全局变量无法被复制导致的。另外，需要将 `import tensorflow` 语句移动到 `Streamer()` 初始化之后，以防止在设置 `CUDA_VISIBLE_DEVICES` 之前就进行了初始化。如果问题依旧，可能需要增加 `service_streamer.py` 中硬编码的 `WORKER_TIMEOUT` 值。","https:\u002F\u002Fgithub.com\u002FShannonAI\u002Fservice-streamer\u002Fissues\u002F71",{"id":130,"question_zh":131,"answer_zh":132,"source_url":133},33892,"为什么并发量上不去？使用多卡是否能直接提高并发？","仅使用多卡并不一定能直接提高并发量。如果已经使用了 gunicorn + flask，可以结合 gunicorn 来实现多进程以提升并发。在使用 service-streamer 时，需确认是否正确配置了多进程模式（Streamer + ManagedModel）来利用多卡资源，而不仅仅是依赖框架本身的多卡支持。","https:\u002F\u002Fgithub.com\u002FShannonAI\u002Fservice-streamer\u002Fissues\u002F32",{"id":135,"question_zh":136,"answer_zh":137,"source_url":138},33893,"为什么库默认使用 'spawn' 方法启动多进程，导致无法共享全局变量或使用 preload 特性？","默认使用 'spawn' 是为了兼容性和避免某些平台（如 Windows\u002FmacOS）上的 fork 问题，但这会导致每个进程复制内存且无法共享全局变量。如果确定环境支持（如 Linux），可以手动修改源码将 `multiprocessing.get_context('spawn')` 改为使用 'fork' 模式，或者直接 `import multiprocessing as mp` 并移除强制指定 spawn 的代码，这样程序通常能正常运行并支持全局变量共享。","https:\u002F\u002Fgithub.com\u002FShannonAI\u002Fservice-streamer\u002Fissues\u002F35",{"id":140,"question_zh":141,"answer_zh":142,"source_url":143},33894,"使用 ThreadedStreamer 时返回结果延时较高，疑似线程唤醒不及时怎么办？","高延时可能是因为异步方式下，执行完 `run_once` 后收集结果的线程没有立即执行，仍在执行 `run_forever`，导致 `finish_event` 未能及时唤醒等待线程。如果遇到此问题，可以考虑检查事件通知机制，或者在极端情况下修改为同步的线程模型来确保结果及时返回，但通常建议先排查是否因负载过高导致调度延迟。","https:\u002F\u002Fgithub.com\u002FShannonAI\u002Fservice-streamer\u002Fissues\u002F52",[]]