Centos7本地部署阿里Qwen2-7B模型

1.从hagging face下载模型

2.把下载的模型文件,放到/usr/local/Qwen2-7B目录下

3.创建虚拟环境,安装依赖

1.环境安装
sudo yum update -y
sudo yum install -y python3 python3-pip git

2.创建虚拟环境并激活
python3 -m venv qwen2_env
source qwen2_env/bin/activate

conda activate  qwen2_env

conda install numpy transformers torch langchain sentence-transformers jieba requests streamlit

3.将diet_ui.py文件放到根目录下

import streamlit as st
import requests
import re
import logging
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
from langchain.memory import ConversationBufferMemory
from langchain.chains import LLMChain
from langchain.llms import HuggingFacePipeline
from langchain.prompts import PromptTemplate
from transformers import pipeline
from sentence_transformers import SentenceTransformer, models
import numpy as np
import jieba# 配置日志记录
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')# 加载 Qwen2 模型和分词器
try:tokenizer = AutoTokenizer.from_pretrained("/usr/local/Qwen2-7B", trust_remote_code=True)model = AutoModelForCausalLM.from_pretrained("/usr/local/Qwen2-7B", device_map="auto", trust_remote_code=True).eval()logging.info("分词器和模型加载成功")
except Exception as e:logging.error(f"加载分词器或模型时发生错误: {e}")raise# 公司业务接口地址
PORTFOLIO_API_URL = "https://xxxxx/plugin/portfolio"# 扩充关键词列表
KEYWORDS = ["方案", "配餐", "计划", "饮食安排", "食谱", "卡路里", "餐单", "膳食"]
# 允许的话题列表,添加配餐相关关键词
ALLOWED_TOPICS = ["健康", "营养", "饮食", "订单", "优惠券", "吃饭", "运动", "养生", "客服"] + KEYWORDS# 初始化会话记忆,最多存储 10 轮对话
memory = ConversationBufferMemory(k=10)# 创建 HuggingFacePipeline
pipe = pipeline("text-generation",model=model,tokenizer=tokenizer,max_new_tokens=500,do_sample=True,top_p=0.85,temperature=0.35
)
llm = HuggingFacePipeline(pipeline=pipe)# 创建一个简单的提示模板
prompt_template = PromptTemplate(input_variables=["input"],template="{input}"
)# 创建 LLMChain
chain = LLMChain(llm=llm, memory=memory, prompt=prompt_template)# 加载知识库
def load_knowledge_base(file_path):with open(file_path, 'r', encoding='utf-8') as file:lines = file.readlines()knowledge_base = []question = Noneanswer = ""for line in lines:line = line.strip()if line.startswith("Q:"):if question is not None:knowledge_base.append((question, answer))question = line[2:]answer = ""elif line.startswith("A:"):answer = line[2:]else:answer += line + " "if question is not None:knowledge_base.append((question, answer))return knowledge_base# 加载知识库
knowledge_base = load_knowledge_base("/root/knowledge_base.txt")# 手动加载模型组件
word_embedding_model = models.Transformer('/root/all-MiniLM-L6-v2')
pooling_model = models.Pooling(word_embedding_model.get_word_embedding_dimension())
encoder = SentenceTransformer(modules=[word_embedding_model, pooling_model])# 编码知识库中的问题
question_embeddings = [encoder.encode(question) for question, _ in knowledge_base]# 提取关键词
def extract_keywords(text):return list(jieba.cut(text))# 从知识库查找答案(结合关键词匹配和向量相似度)
def find_answer_from_knowledge_base(question, threshold=0.5):question_keywords = extract_keywords(question)question_embedding = encoder.encode(question)best_match_index = -1best_similarity = -1for i, (kb_question, _) in enumerate(knowledge_base):kb_keywords = extract_keywords(kb_question)# 检查关键词是否匹配if any(keyword in kb_keywords for keyword in question_keywords):similarity = np.dot(question_embedding, question_embeddings[i]) / (np.linalg.norm(question_embedding) * np.linalg.norm(question_embeddings[i]))if similarity > best_similarity and similarity >= threshold:best_similarity = similaritybest_match_index = iif best_match_index != -1:return knowledge_base[best_match_index][1]return None# 提取配餐参数
def extract_params(text):calory = Noneday = None# 优化后的卡路里提取正则表达式calory_pattern = re.compile(r'(?:每天|每日|每餐)?\s*(?:卡路里|热量|千卡|大卡)\s*(?:是|约|大概|为)?\s*(\d+)', re.IGNORECASE)# 优化后的天数提取正则表达式day_pattern = re.compile(r'(?:配|安排|制定)?\s*(\d+)\s*(?:天|日|天的餐|日的餐)', re.IGNORECASE)calory_match = calory_pattern.search(text)if calory_match:try:calory = int(calory_match.group(1))except ValueError:passday_match = day_pattern.search(text)if day_match:try:day = int(day_match.group(1))except ValueError:passreturn calory, day# 调用配餐接口
def get_meal_plan(calory, day):logging.debug(f"准备调用配餐接口,calory: {calory}, day: {day}")try:response = requests.get(PORTFOLIO_API_URL, params={"calory": calory, "day": day})logging.debug(f"接口响应状态码: {response.status_code}")logging.debug(f"接口响应内容: {response.text}")if response.status_code == 200:logging.debug("配餐接口调用成功")try:response_data = response.json()# 打印完整的响应数据,用于调试logging.debug(f"完整的接口响应数据: {response_data}")# 提取配餐方案信息sku_list = response_data.get("skuList", [])if sku_list:output_text = "以下是为您生成的配餐方案:\n"output_text += "=" * 50 + "\n"current_day = 0for sku in sku_list:sequential_days = sku.get("sequentialDays")if sequential_days is None:logging.warning("配餐数据中缺少 sequentialDays 字段")continueif sequential_days != current_day:current_day = sequential_daysoutput_text += f"\n第 {current_day} 天:\n"output_text += "-" * 50 + "\n"category_type = sku.get("categoryType", "未知餐别")total_kcal = sku.get("totalKcal", "未知热量")output_text += f"  {category_type}({total_kcal} 千卡):\n"meal_list = sku.get("list", [])for meal in meal_list:meal_name = meal.get("name", "未知套餐")output_text += f"    套餐名称:{meal_name}\n"output_text += "    包含菜品:\n"category_list = meal.get("getCategoryList", [])for item in category_list:skuname = item.get("skuname", "未知菜品")price = item.get("price", "未知价格")energy = item.get("energy", "未知能量")output_text += f"      - {skuname}(价格:{price} 元,能量:{energy} 千卡)\n"output_text += "=" * 50 + "\n"else:output_text = "获取配餐方案成功,但无具体信息"return output_textexcept ValueError:logging.error("无法将接口响应内容解析为 JSON 格式")return "调用接口成功,但无法解析响应内容"else:logging.error(f"配餐接口调用失败,状态码: {response.status_code}")return f"调用接口失败,状态码: {response.status_code}"except requests.RequestException as e:logging.error(f"调用配餐接口时发生网络错误: {e}")return f"调用接口时发生网络错误: {e}"# Streamlit UI
st.title("Nutribite 智能营养师聊天机器人")# 初始化聊天历史
if 'chat_history' not in st.session_state:st.session_state.chat_history = []# 初始化输入框值
if 'input_value' not in st.session_state:st.session_state.input_value = ""# 获取用户输入
user_input = st.text_input("请输入你的问题", value=st.session_state.input_value, key="input_key")if user_input:# 拼接历史对话和当前输入history_text = "\n".join([f"用户: {msg['user']}\n机器人: {msg['bot']}" for msg in st.session_state.chat_history]) + "\n" + user_inputlogging.debug(f"拼接后的文本: {history_text}")# 检查是否处于配餐流程中is_in_meal_process = "配餐" in history_text and ("请问,要配几天的餐?" in history_text or "请问每天的卡路里大概是多少?" in history_text)# 检查是否是允许的话题if not any(topic in history_text for topic in ALLOWED_TOPICS) and not is_in_meal_process:bot_response = "我是Nutribite智能營養師,請問我相關問題"else:# 从知识库查找答案answer = find_answer_from_knowledge_base(user_input)if answer:logging.debug("从知识库找到答案")bot_response = answerelse:# 检测用户问题是否与配餐相关,仅依据当前输入文本is_meal_related = any(keyword in user_input for keyword in KEYWORDS)# 尝试从拼接后的文本中提取 calory 和 daycalory, day = extract_params(history_text)if is_meal_related or is_in_meal_process:if day is None:if "请问,要配几天的餐?" in history_text:# 重新提取当前用户输入中的 day_, day = extract_params(user_input)if day is None:logging.debug("仍未提取到 day 参数,再次询问用户")bot_response = "抱歉,我没获取到配餐天数,请明确告知要配几天的餐。"else:if calory is None:logging.debug("提取到 day 参数,未提取到 calory 参数,询问用户")bot_response = "请问每天的卡路里大概是多少?"else:# 调用配餐接口bot_response = get_meal_plan(calory, day)else:logging.debug("未提取到 day 参数,询问用户")bot_response = "请问,要配几天的餐?"elif calory is None:logging.debug("未提取到 calory 参数,询问用户")bot_response = "请问每天的卡路里大概是多少?"else:# 调用配餐接口bot_response = get_meal_plan(calory, day)else:logging.debug("用户问题与配餐无关,使用 Qwen2 模型生成回复")bot_response = chain.run(user_input)# 更新聊天历史st.session_state.chat_history.append({"user": user_input, "bot": bot_response})# 清空输入框st.session_state.input_value = ""# 显示聊天历史
for msg in st.session_state.chat_history:st.markdown(f"**用户**:{msg['user']}")st.markdown(f"**机器人**:{msg['bot']}")

