FastAPI+OpenAI实现Telegram问答机器人

news/2025/3/11 11:02:46/文章来源:https://www.cnblogs.com/cnxue/p/18759034

首先要创建一个机器人,找到BotFather获取到机器人的Token
image
设置后台地址,实现消息转发

curl -X POST "https://api.telegram.org/bot{机器人token}/setWebhook?url=https://chat.xxxxxxxx.com/chat"

配置文件
.env

OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TELEGRAM_BOT_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
OPENAI_API_URL=https://api.openai.com/v1/chat/completions
REDIS_HOST= 127.0.0.1
REDIS_PORT= 6379
REDIS_PASSWD=12346

主程序
main.py

import json
import logging
import osimport httpx
from aioredis import Redis
from dotenv import load_dotenv
from fastapi import FastAPI, Request# 配置日志
logging.basicConfig(level=logging.INFO)load_dotenv()OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
OPENAI_API_URL = os.getenv("OPENAI_API_URL")
REDIS_HOST = os.getenv("REDIS_HOST", '127.0.0.1')
REDIS_PORT = os.getenv("REDIS_PORT", 6379)
REDIS_PASSWD = os.getenv("REDIS_PASSWD", '123456')
REDIS_DB = os.getenv("REDIS_DB", 10)
TELEGRAM_API_URL = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/"
CHAT_HISTORY_EXPIRE = 60 * 60 * 24  # 聊天记录保存24小时
GPT_MODEL = "gpt-4o"app = FastAPI(docs_url=None, redoc_url=None)# 异步Redis连接
redis_client = Redis(host=REDIS_HOST, port=REDIS_PORT, db=REDIS_DB, password=REDIS_PASSWD, decode_responses=True)async def get_chat_history(chat_id):chat_key = f"chat:{chat_id}"history = await redis_client.get(chat_key)if history:return json.loads(history)default_history = [{"role": "system", "content": "你是一个有帮助的助手"}]await redis_client.set(chat_key, json.dumps(default_history), ex=CHAT_HISTORY_EXPIRE)return default_historyasync def update_chat_history(chat_id, messages):chat_key = f"chat:{chat_id}"await redis_client.set(chat_key, json.dumps(messages), ex=CHAT_HISTORY_EXPIRE)async def clear_chat_history(chat_id):"""清除指定用户的聊天历史"""chat_key = f"chat:{chat_id}"await redis_client.delete(chat_key)async def call_openai_api(user_message: str, chat_id) -> str:messages = await get_chat_history(chat_id)headers = {"Authorization": f"Bearer {OPENAI_API_KEY}", "Content-Type": "application/json"}if len(messages) > 9:messages[1:3] = []messages.append({"role": "user", "content": user_message})data = {"model": GPT_MODEL, "messages": messages}try:async with httpx.AsyncClient(timeout=30) as client:response = await client.post(url=OPENAI_API_URL, headers=headers, json=data)result = response.json()assistant_reply = result["choices"][0]["message"]["content"]messages.append({"role": "assistant", "content": assistant_reply})await update_chat_history(chat_id, messages)return assistant_replyexcept httpx.HTTPStatusError as e:error_msg = f"API调用失败: HTTP {e.response.status_code}"logging.error(error_msg)return error_msgexcept Exception as e:error_msg = f"发生错误: {str(e)}"logging.error(error_msg)return error_msgasync def send_message(chat_id, text: str):async with httpx.AsyncClient() as client:await client.post(url=f"{TELEGRAM_API_URL}sendMessage",json={"chat_id": chat_id, "text": text})@app.get("/")
async def index():return {"msg": "Welcome ChatBot!!!"}@app.post("/chat")
async def webhook(request: Request):update = await request.json()try:chat_id = update["message"]["chat"]["id"]user_message = update["message"]["text"]if user_message.lower() == "/clear":await clear_chat_history(chat_id)await send_message(chat_id, "聊天历史已清除!")return {"status": "ok"}response_message = await call_openai_api(user_message, chat_id)await send_message(chat_id, response_message)return {"status": "ok"}except Exception as e:return {"status": "ok"}

启动程序

uvicorn main:app --host=0.0.0.0 --workers=4 --port=8000  --reload

效果
image

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/895445.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

dat格式和mmdb格式IP数据库下载源

