首页 > 大数据 > Hadoop > 我们的核心工作是写 Prompt(提示词)
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI
from langchain.tools import tool
# 加载 .env 文件中的 SILICONFLOW_API_KEY
load_dotenv()
# 1. 定义工具:必须要写清晰的 Docstring(函数注释)
@tool
def get_weather(city: str) -> str:
"""获取指定城市的实时天气情况。"""
return f"{city} 的天气总是阴雨连连!"
# 2. 初始化 SiliconFlow 模型
llm = ChatOpenAI(
model="deepseek-ai/DeepSeek-V3",
api_key=os.getenv("SILICONFLOW_API_KEY"),
base_url="https://api.siliconflow.cn/v1",
temperature=0.1
)
# 3. 创建 Agent
agent = create_agent(
model=llm,
tools=[get_weather],
system_prompt="你是一个乐于助人的天气助手。"
)
# 4. 运行
if __name__ == "__main__":
response = agent.invoke(
{"messages": [{"role": "user", "content": "北京天气怎么样?"}]}
)
# 打印最后一条消息(AI 的回答)
from dataclasses import dataclass
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain.agents import create_agent
from langchain.tools import tool, ToolRuntime
from langgraph. m.suishougou.cn,checkpoint.memory import InMemorySaver
from langchain.agents.structured_output import ToolStrategy
load_dotenv()
# 1. 定义系统提示词(要求 AI 做个“谐音梗”专家)
SYSTEM_PROMPT = """你是一位专业的资深天气预报员,说话极其幽默,特别喜欢讲“谐音梗”。
你有权使用以下两个工具:
- get_weather_for_location: 获取特定城市的天气。
- get_user_location: 获取当前用户的所在地。
如果用户询问天气,请务必确认地点。如果用户说的是“我这儿”或“我这里”,请调用 get_user_location 获取他们的位置。"""
# 2. 定义上下文结构(存储用户信息)
@dataclass
class Context:
"""自定义运行时上下文。"""
user_id: str
# 3. 定义工具
@tool
def get_weather_for_location(city: str) -> str:
"""获取指定城市的天气情况。"""
return f"{city} 的天气总是阳光灿烂!"
@tool
def get_user_location(runtime: ToolRuntime[Context]) -> str:
"""根据用户 ID 获取其地理位置。"""
user_id = runtime.context.user_id
# 模拟数据库:用户 1 在北京,其他在珠海
return "北京" if user_id == "1" else "珠海"
# 4. 配置你的模型 (SiliconFlow)
model = ChatOpenAI(
model="deepseek-ai/DeepSeek-V3",
api_key=os.getenv("SILICONFLOW_API_KEY"),
base_url="https://api.siliconflow.cn/v1",
temperature=0.7 # 稍微提高随机性,让谐音梗更有创意
)
# 5. 定义响应格式(汉化字段描述,让 AI 明白填什么)
@dataclass
class ResponseFormat:
"""Agent 的结构化回复格式。"""
# 幽默的谐音梗回复
punny_response: str
# 任何关于天气的有趣信息(如果有的话)
weather_conditions: str | None = None
# 6. 设置记忆存储
checkpointer = InMemorySaver()
# 7. 创建 Agent
agent = create_agent(
model=model,
system_prompt=SYSTEM_PROMPT,
tools=[get_user_location, get_weather_for_location],
context_schema=Context,
response_format=ToolStrategy(ResponseFormat),
checkpointer=checkpointer
)
# --- 运行测试 ---
# 设置会话 ID
config = {"configurable": {"thread_id": "test_user_001"}}
# 第一次提问
print("--- 第一次对话 ---")
response = agent.invoke(
{"messages": [{"role": "user", "content": "外面天气怎么样?"}]},
config=config,
context=Context(user_id="1")
)
# 访问结构化结果
res = response['structured_response']
print(f"AI: {res.punny_response}")
print(f"详情: {res.weather_conditions}")
print("\n--- 第二次对话(测试记忆) ---")
# 第二次提问
response = agent.invoke(
{"messages": [{"role": "user", "content": "谢谢你!我在哪里?"}]},
config=config,
context=Context(user_id="1")
)
res = response['structured_response']
用户问:“外面天气怎么样?”(没说地点)。
AI 思考:系统提示词告诉我,如果地点不明,先去查用户在哪。
动作:AI 调用 get_user_location -> 得到“北京” -> 调用 get_weather_for_location -> 得到天气。
回复:根据 ResponseFormat 吐出一个谐音梗。
第二次对话:
用户问:“谢谢你!我在哪里?”
AI 思考:由于有 thread_id 和 checkpointer,AI 记得上一次查询的结果。
动作:它不需要再次查工具,直接从记忆里提取信息并回复。
from
transformers
import
AutoProcessor, AutoModelForVision2Seqfrom
qwen_vl_utils
import
process_vision_infoimport
warningswarnings.filterwarnings(
"ignore"
, category
=
FutureWarning, module
=
"transformers"
)import
os njyf.com.cn
# 加载模型和处理器model_path
=
"Qwen/Qwen3-VL-4B-Instruct"processor
=
AutoProcessor.from_pretrained(model_path)
# 加载视觉-文本模型model, output_loading_info m.qieroom.com
=
AutoModelForVision2Seq.from_pretrained(
model_path,
torch_dtype
=
"auto"
,
device_map
=
"auto"
,
output_loading_info
=
True)print
(
"output_loading_info"
, output_loading_info)
# 配置视频处理参数video
=
"./1.mp4"total_pixels
=
20480
*
32
*
32
# 总像素限制min_pixels
=
64
*
32
*
32
# 最小像素限制max_frames
=
2048
# 最大帧数sample_fps
=
2
# 采样帧率max_new_tokens
=
2048
# 生成的最大 token 数
prompt
=
"请描述这个视频的内容"
# 构建对话消息messages
=
[
{
"role"
:
"user"
,
"content"
: [m.jtwL.com.cn
{
"video"
: video,
"total_pixels"
: total_pixels,
"min_pixels"
: min_pixels,
"max_frames"
: max_frames,
'sample_fps'
: sample_fps
},
{
"type"
:
"text"
,
"text"
: prompt
},
]
},]
# 应用对话模板text
=
processor.apply_chat_template(messages, tokenize
=
False
, add_generation_prompt
=
True
)
# 处理视觉信息image_inputs, m.yousLab.com,video_inputs,wap.qzsxy.com, wap.7632.com.cn,video_kwargs
=
process_vision_info(
[messages],
return_video_kwargs
=
True
,wap.zjtgjx.net,
image_patch_size
=
16
,
return_video_metadata
=
True)
# 分离视频数据和元数据if
video_inputs
is
not
None
:
video_inputs, video_metadatas
=
zip
(
*
video_inputs)
video_inputs, video_metadatas firstfeed.com.cn,
=
list
(video_inputs),
list
(video_metadatas)else
:
video_metadatas
=
None
# 准备模型输入inputs
=
processor(
text
=
[text],
images
=
image_inputs,
videos
=
video_inputs,
video_metadata
=
video_metadatas,
*
*
video_kwargs,
do_resize
=
False
,
return_tensors
=
"pt")inputs
=
inputs.to(
'cuda'
)
# 生成输出output_ids
=
model.generate(
*
*
inputs, max_new_tokens
=
max_new_tokens)
# 提取生成的部分(去除输入)generated_ids
=
[
output_ids[
len
(input_ids):]
for
input_ids, output_ids
in
zip
(inputs.input_ids, output_ids)]
# 解码为文本output_text
=
processor.batch_decode(
generated_ids,m.psnsd.com,
skip_special_tokens
=
True
,
clean_up_tokenization_spaces
=
True最后可以看到video_inputs的结果为单元素的list,这单个元素里为1个tuple,包含2部分:
首先看video_grid_thw,这个表示的patch布局,前面提到缩放后的分辨率为640 x 1152,对应到patch=16后的patch布局则为40 x 72。但这里有个问题, 为什么采样时帧数为30,这里变成了15?
通过阅读Qwen3VLVideoProcessor的源码[1]可以了解到有一个重要参数是temporal_patch_size=2(也可以在模型的config文件里看到这个参数)。 这个参数代表的含义是:模型一次看多少帧作为一个token。也可以理解为每个video token覆盖的连续帧数。在这里指定为2,也就表示每2帧合并成1个时间patch,这样就天然包含了帧序列中运动/变化的信息。这个参数越小,能捕捉到的动作变化就越细,对应消耗的token也越多。所以这就解释了为什么输入模型的patch布局为15 * 40 * 72。
再看pixel_value_videos的shape为torch.Size([43200, 1536]):
最后再看input_ids结果,其shape为([1, 10938]),对其做decode的结果为:
orchrun \
# ========== 分布式启动 ==========
-
-
nproc_per_node
=
8
\
-
-
master_addr
=
127.0
.
0.1
\
-
-
master_port
=
29500
\
# ========== 训练入口 ==========
Qwen3
-
VL
/
qwen
-
vl
-
finetune
/
qwenvl
/
train
/
train_qwen.py \
# ========== DeepSpeed wap.huome.cn==========
-
-
deepspeed
=
Qwen3
-
VL
/
qwen
-
vl
-
finetune
/
scripts
/
zero3.json \
# ========== 模型与数据 ==========
-
-
model_name_or_path
=
Qwen
/
Qwen3
-
VL
-
4B
-
Instruct \
-
-
dataset_use
=
wzry_video
%
100
\
# ========== 输出与实验标识 ==========
-
-
output_dir
=wap.jtwL.com.cn
.
/
output
/
wzry_video_finetune \
-
-
run_name
=
wzry_video_qwen3vl_4b \
# ========== 多模态可训练模块 ==========
-
-
tune_mm_vision
=
True
\
-
-
tune_mm_mlp
=
True
\
-
-
tune_mm_llm
=
True
\
# ========== 精度与训练轮数 ==========
-
-
bf16 \
-
-
num_train_epochs
=
20
\
# ========== Batch & 累积 ==========
-
-
per_device_train_batch_size
=
2
\
-
-
per_device_eval_batch_size
=
4
\
-
-
gradient_accumulation_steps
=
4
\
# ========== 学习率(分模块) ==========
-
-
learning_rate
=
2e
-
05
\
-
-
mm_projector_lr
=
4e
-
05
\
-
-
vision_tower_lr
=
2e
-
06
\
# ========== 优化器与调度 ==========
-
-
weight_decay
=
0.01
\
-
-
warmup_ratio
=
0.03
\
-
-
lr_scheduler_type
=
cosine \
-
-
max_grad_norm
=
1.0
\
# ========== 上下文与数据组织 ==========
-
-
model_max_length
=
8192
\
-
-
data_flatten
=
True
\
-
-
data_packing
=
False
\
# ========== 视频采样参数 ==========
-
-
video_fps
=
4
\
-
-
video_max_frames
=
32
\
-
-
video_min_frames
=
16
\
# ========== 视频分辨率 / token 控制 ==========
-
-
video_max_pixels
=
1003520
\
-
-
video_min_pixels
=
401408
\
-
-
max_pixels
=
602112
\
-
-
min_pixels
=
100352
\
# ========== 评估与保存 ==========
-
-
eval_strategy
=
no \
-
-
save_strategy
=
epoch \
-
-
save_steps
=
2
\
-
-
save_total_limit
=
3
\
# ========== 日志 ==========
-
-
logging_steps
=
2 wap.7632.com.cn,
-
-
report_to
=
tensorboard \
-
-
gradient_checkpointing
=
True
\
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70048956/viewspace-3109282/ ,如需转载,请注明出处,否则将追究法律责任。