4.执行streamlit run diet_ui.py

这个智能体实现了知识库、调公司业务接口功能,具体效果图

然后访问公网xxxxx:8501

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

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

相关文章

群晖监控套件通过ONVIF协议添加海康摄像头

1. 首先登录录像机 通道管理 找到每个摄像头的IP地址 2. 登录某个摄像头 配置 3. 添加用户名(注意不能是admin) 设置账户密码 用户类型选管理员 4. 群晖里面添加摄像头,自动搜索,添加刚刚那个IP的摄像头 5. 验证…

【C++】 —— 笔试刷题day_8

一、求最小公倍数 题目解析 题目很简单,给定两个数a和b求它们的最小公倍数。 算法思路 对于求两个数的最小公倍数问题,想必已经非常熟悉了; 在之前学校上课时,记得老师提起过,最小公倍数 两个数的乘积 除以最大公约数…

MTK Android12-Android13 设置系统默认语言

Android 系统,默认语言 文章目录 需求:场景 参考资料实现方案实现思路编译脚本熟悉-平台熟悉mssi_64_cnkernel-4.19 解决方案修改文件-实现方案 源码分析PRODUCT_LOCALES 引用PRODUCT_DEFAULT_LOCALE 定义get-default-product-locale 方法定义PRODUCT_DE…

