用自然语言玩转uArm机械臂?这个机械臂大模型MCP控制系统源码项目让你轻松上车LLM+具身智能开发(下)

一、前言

你是否曾梦想过像科幻电影里那样,用说话就能指挥机械臂干活?现在这个梦想在VREP仿真环境里成真啦!今天要给大家分享一个超酷的项目——基于MCP协议的uArm机械臂自然语言控制系统,让你只需动口就能玩转三轴机械臂,完全不用写复杂代码,小白也能轻松上手!
在这里插入图片描述
接着上篇,这篇来好好唠唠怎么手动实现一个大模型MCP客户端。咱就对着这段代码一步步拆解,把它搞明白。

直接上代码:

二、代码开头部分

import asyncio
from typing import Optional
from contextlib import AsyncExitStack

from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from mcp.client.sse import sse_client

#from anthropic import Anthropic
from dotenv import load_dotenv
from openai import OpenAI

import json

这部分就是导入各种需要用的库。asyncio 是用来处理异步操作的,这在和服务器通信的时候特别有用,能提高效率。OpenAI 这个库让我们能方便地调用大模型API。dotenv 可以帮我们加载环境变量,保证代码的安全性。

三、 大模型配置

#阿里百炼
LLM = OpenAI(
    api_key="sk-206236c9bc694c94a8f根据申请8b93",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)

load_dotenv()

这里配置了大模型,用的是阿里百炼的模型。你得把 api_key 换成你自己申请的,这样才能正常调用模型。load_dotenv() 会把 .env 文件里的环境变量加载进来。

四、 MCPClient 类

class MCPClient:
    def __init__(self):
        self.session: Optional[ClientSession] = None
        self.exit_stack = AsyncExitStack()
        self.llm=LLM

MCPClient 类是整个客户端的核心。在初始化方法里,我们设置了会话 session 初始为 Noneexit_stack 用来管理异步上下文,llm 就是我们前面配置好的大模型。

连接服务器方法

    async def connect_to_sse_server(self, server_url: str):
        self._streams_context = sse_client(url=server_url)
        streams = await self._streams_context.__aenter__()
        self._session_context = ClientSession(*streams)
        self.session: ClientSession = await self._session_context.__aenter__()
        await self.session.initialize()

    async def connect_to_server(self, server_script_path: str):
        is_python = server_script_path.endswith('.py')
        is_js = server_script_path.endswith('.js')
        if not (is_python or is_js):
            raise ValueError("Server script must be a .py or .js file")
        command = "python" if is_python else "node"
        server_params = StdioServerParameters(
            command=command,
            args=[server_script_path],
            env=None
        )
        stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params))
        self.stdio, self.write = stdio_transport
        self.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write))
        await self.session.initialize()
        response = await self.session.list_tools()
        tools = response.tools
        print("\nConnected to server with tools:", [tool.name for tool in tools])

这里有两个连接服务器的方法。connect_to_sse_server 是用SSE(Server-Sent Events)协议连接服务器,能实现服务器向客户端实时推送消息。connect_to_server 则是根据服务器脚本的类型(Python 或者 JavaScript)来启动服务器,然后连接上去,还会列出服务器上可用的工具。

处理查询方法

    async def process_query(self, query: str) -> str:
        messages = [
            {
                "role": "user",
                "content": query
            }
        ]
        response = await self.session.list_tools()
        available_tools = [
            {
                "type": "function",
                "function": { 
                    "name": tool.name,
                    "description": tool.description,            
                    "parameters":tool.inputSchema
                } 
            } for tool in response.tools]
        qwen_response = self.llm.chat.completions.create(
            model="qwen-turbo",
            messages=messages,
            temperature=0.6,
            top_p=0.7,
            max_tokens=4096,
            tools=available_tools,
        )
        assistant_output = qwen_response.choices[0].message
        if  assistant_output.content is None:
            assistant_output.content = ""
            return "llm no respones\n".join(final_text)
        else:
            if assistant_output.tool_calls == None:
                print(f"无需调用工具")
                final_text.append(assistant_output.content)
                messages.append({
                      "role": "assistant",
                      "content": assistant_output.content
                    })
            else:
                tool_name = assistant_output.tool_calls[0].function.name
                tool_args = json.loads(assistant_output.tool_calls[0].function.arguments)
                print(f"call mcp server tool:\n tool_name:{tool_name}\n tool_args:{tool_args}")
                result = await self.session.call_tool(tool_name, tool_args)
                final_text.append(f"[Calling tool {tool_name} with args {tool_args}]")
                messages.append({
                    "role": "user", 
                    "content": result.content
                })
                messages.append({
                    "role": "system",
                    "content": "请只回答与当前任务直接相关的内容,不要输出任何其他信息。直接给出对工具调用结果的分析。"
                })
                qwen_response = self.llm.chat.completions.create(
                    model="qwen-turbo",
                    max_tokens=1000,
                    messages=messages,                   
                )   
                final_text.append(qwen_response.choices[0].message.content)
            return "\n".join(final_text)

