LangGPT提示词工程实践
模型部署
配置好环境后,用lmdeploy工具部署模型。教程推荐用tmux分窗口起服务和调试、但实际上开多个终端窗口也可以解决
以下是环境所需依赖:
# 安装一些必要的库
conda install pytorch==2.1.2 torchvision==0.16.2 torchaudio==2.1.2 pytorch-cuda=12.1 -c pytorch -c nvidia -y
# 安装其他依赖
pip install transformers==4.43.3
pip install streamlit==1.37.0
pip install huggingface_hub==0.24.3
pip install openai==1.37.1
pip install lmdeploy==0.5.2
用lmdeploy工具轻松部署:
::用于
CUDA_VISIBLE_DEVICES=0 lmdeploy serve api_server /share/new_models/Shanghai_AI_Laboratory/internlm2-chat-1_8b --server-port 23333 --api-keys internlm2
CUDA_VISIBLE_DEVICES=0 lmdeploy serve api_server /share/new_models/Shanghai_AI_Laboratory/internlm2_5-7b-chat --server-port 33333 --api-keys internlm2
命令第一项CUDA_VISIBLE_DEVICES 是一个环境变量,用于控制哪些 CUDA 设备(通常是 GPU)对 CUDA 应用程序可见。在运行 CUDA 应用程序时,通过设置这个环境变量,你可以指定哪些 GPU 应该被应用程序使用。
CUDA_VISIBLE_DEVICES=0 这个命令意思是“只使用第一个 GPU”。
部署完成后启动streamlit页面
python -m streamlit run chat_ui.py
-m:这个选项告诉 Python 解释器以模块的方式运行后面的参数。模块运行方式允许你执行一个模块中的代码,而不是直接执行一个脚本文件。
-m streamlit run :启动 Streamlit 的服务器,并且加载指定的应用程序。
在本地终端输入以下命令,将开发机上的8501(web界面占用的端口)映射到本地机器的端口,之后打开浏览器访问http://localhost:8501
ssh -p {ssh端口,从InternStudio获取} root@ssh.intern-ai.org.cn -CNg -L 7860:127.0.0.1:8501 -o StrictHostKeyChecking=no
成功部署!
什么是prompt engineering
提示工程是一种通过设计和调整输入(Prompts)来改善模型性能或控制其输出结果的技术。
在模型回复的过程中,首先获取用户输入的文本,然后处理文本特征并根据输入文本特征预测之后的文本,原理为next token prediction。
提示工程是模型性能优化的基石,有以下六大基本原则:
- 指令要清晰
- 提供参考内容
- 复杂的任务拆分成子任务
- 给 LLM“思考”时间(给出过程)
- 使用外部工具
- 系统性测试变化
构建高质量 Prompt 时,将这些方法结合使用,结构化方式能够更便于各个技巧间的协同组织,例如将 CoT 方法融合到结构化 Prompt 中编写提示词。 汇总现有的一些方法:
- 细节法:给出更清晰的指令,包含更多具体的细节
- 分解法:将复杂的任务分解为更简单的子任务 (Let’s think step by step, CoT,LangChain等思想)
- 记忆法:构建指令使模型时刻记住任务,确保不偏离任务解决路径(system 级 prompt)
- 解释法:让模型在回答之前进行解释,说明理由 (CoT 等方法)
- 投票法:让模型给出多个结果,然后使用模型选择最佳结果 (ToT 等方法)
- 示例法:提供一个或多个具体例子,提供输入输出示例 (one-shot, few-shot 等方法)
什么是langgpt
LangGPT 是 Language For GPT-like LLMs 的简称,中文名为结构化提示词。LangGPT 是一个帮助你编写高质量提示词的工具,理论基础是我们提出的一套模块化、标准化的提示词编写方法论——结构化提示词。我们希望揭开提示工程的神秘面纱,为大众提供一套可操作、可复现的提示词方法论、工具和交流社群。我们的愿景是让人人都能写出高质量提示词。LangGPT社区文档:https://langgpt.ai
任务:浮点数比大小
文生文大模型并不擅长做数学题(math系列模型除外,它们针对性微调过)
但是通过langgpt等提示词引导后做此类任务的效果会有所提升,以下是用1.8b模型的实验:
没有结构化提示词的效果
(11.11和11.9比较错啦)
(17.21和17.6比较错啦)
有结构化提示词比较的效果
(虽然小数比较的逻辑很奇怪、但是结果是正确的…)
不过也有翻车的时候,只能说这个任务对1.8b的小gpt来说太难了:
用7b模型的效果
(试了几个不用复杂提示词都能答对)
附1:ui页面代码(来自官方)
import streamlit as st
from openai import OpenAI
import os
import json
import time
# Create a chatbot UI with Streamlit and OpenAI
def chat_ui():
state = st.session_state
# Set the title of the app
st.title("浦语提示词工程实践")
st.caption("浦语提示词工程实践所用Web UI")
# Create a client for the OpenAI API
if "client" not in state:
st.info("请配置Chatbot的基本设置,其中API Key和Base URL是必须的。")
pass
else:
# if "message_history" not in state:
# state.message_history = []
# pass
# if "system_prompt" in state:
# state.message_history.append({"role": "system", "content": state.system_prompt})
user_input = st.chat_input("输入消息")
if user_input:
state.message_history.append({"role": "user", "content": user_input})
# Generate a response from the chatbot
if "max_tokens" in state:
response = state.client.chat.completions.create(
model=state.client.models.list().data[0].id,
messages=state.message_history,
max_tokens=state.max_tokens,
temperature=state.temperature
)
else:
response = state.client.chat.completions.create(
model=state.client.models.list().data[0].id,
messages=state.message_history,
temperature=state.temperature
)
state.message_history.append({"role": "assistant", "content": response.choices[0].message.content})
pass
for message in state.message_history:
if message["role"] == "system":
continue
else:
st.chat_message(message["role"]).write(message["content"])
# Create a text input for the user to type their message
pass
# define a side bar for the setting of the chatbot, such as the max token length, temperature, api_key, base_url, system prompt, etc.
def side_bar():
st.sidebar.title("设置")
state = st.session_state
# Set a form of the settings
with st.sidebar.form(key="settings"):
# Set the max token length for the chatbot
max_tokens = st.number_input("最大token长度", min_value=0, max_value=2048, value=100, step=1)
# Set the temperature for the chatbot
temperature = st.number_input("Temperature", min_value=0.0, max_value=1.0, value=0.0, step=0.01)
# Set the api key for the OpenAI API
api_key = st.text_input("API Key", value="internlm2")
# Set the base url for the OpenAI API
# internlm2-chat-1_8b
base_url = st.text_input("Base URL",value="http://0.0.0.0:23333/v1")
# # internlm2_5-7b-chat
# base_url = st.text_input("Base URL",value="http://0.0.0.0:33333/v1")
# Set the system prompt for the chatbot
system_prompt = st.text_area("系统提示", value="")
# Add a submit button to the form
submit = st.form_submit_button("保存设置")
# If the submit button is pressed, save the settings
if submit:
if max_tokens != 0:
state.max_tokens = max_tokens
state.temperature = temperature
state.api_key = api_key
state.base_url = base_url
state.message_history = []
if system_prompt != "":
state.system_prompt = system_prompt
state.message_history.append({"role": "system", "content": system_prompt})
state.client = OpenAI(api_key=state.api_key, base_url=state.base_url)
pass
if st.sidebar.button("开启新对话"):
if not os.path.exists("chat_history"):
os.mkdir("chat_history")
pass
with open(f"chat_history/{time.time()}.json", "w") as f:
json.dump(state.message_history, f, ensure_ascii=False)
pass
state.message_history = []
st.rerun()
pass
if __name__ == "__main__":
side_bar()
chat_ui()
pass
附2: 比大小任务的提示词
## Role
你是一名出色的数学家
## Profile
你对于数学概念有非常清晰的认识,并能很好的向其他人解释,尤其擅长在不同格式的浮点数之间进行值的大小比较。
概念:浮点数的格式为:<整数>.<小数>,如2.11,2.8。有时小数部分会被省略,如2。
## Tasks
一步步思考,完成以下任务:公平的比较输入的几个数值的大小,输出整个思考过程和结论。
## Workflow
两个浮点数比较时请遵循如下步骤:
1. 浮点数格式对齐:取所有浮点数中小数的最长数位,将所有浮点数的小数部分都填充0,直到它们的小数部分位数相同
2. 整数部分比较:先比较整数部分的值,整数部分值相同时,再比较小数部分的值
3. 小数部分比较:把小数部分做比较,不要四舍五入计算
4. 如果有多个浮点数,循环按上面的规则进行
4. 比较完成后,给出结论
## Sample
Input1:比较2.11和2.2,以及2的大小
Output1:根据所有浮点数的最长小数位补齐,得到2.11, 2.20, 2.00
首先比较整数值,因为整数位相同所以比较小数,各浮点数的小数部分分别为20,11,00, 而20大于11大于00, 因此最终浮点数的大小为:2.2>2.11>2
Input2:比较17.5和17.21的大小
Output2:1.根据所有浮点数的最长小数位补齐,得到15.50和17.21;2.比较整数值,整数位相同;3.比较小数,各浮点数的小数部分分别为50和21, 而50大于21;4.因此最终浮点数的大小为:17.5大于17.21
## Input