系统如何查找文件?inode号又是什么?

下面分别详细解释您提到的三个问题: “文件系统怎么定位文件”、“inode 是什么”、“为什么删除后还可能被占用”。 一、文件系统怎么定位文件 1.1 目录与文件名并不直接存储文件数据 在常见的 Unix/Linux 文件系统(如 ext4、xfs)或类似的…

05-SpringBoot3入门-整合SpringMVC(配置静态资源、拦截器)

1、说明 在01-SpringBoot3入门-第一个项目-CSDN博客中,其实就已经整合了SpringMVC。下面讲解怎么配置静态资源和拦截器 2、配置静态资源 命名:static(文件夹) 位置:src/main/resources 编写一个html文件 访问 http:/…

Transformer-LSTM、Transformer、CNN-LSTM、LSTM、CNN五模型多变量回归预测

聚划算!Transformer-LSTM、Transformer、CNN-LSTM、LSTM、CNN五模型多变量回归预测 目录 聚划算!Transformer-LSTM、Transformer、CNN-LSTM、LSTM、CNN五模型多变量回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 聚划算!Tran…

树莓派浏览器配置全解析:从轻量系统到网页应用平台

树莓派(Raspberry Pi)不仅是嵌入式开发的入门利器,也因其低成本和强大的社区支持而成为物联网、数字标牌、教育培训等领域的热门平台。在很多应用中,运行一个浏览器并作为 Web 前端展示、操作或交互的能力显得尤为关键。 但在资源…

初识Qt(一)