MaxMind 提供了免费的 IP 地域数据库,早期的dat格式的ip库MaxMind 官方已经停止支持。 现在MaxMind 官方提供的mmdb格式需要注册后才能下载。 本文记录找到的其它下载源。 dat格式下载:https://www.miyuru.lk/geoiplegacy下载国家IP库(包含ipv4和ipv6),解压并重命名:wget …

Linux 平均负载 Load Average 详解

转载自Linux 平均负载 Load Average 详解_load average多少是正常-CSDN博客 一、什么是Load Average? 系统负载(System Load)是系统CPU繁忙程度的度量,即有多少进程在等待被CPU调度(进程等待队列的长度)。 平均负载(Load Average)是一段时间内系统的平均负载,这个一段…

Linux 中 sh -c

001、[root@PC1 test]# ls a.sh [root@PC1 test]# cat a.sh #!/bin/bash echo hello world [root@PC1 test]# sh -c bash a.sh ## 更新了系统环境变量? (base) [root@PC1 test]# (base) [root@PC1 test]# conda deactivate [root@PC1 test]# ls a.sh [root@PC1 test]#…

跑步名词

跑步名词 1. 跑步机上的速度6指的是多少跑步机上的速度指的是每小时几公里(km/h)所以跑步机上的速度“6”通常指的是每小时6公里(km/h)。 2. 配速是什么意思 配速(Pace)是跑步运动中常用的术语,指的是完成每公里(或每英里)需要几分钟。 它是衡量跑步速度的一种方式,通…

探秘Transformer系列之(11)--- 掩码

从零开始解析Transformer,目标是:(1) 解析Transformer如何运作,以及为何如此运作,让新同学可以入门;(2) 力争融入一些比较新的或者有特色的论文或者理念,让老鸟也可以有所收获。探秘Transformer系列之(11)--- 掩码 目录探秘Transformer系列之(11)--- 掩码0x00 概述0x…

私有云电脑的技术原理,干货多多

当我们谈论现代科技如何改变生活和工作时,远程连接无疑是一个重要的话题:它是一种能够让用户在远离设备物理位置的情况下,依然能够对其进行操作和管理的技术。通过远程连接,我们可以跨越城市、国家甚至洲际距离,实现对远程计算机、服务器、网络设备等的实时控制,这在很大…

NeoBERT:4096 tokens上下文窗口,参数更少但性能翻倍

NeoBERT代表了双向编码器模型的新一代技术发展,通过整合前沿架构改进、现代大规模数据集和优化的预训练策略,有效缩小了传统编码器与高性能自回归语言模型之间的性能差距。该模型在支持4096 tokens的扩展上下文窗口的同时,仅维持250M参数规模的紧凑设计。值得注意的是,尽管…

【第四章 定时任务】手把手教你玩转新版正点原子云

【第四章 定时任务】手把手教你玩转新版正点原子云 承接上篇,除了报警联动这个功能,原子云还有一个特色功能也是各开发者喜欢用的,定时任务功能。 【正点原子】云平台:原子云(点击登录原子云) 前言: 定时任务可以在云平台定时、定向地向设备发送数据。比如在设定好定时任…

IDEA-MyBatisCodeHelperPro插件免激活离线安装根据实体类创建create建表语句

MyBatisCodeHelperPro插件免激活离线安装&根据实体类创建create建表语句 通过网盘分享的文件:MyBatisCodeHelper-Pro.zip 链接: https://pan.baidu.com/s/1Yg-ENwXY0MseR2DjFu9uHQ?pwd=sky1 提取码: sky1 一、File -> Setting -> Plugin -> Install Plugin Disk…

优化Hyper-V:合理设定CPU核数的教程

优化Hyper-V虚拟机的CPU核数配置,是提高虚拟机性能和整体虚拟化环境效率的关键步骤。以下是一份详细的教程,指导您如何合理设定Hyper-V虚拟机的CPU核数。一、了解CPU核数配置的基本原则 根据工作负载需求设定: 轻量级应用:如文件共享、简单的Web服务等,通常分配1-2个虚拟C…

MYSQL-浅谈MYSQL加锁机制、锁分类

MYSQL-浅谈MYSQL加锁机制、锁分类 文章转载自:https://cloud.tencent.com/developer/article/2431018 一、概述 1.1、MySQL锁的由来 客户端发往MySQL的一条条SQL语句,实际上都可以理解成一个个单独的事务(一条SQL语句就是一个事务),而事务是基于数据库连接的,每个数据库连…