Этап 2: Интеграция с qwen-code и opencode

This commit is contained in:
mirivlad 2026-03-17 03:21:44 +08:00
parent 481ad8dddc
commit 85e702ce25
3 changed files with 94 additions and 4 deletions

View File

@ -3,6 +3,7 @@ import logging
from telegram import Update from telegram import Update
from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes
from config.config import get_settings from config.config import get_settings
from src.tools.tool_runner import ToolRunner
logging.basicConfig( logging.basicConfig(
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
@ -11,6 +12,7 @@ logging.basicConfig(
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
settings = get_settings() settings = get_settings()
tool_runner = ToolRunner()
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE): async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
@ -20,20 +22,44 @@ async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
) )
async def echo(update: Update, context: ContextTypes.DEFAULT_TYPE):
await update.message.reply_text(update.message.text)
async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE): async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
help_text = ( help_text = (
f"Я {settings.bot_name}, ваш ИИ-ассистент.\n\n" f"Я {settings.bot_name}, ваш ИИ-ассистент.\n\n"
"Доступные команды:\n" "Доступные команды:\n"
"/start - Начать работу\n" "/start - Начать работу\n"
"/help - Показать эту справку\n" "/help - Показать эту справку\n"
"/qwen <текст> - Задать вопрос qwen-code\n"
"/open <текст> - Задать вопрос opencode\n"
) )
await update.message.reply_text(help_text) await update.message.reply_text(help_text)
async def qwen_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
prompt = " ".join(context.args)
if not prompt:
await update.message.reply_text("Использование: /qwen <текст>")
return
await update.message.reply_text("Думаю...")
result, success = await tool_runner.run_qwen(prompt)
await update.message.reply_text(result[:4096] if len(result) > 4096 else result)
async def open_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
prompt = " ".join(context.args)
if not prompt:
await update.message.reply_text("Использование: /open <текст>")
return
await update.message.reply_text("Думаю...")
result, success = await tool_runner.run_opencode(prompt)
await update.message.reply_text(result[:4096] if len(result) > 4096 else result)
async def echo(update: Update, context: ContextTypes.DEFAULT_TYPE):
await update.message.reply_text(update.message.text)
def main(): def main():
builder = Application.builder() builder = Application.builder()
builder.token(settings.telegram_bot_token) builder.token(settings.telegram_bot_token)
@ -46,6 +72,8 @@ def main():
application.add_handler(CommandHandler("start", start)) application.add_handler(CommandHandler("start", start))
application.add_handler(CommandHandler("help", help_command)) application.add_handler(CommandHandler("help", help_command))
application.add_handler(CommandHandler("qwen", qwen_command))
application.add_handler(CommandHandler("open", open_command))
application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, echo)) application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, echo))
logger.info("Бот запущен") logger.info("Бот запущен")

0
src/tools/__init__.py Normal file
View File

62
src/tools/tool_runner.py Normal file
View File

@ -0,0 +1,62 @@
import asyncio
import logging
from typing import Optional, Tuple
from config.config import get_settings
logger = logging.getLogger(__name__)
settings = get_settings()
class ToolRunner:
def __init__(self):
self.qwen_command = settings.qwen_command
self.opencode_command = settings.opencode_command
self.timeout = settings.tool_timeout
async def run_qwen(self, prompt: str) -> Tuple[str, bool]:
return await self._run_tool(self.qwen_command, prompt)
async def run_opencode(self, prompt: str) -> Tuple[str, bool]:
return await self._run_tool(self.opencode_command, prompt)
async def _run_tool(self, command: str, prompt: str) -> Tuple[str, bool]:
try:
process = await asyncio.create_subprocess_exec(
command,
prompt,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE
)
try:
stdout, stderr = await asyncio.wait_for(
process.communicate(),
timeout=self.timeout
)
except asyncio.TimeoutError:
process.kill()
await process.wait()
return "Превышен таймаут выполнения", False
stdout_str = stdout.decode() if stdout else ""
stderr_str = stderr.decode() if stderr else ""
if process.returncode != 0:
error_msg = stderr_str or stdout_str
return f"Ошибка выполнения: {error_msg}", False
return stdout_str, True
except FileNotFoundError:
return f"Инструмент {command} не найден. Убедитесь, что он установлен и доступен в PATH.", False
except Exception as e:
logger.exception("Ошибка при выполнении инструмента")
return f"Ошибка: {str(e)}", False
async def run_tool(self, tool_name: str, prompt: str) -> Tuple[str, bool]:
if tool_name == "qwen":
return await self.run_qwen(prompt)
elif tool_name == "opencode":
return await self.run_opencode(prompt)
else:
return f"Неизвестный инструмент: {tool_name}", False