如何实现本地大模型与MCP集成
<h1>1.概述</h1><p>本文将围绕构建兼具本地运行大型语言模型(LLM)与MCP 集成能力的 AI 驱动工具展开,为读者提供从原理到实践的全流程指南。通过深度整合本地大模型的隐私性、可控性优势与 MCP 工具的自动化执行能力,帮助用户以低门槛、高效率的方式,打造个性化 AI 助手,实现任务自动化 —— 无论是文档处理、数据分析,还是流程调度等场景,均可通过这一集成方案,借助大模型的语义理解与推理能力,结合 MCP 工具的标准化接口,构建端到端的智能工作流,让 AI 真正成为提升生产力的核心引擎。</p>
<h1>2.内容</h1>
<h2>2.1 环境准备</h2>
<ul>
<li>ollama</li>
<li>python==3.13.2</li>
<li>uv 0.6.12</li>
<li>Linux / macOS</li>
</ul>
<p>大模型服务部署</p>
<ul>
<li>安装ollama服务框架</li>
<li>通过ollama部署所需的大语言模型</li>
</ul>
<p>开发环境配置</p>
<ul>
<li>准备Python 3.13运行环境(推荐使用最新稳定版)</li>
<li>安装mcp服务开发所需的Python包</li>
</ul>
<p>开发工具推荐</p>
<ul>
<li>使用uv工具链(新一代Python项目管理工具)</li>
<li>功能覆盖:
<ul>
<li>Python版本管理</li>
<li>虚拟环境控制</li>
<li>依赖包管理</li>
<li>项目依赖维护</li>
</ul>
</li>
<li>优势:提供全流程的Python开发环境管理方案</li>
</ul>
<h2>2.2 ollama安装</h2>
<p>访问ollama地址:https://ollama.com/,然后根据自己的环境下载对应的安装包,如下图所示:</p>
<p><img src="https://img2024.cnblogs.com/blog/666745/202505/666745-20250531191045515-1999840362.png" alt="" loading="lazy"></p>
<p>安装好ollama后,启动服务后,可以执行命令来检查服务是否启动成功,如下图所示:</p>
<p><img src="https://img2024.cnblogs.com/blog/666745/202505/666745-20250531191237899-238773271.png" alt="" loading="lazy"></p>
<p> 然后,我们在ollama的模型页面选择我们需要下载的大模型,可以根据自身机器的性能来选择不同规模的模型,如图所示:</p>
<p><img src="https://img2024.cnblogs.com/blog/666745/202505/666745-20250531191935032-1436115815.png" alt="" loading="lazy"></p>
<p> </p>
<p>安装完成对应的模型后,可以通过http://localhost:11434/api/tags访问查看安装在本地的模型信息,如图所示:</p>
<p><img src="https://img2024.cnblogs.com/blog/666745/202505/666745-20250531192356364-186606724.png" alt="" loading="lazy"></p>
<h2> 2.3 安装uv工具</h2>
<p>安装 uv(通常指 Rust 编写的超快 Python 包安装工具 uv,由 Astral 团队开发)的常用方法如下:</p>
<p><strong>1. 使用官方安装脚本(推荐)</strong><br>运行以下命令一键安装(适合 Linux/macOS):</p>
<div class="cnblogs_code">
<pre>curl -LsSf https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">astral.sh/uv/install.sh | sh</span></pre>
</div>
<p>安装后按提示将 uv 加入 PATH 环境变量,或直接重启终端。</p>
<p><strong>2. 通过 pip 安装</strong><br>如果已配置 Python 环境,可直接用 pip 安装:</p>
<div class="cnblogs_code">
<pre>pip <span style="color: rgba(0, 0, 255, 1)">install</span> uv</pre>
</div>
<p><strong>3. 验证安装</strong><br>运行以下命令检查是否成功:</p>
<div class="cnblogs_code">
<pre>uv --version</pre>
</div>
<h1>3.编写MCP服务</h1>
<p>环境准备好之后,我们就可以开始编写MCP服务了,这里我们编写一个简单的MCP服务,用于读取本地文件,实现代码如下所示:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> os
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> uvicorn
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> logging
</span><span style="color: rgba(0, 0, 255, 1)">from</span> dotenv <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> load_dotenv
</span><span style="color: rgba(0, 0, 255, 1)">from</span> argparse <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> ArgumentParser
</span><span style="color: rgba(0, 0, 255, 1)">from</span> mcp.server.fastmcp <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> FastMCP
</span><span style="color: rgba(0, 0, 255, 1)">from</span> starlette.applications <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> Starlette
</span><span style="color: rgba(0, 0, 255, 1)">from</span> starlette.requests <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> Request
</span><span style="color: rgba(0, 0, 255, 1)">from</span> starlette.routing <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> Route, Mount
</span><span style="color: rgba(0, 0, 255, 1)">from</span> mcp.server <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> Server
</span><span style="color: rgba(0, 0, 255, 1)">from</span> mcp.server.sse <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> SseServerTransport
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 配置日志</span>
<span style="color: rgba(0, 0, 0, 1)">logging.basicConfig(
level</span>=<span style="color: rgba(0, 0, 0, 1)">logging.INFO,
format</span>=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">%(asctime)s - %(name)s - %(levelname)s - %(message)s</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
)
logger </span>= logging.getLogger(<span style="color: rgba(128, 0, 128, 1)">__name__</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 加载环境变量</span>
<span style="color: rgba(0, 0, 0, 1)">load_dotenv()
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Config:
</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">应用配置类</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(0, 0, 0, 1)">
HOST </span>= os.getenv(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">HOST</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">0.0.0.0</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
PORT </span>= int(os.getenv(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">PORT</span><span style="color: rgba(128, 0, 0, 1)">'</span>, 8020<span style="color: rgba(0, 0, 0, 1)">))
DEBUG </span>= os.getenv(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">DEBUG</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">False</span><span style="color: rgba(128, 0, 0, 1)">'</span>).lower() == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">true</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
FILE_PATH </span>=<span style="color: rgba(0, 0, 0, 1)"> os.getenv(
</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">FILE_PATH</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">/Users/smartloli/workspace/vscode/1/data.txt</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 初始化MCP</span>
mcp = FastMCP(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">file_reader</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
@mcp.tool()
async </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> read_file():
</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
读取配置文件中的数据
Returns:
文件内容或错误信息
</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(0, 0, 0, 1)">
file_path </span>=<span style="color: rgba(0, 0, 0, 1)"> Config.FILE_PATH
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">:
logger.info(f</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Reading file: {file_path}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
with open(file_path, </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">r</span><span style="color: rgba(128, 0, 0, 1)">'</span>, encoding=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">utf-8</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">) as file:
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> file.read()
</span><span style="color: rgba(0, 0, 255, 1)">except</span><span style="color: rgba(0, 0, 0, 1)"> FileNotFoundError as e:
logger.error(f</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">File not found: {file_path}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">return</span> {<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">error</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">File not found</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">details</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: str(e)}
</span><span style="color: rgba(0, 0, 255, 1)">except</span><span style="color: rgba(0, 0, 0, 1)"> Exception as e:
logger.exception(f</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Error reading file: {file_path}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">return</span> {<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">error</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Unexpected error</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">details</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: str(e)}
</span><span style="color: rgba(0, 0, 255, 1)">def</span> create_starlette_app(mcp_server: Server) -><span style="color: rgba(0, 0, 0, 1)"> Starlette:
</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">创建基于Starlette的MCP服务器应用
Args:
mcp_server: MCP服务器实例
Returns:
Starlette应用实例
</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(0, 0, 0, 1)">
sse </span>= SseServerTransport(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/messages/</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
async </span><span style="color: rgba(0, 0, 255, 1)">def</span> handle_sse(request: Request) -><span style="color: rgba(0, 0, 0, 1)"> None:
async with sse.connect_sse(
request.scope,
request.receive,
request._send
) as (read_stream, write_stream):
await mcp_server.run(
read_stream,
write_stream,
mcp_server.create_initialization_options(),
)
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Starlette(
debug</span>=<span style="color: rgba(0, 0, 0, 1)">Config.DEBUG,
routes</span>=<span style="color: rgba(0, 0, 0, 1)">[
Route(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/sse</span><span style="color: rgba(128, 0, 0, 1)">"</span>, endpoint=<span style="color: rgba(0, 0, 0, 1)">handle_sse),
Mount(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/messages/</span><span style="color: rgba(128, 0, 0, 1)">"</span>, app=<span style="color: rgba(0, 0, 0, 1)">sse.handle_post_message),
],
on_startup</span>=[<span style="color: rgba(0, 0, 255, 1)">lambda</span>: logger.info(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Server starting...</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)],
on_shutdown</span>=[<span style="color: rgba(0, 0, 255, 1)">lambda</span>: logger.info(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Server shutting down...</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)]
)
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> parse_arguments():
</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">解析命令行参数</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(0, 0, 0, 1)">
parser </span>= ArgumentParser(description=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Run MCP SSE-based server</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
parser.add_argument(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">--host</span><span style="color: rgba(128, 0, 0, 1)">'</span>, default=Config.HOST, help=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Host to bind to</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
parser.add_argument(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">--port</span><span style="color: rgba(128, 0, 0, 1)">'</span>, type=<span style="color: rgba(0, 0, 0, 1)">int,
default</span>=Config.PORT, help=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Port to listen on</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
parser.add_argument(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">--debug</span><span style="color: rgba(128, 0, 0, 1)">'</span>, action=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">store_true</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
help</span>=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Enable debug mode</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> parser.parse_args()
</span><span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(128, 0, 128, 1)">__name__</span> == <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">__main__</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">:
args </span>=<span style="color: rgba(0, 0, 0, 1)"> parse_arguments()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 更新配置</span>
Config.HOST =<span style="color: rgba(0, 0, 0, 1)"> args.host
Config.PORT </span>=<span style="color: rgba(0, 0, 0, 1)"> args.port
Config.DEBUG </span>=<span style="color: rgba(0, 0, 0, 1)"> args.debug
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 启动服务器</span>
mcp_server =<span style="color: rgba(0, 0, 0, 1)"> mcp._mcp_server
starlette_app </span>=<span style="color: rgba(0, 0, 0, 1)"> create_starlette_app(mcp_server)
logger.info(f</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Starting server on {Config.HOST}:{Config.PORT}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
uvicorn.run(
starlette_app,
host</span>=<span style="color: rgba(0, 0, 0, 1)">Config.HOST,
port</span>=<span style="color: rgba(0, 0, 0, 1)">Config.PORT,
log_level</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">info</span><span style="color: rgba(128, 0, 0, 1)">"</span> <span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(0, 0, 255, 1)">not</span> Config.DEBUG <span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">debug</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
)</span></pre>
</div>
<p> </p>
<p>然后,我们使用uv来启动MCP服务,执行命令如下:</p>
<div class="cnblogs_code">
<pre>uv run file_list.py --host 0.0.0.0 --port 8020</pre>
</div>
<p>启动成功后,显示如下图所示信息:</p>
<p><img src="https://img2024.cnblogs.com/blog/666745/202505/666745-20250531193601661-1044786069.png" alt="" loading="lazy"></p>
<h1>4.集成LLM 和 MCP</h1>
<p> 准备好LLM服务和MCP服务之后,我们在Cherry Studio客户端上集成我们本地部署的LLM 和 MCP 服务,如下图所示:</p>
<p><strong>1.配置本地文件搜索MCP服务</strong></p>
<p><img src="https://img2024.cnblogs.com/blog/666745/202505/666745-20250531194356582-1051601961.png" alt="" loading="lazy"></p>
<p> <strong>2.集成本地LLM</strong></p>
<p><img src="https://img2024.cnblogs.com/blog/666745/202505/666745-20250531194536217-1948810406.png" alt="" loading="lazy"></p>
<p> 然后,在设置里面勾选“工具”就可以使用MCP服务了,如图所示:</p>
<p><img src="https://img2024.cnblogs.com/blog/666745/202505/666745-20250531194700143-951741171.png" alt="" loading="lazy"></p>
<p><strong> 3.测试本地LLM回答</strong></p>
<p><img src="https://img2024.cnblogs.com/blog/666745/202505/666745-20250531200016556-1705855351.png" alt="" loading="lazy"></p>
<p><strong> 4.测试本地LLM & MCP调用</strong></p>
<p><img src="https://img2024.cnblogs.com/blog/666745/202505/666745-20250531200748456-366627597.png" alt="" loading="lazy"></p>
<p> 当我们开启MCP服务后,输入的搜索词中LLM会自行判断是否需要调用本地的MCP服务,这里我们通过搜索词触发LLM通过function去调用本地MCP服务。</p>
<h1>5.总结</h1>
<p>本文围绕本地大模型与模型上下文协议(MCP)的集成展开探索,重点揭示了通过 MCP 构建自定义 AI 工具的路径。通过适配不同开发环境与实际用例,MCP 为 AI 功能的跨场景整合提供了灵活框架,其核心优势体现在定制化能力上 —— 从模型选型到集成策略的全流程可调节性,使开发者能够基于具体需求打造精准适配的 AI 解决方案,展现了 MCP 在整合本地大模型时的多功能性与实践价值。</p>
<h1>6.结束语</h1>
<p>这篇博客就和大家分享到这里,如果大家在研究学习的过程当中有什么问题,可以加群进行讨论或发送邮件给我,我会尽我所能为您解答,与君共勉!</p>
<p>另外,博主出新书了《<span style="color: rgba(255, 0, 0, 1)"><strong><span style="color: rgba(255, 0, 0, 1)">Hadoop与Spark大数据全景解析</span></strong></span>》、同时已出版的《<span style="color: rgba(0, 0, 255, 1)"><strong><span style="color: rgba(0, 0, 255, 1)">深入理解Hive</span></strong></span>》、《<span style="color: rgba(0, 0, 255, 1)"><strong><span style="color: rgba(0, 0, 255, 1)">Kafka并不难学</span></strong></span>》和《<span style="color: rgba(0, 0, 255, 1)"><strong><span style="color: rgba(0, 0, 255, 1)">Hadoop大数据挖掘从入门到进阶实战</span></strong></span>》也可以和新书配套使用,喜欢的朋友或同学, 可以<span style="color: rgba(255, 0, 0, 1)"><strong>在公告栏那里点击购买链接购买博主的书</strong></span>进行学习,在此感谢大家的支持。关注下面公众号,根据提示,可免费获取书籍的教学视频。</p>
</div>
<div id="MySignature" role="contentinfo">
<div>
<b class="b1"></b><b class="b2 d1"></b><b class="b3 d1"></b><b class="b4 d1"></b>
<div class="b d1 k">
联系方式:
<br/>
邮箱:smartloli.org@gmail.com
<br/>
<strong style="color: green">QQ群(Hive与AI实战【新群】):935396818</strong>
<br/>
QQ群(Hadoop - 交流社区1):424769183
<br/>
QQ群(Kafka并不难学):825943084
<br/>
温馨提示:请大家加群的时候写上加群理由(姓名+公司/学校),方便管理员审核,谢谢!
<br/>
<h3>热爱生活,享受编程,与君共勉!</h3>
</div>
<b class="b4b d1"></b><b class="b3b d1"></b><b class="b2b d1"></b><b class="b1b"></b>
</div>
<br>
<div>
<b class="b1"></b><b class="b2 d1"></b><b class="b3 d1"></b><b class="b4 d1"></b>
<div class="b d1 k">
<h3>公众号:</h3>
<h3><img style="width: 8%; margin-left: 10px" src="https://www.cnblogs.com/images/cnblogs_com/smartloli/1324636/t_qr.png"></h3>
</div>
<b class="b4b d1"></b><b class="b3b d1"></b><b class="b2b d1"></b><b class="b1b"></b>
</div>
<br>
<div>
<b class="b1"></b><b class="b2 d1"></b><b class="b3 d1"></b><b class="b4 d1"></b>
<div class="b d1 k">
<h3>作者:哥不是小萝莉 [关于我][犒赏]</h3>
<h3>出处:http://www.cnblogs.com/smartloli/</h3>
<h3>转载请注明出处,谢谢合作!</h3>
</div>
<b class="b4b d1"></b><b class="b3b d1"></b><b class="b2b d1"></b><b class="b1b"></b>
</div><br><br>
来源:https://www.cnblogs.com/smartloli/p/18905572
頁:
[1]