process_query 方法用来处理用户的查询。首先把用户的查询封装成消息,然后列出服务器上可用的工具。接着调用大模型 qwen-turbo 来处理查询。如果模型返回的结果不需要调用工具,就直接把结果返回;如果需要调用工具,就调用服务器上的工具,把工具调用结果再传给模型,让模型继续处理,最后把所有结果拼接起来返回。

聊天循环方法

    async def chat_loop(self):
        print("\nMCP Client Started!")
        print("Type your queries or 'quit' to exit.")
        while True:
            try:
                query = input("\nQuery: ").strip()
                if query.lower() == 'quit':
                    break
                response = await self.process_query(query)
                print("\n" + response)
            except Exception as e:
                print(f"\nError: {str(e)}")

chat_loop 方法实现了一个交互式的聊天循环。程序启动后,会提示你输入查询内容,你输入 quit 就可以退出。每次输入查询后,程序会调用 process_query 方法处理查询,并把结果打印出来。

清理资源方法

    async def cleanup(self):
        await self.exit_stack.aclose()

cleanup 方法用来清理资源,关闭异步上下文。

五、主函数

async def main():
    if len(sys.argv) < 2:
        print("Usage: python client.py <path_to_server_script> or <sse url such as :http://localhost:9900/sse>")
        sys.exit(1)
    client = MCPClient()
    try:
        await client.connect_to_sse_server(sys.argv[1])
        await client.chat_loop()
    finally:
        await client.cleanup()

if __name__ == "__main__":
    import sys
    asyncio.run(main())

主函数 main 会检查命令行参数,如果参数不够,会提示你正确的使用方法。然后创建 MCPClient 实例,连接服务器,启动聊天循环,最后在程序结束时清理资源。

好啦,到这里整个大模型MCP客户端的核心代码就拆解完了。大家要是有兴趣,可以自己动手试试,搞出一个属于自己的客户端!

大模型+MCP服务让机械臂听懂人话

最后

这个项目把大模型的“智能”和机械臂的“精准”结合得恰到好处,真正实现了“自然语言控制硬件”的轻量化方案。不管你是机械臂爱好者、AI开发者,还是单纯觉得好玩的极客,都可以试试——毕竟,用说话就能指挥机械臂的感觉,真的太酷了!

赶紧下载项目源代码,启动你的“LLM智能机械臂之旅”吧~
下载相关资源

  1. vrep机械臂仿真环境连接本站地址
  2. 机械臂MCP服务器及机械臂逆解python程序源码及虚拟环境地址
  3. 机械臂MCP自然语言交互客户端python程序源码及虚拟环境地址

(项目版权归FEI PANFENG所有,欢迎垂询!)

-----------------本篇完------------------

PS.扩展阅读

————————————————————————————————————————

对于python机器人编程感兴趣的小伙伴,可以进入如下链接阅读相关咨询

ps1.六自由度机器人相关文章资源

(1) 对六自由度机械臂的运动控制及python实现(附源码)
在这里插入图片描述

(2) N轴机械臂的MDH正向建模,及python算法
在这里插入图片描述

ps2.四轴机器相关文章资源

(1) 文章:python机器人编程——用python实现一个写字机器人
在这里插入图片描述

在这里插入图片描述

(2)python机器人实战——0到1创建一个自动是色块机器人项目-CSDN直播

(3)博文《我从0开始搭建了一个色块自动抓取机器人,并实现了大模型的接入和语音控制-(上基础篇)》的vrep基础环境
(3)博文《我从0开始搭建了一个色块自动抓取机器人,并实现了大模型的接入和语音控制-(上基础篇)》的vrep基础环境
(4)实现了语音输入+大模型指令解析+机器视觉+机械臂流程打通
在这里插入图片描述
在这里插入图片描述

ps3.移动小车相关文章资源

(1)python做了一个极简的栅格地图行走机器人,到底能干啥?[第五弹]——解锁蒙特卡洛定位功能-CSDN博客
(2) 对应python资源:源码地址
在这里插入图片描述
在这里插入图片描述

(3)python机器人编程——差速AGV机器、基于视觉和预测控制的循迹、自动行驶(上篇)_agv编程-CSDN博客
(4)python机器人编程——差速AGV机器、基于视觉和预测控制的循迹、自动行驶(下篇)_agv路线规划原则python-CSDN博客
对应python及仿真环境资源:源码链接
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

ps3.wifi小车控制相关文章资源

web端配套资源源代码已经上传(竖屏版),下载地址
仿真配套资源已经上传:下载地址
web端配套资源源代码已经上传(横屏版),下载地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

机智新语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值