first add
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.venv/
|
||||
Qwen-Agent/
|
||||
46
README.md
Normal file
46
README.md
Normal file
@@ -0,0 +1,46 @@
|
||||
## Agent
|
||||
|
||||
自建基于llama-box启动qwen3-code-flash-1M 的 AI Agent 代码仓库
|
||||
|
||||
|
||||
### llama-box 启动参数
|
||||
|
||||
注意:
|
||||
添加 --enable-reasoning:这个参数对 Qwen3 模型的工具调用非常重要,能够提升推理能力。
|
||||
添加 --jinja:这个参数用于加载 Jinja 模板,Qwen3 模型需要使用 Jinja 模板进行推理。、
|
||||
|
||||
启动参数参考:
|
||||
|
||||
```bash
|
||||
llama-box \
|
||||
--host 0.0.0.0 \
|
||||
--port 8080 \
|
||||
--model /Volumes/long990max/gpustack_data/unsloth/Qwen3-Coder-30B-A3B-Instruct-1M-GGUF/Qwen3-Coder-30B-A3B-Instruct-1M-UD-Q4_K_XL.gguf \
|
||||
--chat-template chatml \
|
||||
--jinja \
|
||||
--enable-reasoning \
|
||||
--flash-attn \
|
||||
--cache-type-k q4_0 \
|
||||
--cache-type-v q4_0 \
|
||||
--ctx-size 262144 \
|
||||
--gpu-layers 49 \
|
||||
--threads 12 \
|
||||
--threads-batch 16 \
|
||||
--threads-http 16 \
|
||||
--batch-size 1024 \
|
||||
--ubatch-size 1024 \
|
||||
--defrag-thold -1 \
|
||||
--no-context-shift
|
||||
```
|
||||
|
||||
### 安装环境
|
||||
|
||||
```bash
|
||||
uv venv --managed-python -p 3.12 --seed .venv
|
||||
source .venv/bin/activate
|
||||
git clone https://github.com/hotwa/Qwen-Agent
|
||||
cd Qwen-Agent
|
||||
uv pip install -e ./"[gui,rag,code_interpreter,mcp]"
|
||||
cd ..
|
||||
python qwen3_coder_with_qwen_agent.py
|
||||
```
|
||||
250
qwen3_coder_with_qwen_agent.py
Normal file
250
qwen3_coder_with_qwen_agent.py
Normal file
@@ -0,0 +1,250 @@
|
||||
"""
|
||||
Qwen3-Coder 使用 Qwen-Agent 框架测试示例
|
||||
|
||||
这个示例演示了如何使用 Qwen-Agent 框架调用 qwen3-coder 模型进行工具调用测试。
|
||||
|
||||
工具配置说明:
|
||||
1. MCP工具:通过'mcpServers'配置,需要安装对应的MCP服务器
|
||||
- time: 获取当前时间的MCP工具
|
||||
- fetch: 网络请求工具
|
||||
- filesystem: 文件系统操作工具
|
||||
这些工具需要额外安装对应的MCP服务器才能使用
|
||||
|
||||
2. 原生工具:Qwen-Agent内置的工具,直接可用
|
||||
- 'code_interpreter': 代码解释器,可以执行Python代码
|
||||
- 'image_gen': 图像生成工具
|
||||
- 'web_search': 网络搜索工具
|
||||
- 'calculator'或'python_executor': Python代码执行器(可作为计算器)
|
||||
|
||||
环境变量说明:
|
||||
- MAX_LLM_CALL_PER_RUN: 控制LLM调用的最大轮数(不是工具调用次数)
|
||||
这个限制是针对整个对话的LLM调用轮数,包括初始调用和后续基于工具结果的调用
|
||||
- MAX_TOOL_CALLS_PER_TURN: 控制每轮LLM输出中可触发的工具调用数量
|
||||
这个限制是针对单次LLM响应中可以触发的工具数量,防止模型一次性触发过多工具
|
||||
"""
|
||||
|
||||
import os
|
||||
# 设置环境变量以控制工具调用行为
|
||||
# MAX_LLM_CALL_PER_RUN: 控制LLM调用的最大轮数(不是工具调用次数)
|
||||
# MAX_TOOL_CALLS_PER_TURN: 控制每轮LLM输出中可触发的工具调用数量
|
||||
os.environ["MAX_LLM_CALL_PER_RUN"] = "8"
|
||||
os.environ["MAX_TOOL_CALLS_PER_TURN"] = "8"
|
||||
|
||||
import sys
|
||||
import traceback
|
||||
from pathlib import Path
|
||||
|
||||
# 添加项目路径到Python路径
|
||||
project_root = Path(__file__).parent.parent.parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
try:
|
||||
from qwen_agent.agents import Assistant
|
||||
from qwen_agent.gui import WebUI
|
||||
from qwen_agent.utils.output_beautify import typewriter_print
|
||||
except ImportError as e:
|
||||
print(f"❌ 导入失败: {e}")
|
||||
print("请确保已安装 qwen-agent: pip install qwen-agent")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def init_agent_service():
|
||||
"""初始化Agent服务"""
|
||||
# 配置API参数,使用OpenAI兼容模式
|
||||
llm_cfg = {
|
||||
'model': 'qwen3-coder-flash-1M',
|
||||
'model_server': 'https://ai.jmsu.top/v1',
|
||||
'api_key': 'gpustack_96d105073565a038_23d7fe2768b4b27f9d92ab4661452ade',
|
||||
'generate_cfg': {
|
||||
# 使用API的原生工具调用接口
|
||||
'temperature': 0.7,
|
||||
'top_p': 0.8,
|
||||
'fncall_prompt_type': 'qwen', # 对 Qwen3 通常更稳
|
||||
},
|
||||
}
|
||||
|
||||
# 配置工具
|
||||
tools = [
|
||||
{
|
||||
'mcpServers': { # 指定MCP配置
|
||||
'time': {
|
||||
'command': 'uvx',
|
||||
'args': ['mcp-server-time', '--local-timezone=Asia/Shanghai']
|
||||
},
|
||||
'fetch': {
|
||||
'command': 'uvx',
|
||||
'args': ['mcp-server-fetch']
|
||||
},
|
||||
'filesystem': {
|
||||
'command': 'npx',
|
||||
'args': [
|
||||
'-y',
|
||||
'@modelcontextprotocol/server-filesystem',
|
||||
'~/Desktop/'
|
||||
]
|
||||
},
|
||||
}
|
||||
},
|
||||
# 添加一些原生工具示例
|
||||
'code_interpreter', # 代码解释器
|
||||
'web_search', # 网络搜索
|
||||
]
|
||||
|
||||
# 创建Agent
|
||||
bot = Assistant(
|
||||
llm=llm_cfg,
|
||||
function_list=tools,
|
||||
name='Qwen3-Coder Tool-calling Demo',
|
||||
description="I'm a demo using the Qwen3-Coder tool calling. Welcome to add and play with your own tools!"
|
||||
)
|
||||
|
||||
return bot
|
||||
|
||||
|
||||
def test(query: str = '现在几点了?'):
|
||||
"""测试函数"""
|
||||
print("=== Qwen3-Coder 使用 Qwen-Agent 测试 ===\n")
|
||||
|
||||
# 初始化Agent
|
||||
bot = init_agent_service()
|
||||
|
||||
# 进行对话
|
||||
messages = [{'role': 'user', 'content': query}]
|
||||
|
||||
print(f"💬 用户: {query}")
|
||||
print("🤖 助手: ", end='', flush=True)
|
||||
|
||||
# 缓存最终回复内容
|
||||
final_response = ""
|
||||
current_tool_call = ""
|
||||
in_tool_call = False
|
||||
|
||||
try:
|
||||
for response in bot.run(messages=messages):
|
||||
# 处理响应
|
||||
if response:
|
||||
for msg in response:
|
||||
if msg['role'] == 'assistant':
|
||||
if msg.get('content'):
|
||||
# 检查是否包含工具调用标记
|
||||
if '[TOOL_CALL]' in msg['content']:
|
||||
in_tool_call = True
|
||||
current_tool_call = msg['content']
|
||||
# 清空之前的输出,准备显示工具调用
|
||||
print(f"\r🤖 助手: {msg['content']}", end='', flush=True)
|
||||
elif in_tool_call:
|
||||
# 继续工具调用信息
|
||||
current_tool_call += msg['content']
|
||||
print(msg['content'], end='', flush=True)
|
||||
else:
|
||||
# 普通回复内容
|
||||
final_response += msg['content']
|
||||
# 不再实时打印,等待工具调用完成后统一显示
|
||||
# print(msg['content'], end='', flush=True)
|
||||
elif msg['role'] == 'function':
|
||||
# 工具响应,显示工具结果
|
||||
in_tool_call = False
|
||||
print(f"\n[TOOL_RESPONSE] {msg.get('name', 'unknown')}")
|
||||
print(msg.get('content', ''))
|
||||
# 重置最终回复内容,准备接收新的回复
|
||||
final_response = ""
|
||||
|
||||
# 输出最终结果
|
||||
if final_response:
|
||||
print("\r🤖 助手: ", end='', flush=True)
|
||||
print(final_response, end='', flush=True)
|
||||
print() # 输出完成后换行
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n❌ 调用失败: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
def app_tui():
|
||||
"""命令行交互模式"""
|
||||
print("=== Qwen3-Coder 使用 Qwen-Agent 命令行交互模式 ===\n")
|
||||
|
||||
# 初始化Agent
|
||||
bot = init_agent_service()
|
||||
|
||||
# 进行对话
|
||||
messages = []
|
||||
while True:
|
||||
query = input('user question: ')
|
||||
if query.lower() in ['quit', 'exit', '退出']:
|
||||
print("👋 再见!")
|
||||
break
|
||||
|
||||
messages.append({'role': 'user', 'content': query})
|
||||
response = []
|
||||
response_plain_text = ''
|
||||
print("🤖 助手: ", end='', flush=True)
|
||||
try:
|
||||
for response in bot.run(messages=messages):
|
||||
# 添加调试信息
|
||||
# print(f"[DEBUG] 收到响应: {type(response)}", file=sys.stderr)
|
||||
|
||||
# 使用 typewriter_print 实现流式输出
|
||||
if response:
|
||||
try:
|
||||
response_plain_text = typewriter_print(response, response_plain_text)
|
||||
except Exception as e:
|
||||
# 如果typewriter_print出错,尝试直接打印
|
||||
# print(f"[WARNING] typewriter_print出错: {e}", file=sys.stderr)
|
||||
if isinstance(response, list):
|
||||
for item in response:
|
||||
if isinstance(item, dict) and 'content' in item:
|
||||
print(item['content'], end='', flush=True)
|
||||
elif isinstance(item, dict) and 'message' in item:
|
||||
print(item['message'], end='', flush=True)
|
||||
print() # 输出完成后换行
|
||||
messages.extend(response)
|
||||
except Exception as e:
|
||||
print(f"\n❌ 调用失败: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
def app_gui():
|
||||
"""图形界面模式"""
|
||||
# 初始化Agent
|
||||
bot = init_agent_service()
|
||||
chatbot_config = {
|
||||
'prompt.suggestions': [
|
||||
'现在几点了?',
|
||||
'请用Python写一个计算斐波那契数列的函数',
|
||||
'帮我搜索一下Python装饰器的用法'
|
||||
]
|
||||
}
|
||||
WebUI(
|
||||
bot,
|
||||
chatbot_config=chatbot_config,
|
||||
).run()
|
||||
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
print("🚀 Qwen3-Coder 使用 Qwen-Agent 测试示例")
|
||||
print("=" * 50)
|
||||
|
||||
print("\n请选择运行模式:")
|
||||
print("1. 简单测试 - 固定问题")
|
||||
print("2. 命令行交互模式")
|
||||
print("3. 图形界面模式")
|
||||
|
||||
choice = input("\n请输入选项 (1-3): ").strip()
|
||||
|
||||
if choice == "1":
|
||||
test()
|
||||
elif choice == "2":
|
||||
app_tui()
|
||||
elif choice == "3":
|
||||
app_gui()
|
||||
else:
|
||||
print("❌ 无效选项,运行默认测试")
|
||||
test()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user