本文部分ppt、视频截图原链接:萌马工作室的个人空间-萌马工作室个人主页-哔哩哔哩视频 1. Qt是什么? Qt是一个跨平台的C应用程序开发框架,它既为图形用户界面(GUI)程序开发提供了强大支持,也能用于开发非GUI的控制台程序、服务端…

六十天前端强化训练之第三十二天之Babel 转译配置大师级深度讲解

欢迎来到编程星辰海的博客讲解 看完可以给一个免费的三连吗,谢谢大佬! 目录 一、核心概念与知识体系详解 1. Babel 工作原理全景解析 二、完整配置方案(带详细注释) 1. 进阶版 .babelrc 配置 2. Webpack 集成配置&#xff08…

智能提示词生成器:助力测试工程师快速设计高质量测试用例

在软件测试中,测试用例设计方法的选择和实施是确保软件质量的重要步骤。测试工程师经常需要根据不同的测试场景、参数维度和业务需求,设计出覆盖率高且有效的测试用例。然而,设计测试用例并非易事,特别是在面对复杂的业务逻辑时。 为了帮助测试工程师高效生成测试用例提示…

beanie.exceptions.CollectionWasNotInitialized

遇到这样的情况不要慌,不要慌 1:检查模型是否已经初始化: class TaskModel(Document):"""定时任务模型"""task_id: str Field(default_factorylambda: str(uuid.uuid4()), # 新增默认值description"任…

【CVE-2025-30208】| Vite-漏洞分析与复现

漏洞简介 CVE-2025-30208 是 Vite 开发服务器中的一个任意文件读取漏洞。该漏洞允许攻击者通过特定的 URL 参数绕过访问控制,从而读取服务器上的敏感文件(如 /etc/passwd 或 C:\windows\win.ini)。 该漏洞主要影响以下版本的 Vite&#xff…

将 Markdown 表格结构转换为Excel 文件

在数据管理和文档编写过程中,我们经常使用 Markdown 来记录表格数据。然而,Markdown 格式的表格在实际应用中不如 Excel 方便,特别是需要进一步处理数据时。因此,我们开发了一个使用 wxPython 的 GUI 工具,将 Markdown…

Golang使用 ip2region 查询IP的地区信息

利用 ip2region 进行 IP 地址定位 import ("fmt""log""github.com/lionsoul2014/ip2region/binding/golang/xdb" )func main() {ip : "213.118.179.98"dbPath : ".\\cmd\\ip\\ip2region.xdb"// 1、初始化查询器//searcher,…

对匿名认证的理解

概述:在 Spring Security 中,** 匿名认证(Anonymous Authentication)** 是一种特殊的认证机制,用于处理未提供有效凭证的请求。 匿名认证的本质 目的:允许未认证用户访问特定资源。原理: 当请求…

C++调用Python

Python安装 地址: python官网 可以根据需要下载对应的版本。 调用python python测试脚本 # my_script.py import sys import jsondef calculate(a, b):return a * b 10 # 示例计算逻辑if __name__ "__main__":# 从命令行参数读取 JSON 字符串try…

工程数字建造管理系统平台有哪些?好的数字建造管理系统推荐

一、什么是工程数字建造管理系统平台? 工程数字建造管理系统平台是一种集成了先进信息技术(如云计算、大数据、物联网等)的综合性管理工具,它旨在通过数字化手段提升工程建造全过程的管理效率和决策水平。这一平台不仅覆盖了工程…

Android开发EmojiCompat 初始化

Android开发EmojiCompat 初始化 报错信息: ensure spannable:java.lang.IllegalStateException: EmojiCompat is not initialized 在Application上写上下面代码即可: EmojiCompat.Config config new BundledEmojiCompatConfig(this);EmojiCompat.in…

【Go】数组

数组Array 重点: 数组是值类型 注意点: 1. 数组:是同一种数据类型的固定长度的序列。2. 数组定义:var a [len]int,比如:var a [5]int,数组长度必须是常量,且是类型的组成部分。一旦定义&…

CORDIC算法:三角函数的硬件加速革命——从数学原理到FPGA实现的超高效计算方案

计算机该如何求解三角函数?或许你的第一印象是采用泰勒展开,或者采用多项式进行逼近。对于前者,来回的迭代计算开销成本很大;对于后者,多项式式逼近在较窄的范围內比较接近,超过一定范围后,就变…