# 大模型应用开发实战:Prompt 工程 + 多会话管理 + Function Calling 入门 本文基于 BOSS 直聘项目的实际代码系统讲解大模型应用开发的三个核心维度**Prompt 工程模板设计**、**多会话上下文管理**、**Function Calling 函数调用入门**。所有代码均来自生产环境可直接复用。---## 一、技术架构总览### 1.1 技术栈| 组件 | 技术 | 用途 ||------|------|------|| 大模型 | 阿里云通义 qwen-plus | 对话、文本生成、函数调用 || 后端框架 | FastAPI | 提供 RESTful API || 会话存储 | Redis List | 存储会话历史与消息 || 数据校验 | Pydantic | 请求参数校验 || 前端 | Vue3 Element Plus | 对话界面 |### 1.2 功能模块大模型应用├── Case1基础对话│ ├── Prompt 工程模板│ └── SSE 流式响应├── Case2多会话管理│ ├── 会话 CRUD│ ├── 上下文压缩│ └── 多轮对话└── Case3Function Calling├── 工具定义├── 函数调用流程└── 实战示例---## 二、Prompt 工程模板设计### 2.1 为什么需要 Prompt 模板直接将用户问题发给大模型效果往往不稳定。通过 Prompt 模板可以- **固定角色设定**确保 AI 始终扮演正确的角色- **约束输出格式**便于前端解析- **提供示例**引导输出质量- **支持扩展**方便后续添加约束### 2.2 模板结构设计pythonprompt f## 角色设定:你是一个智能助手## 任务描述:{user_question}## 输入参数## 输出格式## 约束条件## 示例#### 六大模块说明| 模块 | 作用 | 示例 ||------|------|------|| **角色设定** | 定义 AI 身份 | 你是一个资深 HR 顾问 || **任务描述** | 描述具体任务 | 优化用户的简历 || **输入参数** | 说明输入字段 | 姓名、岗位、工作年限 || **输出格式** | 约束输出结构 | JSON 格式包含 score、suggestions || **约束条件** | 限制输出规则 | 不超过 500 字使用中文 || **示例** | 提供 few-shot | 示例 1: ... 示例 2: ... |### 2.3 最佳实践#### ✅ 好的 Promptpythonprompt f## 角色设定你是一名资深的 BOSS 直聘求职顾问擅长简历优化和面试指导。## 任务描述根据用户提供的简历信息给出专业的优化建议。## 输入参数- 姓名{resume.name}- 应聘岗位{resume.position}- 工作年限{resume.years}- 技能列表{resume.skills}## 输出格式请严格按照以下 JSON 格式输出json{{score: 评分(0-100),highlights: [亮点1, 亮点2],suggestions: [建议1, 建议2],summary: 综合评价(50字以内)}}## 约束条件1. 评分必须客观公正2. 建议不少于 3 条3. 使用专业但易懂的语言4. 不编造不存在的经历## 示例### 示例输入- 姓名张三- 应聘岗位Python 后端工程师- 工作年限3 年- 技能Python, FastAPI, MySQL, Redis### 示例输出json{{score: 75,highlights: [具备完整的后端技术栈,有 Redis 缓存经验],suggestions: [补充具体的项目业绩数据,突出高并发优化经验,增加微服务架构相关内容],summary: 基础扎实建议强化项目深度和架构经验}}#### ❌ 差的 Promptpython# 直接将用户问题作为 prompt没有任何约束prompt user_question### 2.4 接口实现#### Schema 定义pythonfrom pydantic import BaseModel, Fieldclass LLMCase1(BaseModel):question: str Field(..., title问题, description用户问题)#### API 接口pythonllm_day01_router.post(/case1, summary基础对话接口)async def case1_api(llmCase1Request: LLMCase1):client OpenAI(api_keyos.getenv(DASHSCOPE_API_KEY),base_urlhttps://...maas.aliyuncs.com/compatible-mode/v1,)# 构造 Promptprompt f## 角色设定: 你是一个智能助手## 任务描述: {llmCase1Request.question}## 输入参数## 输出格式## 约束条件## 示例completion client.chat.completions.create(modelqwen-plus,messages[{role: system, content: 你是一个智能助手。},{role: user, content: prompt}],temperature0.75,)ai_reply completion.choices[0].message.contentreturn {code: 1,message: success,data: {ai_reply: ai_reply}}---## 三、多会话上下文管理### 3.1 核心问题大模型应用需要解决的核心问题1. **多用户隔离**不同用户的会话不能混淆2. **多会话管理**同一用户可以有多个独立会话3. **上下文保持**同一会话内保留历史消息4. **Token 控制**避免上下文过长导致成本爆炸### 3.2 Redis 数据结构设计#### Key 结构会话列表: boss:llm:session:{user_id} → List会话消息: boss:llm:case2:messages:{user_id}:{session_id} → List#### 数据示例# 会话列表Key: boss:llm:session:1Value: [{session_id: uuid-1, title: 简历优化, create_time: 2026-08-04 10:00:00},{session_id: uuid-2, title: 面试技巧, create_time: 2026-08-03 15:00:00}]# 会话消息Key: boss:llm:case2:messages:1:uuid-1Value: [{role: system, content: 你是一个智能助手},{role: user, content: 如何优化简历, create_time: ...},{role: assistant, content: 建议..., create_time: ...}]### 3.3 会话 CRUD 实现#### 创建会话pythonllm_day02_router.post(/create_session, summary创建会话)async def create_session(user_id: int):key fboss:llm:session:{user_id}current_session {session_id: str(uuid.uuid4()),title: 新会话,create_time: datetime.now().strftime(%Y-%m-%d %H:%M:%S)}# LPUSH新会话在列表头部redis_client.lpush(key, json.dumps(current_session, ensure_asciiFalse))return {code: 1,message: 创建会话成功,data: {current_session: current_session}}#### 查询会话列表pythonllm_day02_router.get(/get_session_list, summary查询会话列表)async def get_session_list(user_id: int):key fboss:llm:session:{user_id}user_sessions [json.loads(session)for session in redis_client.lrange(key, 0, -1)]return {code: 1,data: {user_sessions: user_sessions}}#### 查询会话消息pythonllm_day02_router.get(/get_user_session_messages, summary查询会话详情)async def get_user_session_messages(user_id: int, session_id: str):key fboss:llm:case2:messages:{user_id}:{session_id}# 跳过 system 消息索引 0user_session_messages [json.loads(message)for message in redis_client.lrange(key, 1, -1)]return {code: 1,data: {user_session_messages: user_session_messages}}### 3.4 发送消息与上下文管理#### 完整流程用户发送消息↓检查是否首轮对话├── 是 → 添加 system 消息 更新会话标题└── 否 → 跳过↓存储用户消息到 Redis↓读取完整消息历史↓上下文压缩超过 10 条时↓调用大模型获取回复↓存储 AI 回复到 Redis↓返回成功#### 核心代码pythonllm_day02_router.post(/send_message, summary发送消息)async def send_message(case_request: LLMCase2):key fboss:llm:case2:messages:{case_request.user_id}:{case_request.session_id}user_session_messages redis_client.lrange(key, 0, -1)# 1. 首轮对话添加 system 消息 更新标题if len(user_session_messages) 0:system_message {role: system, content: 你是一个智能助手}redis_client.rpush(key, json.dumps(system_message, ensure_asciiFalse))# 用第一条消息作为会话标题session_key fboss:llm:session:{case_request.user_id}user_sessions redis_client.lrange(session_key, 0, -1)for index, session in enumerate(user_sessions):session_dict json.loads(session)if session_dict[session_id] case_request.session_id:session_dict[title] case_request.message[:10] ...redis_client.lset(session_key, index,json.dumps(session_dict, ensure_asciiFalse))# 2. 存储用户消息current_user_message {role: user,content: case_request.message,create_time: datetime.now().strftime(%Y-%m-%d %H:%M:%S)}redis_client.rpush(key, json.dumps(current_user_message, ensure_asciiFalse))# 3. 读取消息历史并压缩messages [json.loads(m) for m in redis_client.lrange(key, 0, -1)]messages compression_messages(messages)# 4. 调用大模型ai_reply get_ai_response(messages)# 5. 存储 AI 回复ai_reply_message {role: assistant,content: ai_reply,create_time: datetime.now().strftime(%Y-%m-%d %H:%M:%S)}redis_client.rpush(key, json.dumps(ai_reply_message, ensure_asciiFalse))return {code: 1, message: 发送消息成功}### 3.5 上下文压缩策略#### 为什么需要压缩| 问题 | 说明 ||------|------|| Token 限制 | qwen-plus 支持 128K但长对话仍会超限 || 成本控制 | Token 消耗与费用成正比 || 响应速度 | 长上下文处理耗时更长 |#### 压缩算法滑动窗口 语义压缩pythondef compression_messages(messages: list):# 阈值判断if len(messages) 10:return messages # 不压缩# 1. 保留最近 10 条消息recently_messages messages[-10:]# 2. 将更早的消息压缩成摘要history_messages messages[:-10]c_messages [{role: user,content: f请将以下用户与大模型的上下文进行语义压缩,要保留核心的关键信息,上下文:{history_messages}}]summary get_ai_response(c_messages)# 3. 拼接摘要 最近消息return [{role: user, content: summary}] recently_messages#### 压缩前后对比压缩前20 条消息:[system, user1, ai1, user2, ai2, ..., user10, ai10]压缩后:[压缩摘要(user), user6, ai6, ..., user10, ai10]---## 四、Function Calling 入门### 4.1 什么是 Function CallingFunction Calling函数调用是大模型的核心能力之一允许 AI 在对话过程中**主动调用外部 API**。#### 应用场景| 场景 | 示例 ||------|------|| 数据查询 | 查询北京今日天气 → 调用天气 API || 业务操作 | 帮我投递这个简历 → 调用投递接口 || 信息检索 | 最新 Python 岗位有哪些 → 调用搜索接口 || 系统控制 | 打开会议室 A → 调用会议室 API |### 4.2 Function Calling 流程用户: 帮我查询北京今日天气↓大模型判断需要调用函数↓返回: { name: get_weather, arguments: { city: 北京 } }↓后端解析函数名和参数↓调用实际的 API↓将 API 结果返回给大模型↓大模型生成自然语言回复↓用户: 北京今日晴天温度 25℃### 4.3 工具定义#### 示例定义天气查询工具pythontools [{type: function,function: {name: get_weather,description: 获取指定城市的天气信息,parameters: {type: object,properties: {city: {type: string,description: 城市名称如北京、上海、广州}},required: [city]}}}]#### 示例定义职位搜索工具pythontools [{type: function,function: {name: search_job,description: 搜索招聘职位,parameters: {type: object,properties: {keyword: {type: string,description: 职位关键词如Python工程师},city: {type: string,description: 城市名称},salary_range: {type: string,description: 薪资范围如10-20K}},required: [keyword]}}}]### 4.4 Function Calling 实现#### 核心代码pythondef call_with_tools(client, messages, tools):带 Function Calling 的对话# 第一次调用response client.chat.completions.create(modelqwen-plus,messagesmessages,toolstools, # 传入工具定义tool_choiceauto # 让模型自动判断是否调用)assistant_message response.choices[0].messagemessages.append(assistant_message) # 添加 AI 回复# 检查是否需要调用函数if assistant_message.tool_calls:for tool_call in assistant_message.tool_calls:function_name tool_call.function.namefunction_args json.loads(tool_call.function.arguments)# 根据函数名分发调用if function_name get_weather:result get_weather(**function_args)elif function_name search_job:result search_job(**function_args)else:result {error: f未知函数: {function_name}}# 将函数结果返回给模型messages.append({role: tool,name: function_name,content: json.dumps(result, ensure_asciiFalse)})# 第二次调用让模型基于工具结果生成回复response client.chat.completions.create(modelqwen-plus,messagesmessages)return response.choices[0].message.content#### 工具实现示例pythonimport requestsdef get_weather(city: str):获取天气信息# 实际项目中调用真实 API# response requests.get(fhttps://api.weather.com/{city})return {city: city,weather: 晴,temperature: 25℃,humidity: 60%,wind: 东风3级}def search_job(keyword: str, city: str , salary_range: str ):搜索职位# 实际项目中查询数据库return {total: 50,jobs: [{title: f{keyword}{city},company: 某某科技,salary: salary_range or 面议,location: city or 不限}]}### 4.5 Function Calling 完整示例#### 用户调用pythonmessages [{role: system, content: 你是 BOSS 直聘 AI 助手可以查询职位和天气。},{role: user, content: 帮我搜索北京的 Python 岗位}]tools [{type: function,function: {name: search_job,description: 搜索招聘职位,parameters: {type: object,properties: {keyword: {type: string},city: {type: string}},required: [keyword]}}}]result call_with_tools(client, messages, tools)print(result)# 输出: 为您找到北京的 Python 岗位共 50 个其中某某科技的 Python 工程师岗位...#### 完整交互流程1. 用户: 帮我搜索北京的 Python 岗位2. AI: (判断需要调用 search_job 工具)3. 系统: 调用 search_job(keywordPython, city北京)4. 系统: 返回 {total: 50, jobs: [...]}5. AI: 为您找到北京的 Python 岗位共 50 个...---## 五、API 接口汇总### Case1基础对话| 方法 | URL | 说明 ||------|-----|------|| POST | /llm-day01/case1 | Prompt 工程模板对话 || POST | /llm-day01/case2 | SSE 流式响应 |### Case2多会话管理| 方法 | URL | 说明 ||------|-----|------|| POST | /llm-day02/create_session | 创建会话 || GET | /llm-day02/get_session_list | 查询会话列表 || GET | /llm-day02/get_user_session_messages | 查询会话消息 || POST | /llm-day02/send_message | 发送消息 |### 请求参数示例#### send_messagejson{user_id: 1,session_id: 97570f91-c71a-44ec-8d9b-ff0f183cf013,message: 如何优化我的简历}---## 六、踩坑总结### 6.1 Prompt 工程| 问题 | 解决方案 ||------|---------|| 输出不稳定 | 使用模板固定结构 || 输出难以解析 | 约束 JSON 格式输出 || 回答过于简短 | 添加示例引导 |### 6.2 会话管理| 问题 | 解决方案 ||------|---------|| Redis 中文乱码 | ensure_asciiFalse || 会话顺序错误 | LPUSH 新会话在头部 || Token 爆炸 | 滑动窗口 压缩 |### 6.3 Function Calling| 问题 | 解决方案 ||------|---------|| 模型不调用函数 | 清晰描述 function.description || 参数解析错误 | 使用 json.loads 解析参数 || 多轮调用 | 循环处理 tool_calls |---## 七、扩展方向| 功能 | 说明 ||------|------|| **流式 Function Calling** | 结合 SSE 实现实时工具调用反馈 || **多模型切换** | 根据场景选择不同模型turbo/max || **权限控制** | 限制每个用户的调用频率 || **对话导出** | 支持导出为 PDF、Markdown || **知识库集成** | 接入向量数据库实现 RAG || **多模态支持** | 图片理解、语音输入 |---## 八、完整代码文件| 文件 | 说明 ||------|------|| [app/apis/llm/case1.py](file:///d:/p4newxm/boss_api/app/apis/llm/case1.py) | 基础对话 Prompt 模板 || [app/apis/llm/case2.py](file:///d:/p4newxm/boss_api/app/apis/llm/case2.py) | 多会话管理 || [app/schemas/llm_case1.py](file:///d:/p4newxm/boss_api/app/schemas/llm_case1.py) | Pydantic 模型定义 || [main.py](file:///d:/p4newxm/boss_api/main.py) | 路由注册 |---## 总结本文系统介绍了大模型应用开发的三个核心维度### 1. Prompt 工程模板- **六大模块**角色设定、任务描述、输入参数、输出格式、约束条件、示例- **核心价值**稳定输出、易于解析、便于维护### 2. 多会话管理- **Redis List**高效存储会话和消息- **上下文压缩**滑动窗口 语义压缩- **用户隔离**基于 user_id 的数据隔离### 3. Function Calling 入门- **核心概念**让大模型调用外部 API- **实现步骤**工具定义 → 调用分发 → 结果回传- **应用场景**数据查询、业务操作、信息检索