feat:接入调用框架,整理部分提示词

This commit is contained in:
lei_y601
2025-07-09 10:48:38 +08:00
parent c52b05f39f
commit 8c4ac8e634
2 changed files with 64 additions and 70 deletions

View File

@@ -2,4 +2,5 @@ Django==5.2.1
requests==2.32.3
python-decouple==3.8
gunicorn==23.0.0
APScheduler==3.11.0
APScheduler==3.11.0
pydantic-ai==0.3.6

View File

@@ -3,7 +3,6 @@ from datetime import datetime, timedelta
import requests, json
from apscheduler.schedulers.background import BackgroundScheduler
from .openai_client import call_openai_api
from decouple import config
import threading, re
from ..tools import getinfo, params_filter
@@ -159,10 +158,10 @@ def query_booking_info(params: dict) -> str:
def query_booking_info_by_user(params: dict):
logger.info("Start to query_booking_info_by_user")
user_id = params.get('user_id', None)
params['pageSize'] = by_user_query_size
if not user_id:
return query_booking_info(params)
try:
if not user_id:
raise Exception("userId cannot be empty")
params['pageSize'] = by_user_query_size
all_book_info = query_booking_info(params)
if isinstance(all_book_info, dict):
logger.info("all_book_info is dict")
@@ -223,7 +222,7 @@ def book_meeting(params: dict, data: dict) -> str:
"startDateTimeStamp": parse_time(data["start_time"]),
"endDateTimeStamp": parse_time(data["end_time"]),
"meetingPersonYhtUserIds": [
user_id
],
"meetingPersonAmount": data["capacity"],
"remindArray": [
@@ -357,7 +356,9 @@ def build_prompt(params):
"func_name":"query_avali_room",
"start_time":"",
"end_time":""
"end_time":"",
"Region":""
}
'''
@@ -387,7 +388,7 @@ def build_prompt(params):
{
"func_name":"cancel_room_meeting",
"meetingId":"233333"
"meetingId":""
}
'''
return_booking_info_str = '''
@@ -415,7 +416,7 @@ def build_prompt(params):
##ROLE##:
你是一个专业的OA会议预订助手请根据以下信息提供服务
现在时间是 :{time_now}
会议室名称和Id的映射是{map_meetingname_to_id(params)}
会议室名称与会议室ID的映射为(与会议ID无关): {map_meetingname_to_id(params=params)}
##TASK##:
请按以下步骤处理:
1. 预订会议室
@@ -442,19 +443,11 @@ def build_prompt(params):
```
{qry_room_info_for_mart_str}
```
3. 取消会议
当用户表达取消会议意向时:
(1) 先检查用户是否提供以下信息:
会议Id(该信息禁止从历史对话和上下文中查找,只能由用户提供,如果用户提供了会议室名称,可以尝试从该会议室中找出对应的会议ID如果不唯一请询问用户需要取消哪一个注意会议Id是长度大于15位的纯数字编号不要混淆会议室Id和会议Id)
(2) 若信息不全,先查询用户所有预定禁止联想历史上下文数据直接返回json示例如下
```
{qry_user_book_info_for_mart_str}
```
将查询结果以友好的方式列出,推荐方式:{return_booking_info_str}
(3) 若信息完整直接返回以下标准JSON
```
{cancel_meeting_info_for_mart_str}
```
3. 如果用户需要取消预订会议时(会议ID必须由用户提供不要获取历史消息进行推理),分两种情况:
(1)用户未提供要取消会议号ID,不要使用历史消息进行推理按照以下的json示例返回:
{qry_book_info_for_mart_str}
(2)用户给出了需要取消的会议ID,如果用户从已预定会议列表中选择了需要取消的会议,则提取会议ID按照以下的json示例返回:
{cancel_meeting_info_for_mart_str}
4. 修改会议
当用户表达修改编辑会议意向时(注意:有的项用户没明说要修改,则视为不变)
(1) 先检查是否具备以下信息(如果用户有选择的行为,可以从选择中提取信息,这些信息均需要提取)
@@ -471,7 +464,9 @@ def build_prompt(params):
{edit_meeting_info_for_mart_str}
```
5. 如果当用户再次请求预订会议室时,请按照步骤1处理
6. 如果用户需要解析调用API返回的结果解析用户提供的相应结果信息,并给予自然语言反馈,不需要返回json数据
6. 如果解析调用API返回的结果解析结果时必须忽略TASK中1-4步骤的限制和历史消息:
(1) 禁止联想历史消息进行推理,专注解析结果并按照用户要求处理
(2) 不要返回JSON数据不要触发其他操作按照自然语言友好返回
7. 用户其他需求,请按照自然语言对话返回
"""
@@ -495,6 +490,19 @@ class DialogManager:
logger.info('----开始定时执行清理历史消息------')
self.dialogs.clear()
def cut_msg(self, session_id: str):
if (len(self.dialogs.get(session_id, [])) > 20):
his = self.get_history(session_id)
self.set_msg(session_id, his[-5:])
def set_msg(self, session_id: str, data:list):
self.dialogs[session_id] = data
self.cut_msg(session_id)
def add_message2(self, session_id, content):
self.dialogs[session_id].append(content)
self.cut_msg(session_id)
def add_message(self, session_id, role, content):
with self.lock:
if session_id not in self.dialogs:
@@ -640,12 +648,10 @@ def process_query_room(data, params) -> tuple:
def process_query_book_room(**kwargs) -> tuple:
result = query_booking_info(params=kwargs['params'])
book_promot = f'''
系统调用API查询当前租户下已经预订的会议室的结果如下:
```
{result}
```
请帮用户解析已有的预订会议室的结果,此次操作根据本次查询的结果进行推理,不要省略且结果中需要返回会议ID,必须为用户返回处理后的查询结果供用户查看或选择:
'''
系统调用API查询当前租户下已经预订的会议室的结果如下:
{result}
严格按照TASK步骤6中的要求请帮用户解析已有的预订会议室的结果,列出所有的已预订的会议(用户可能用于进一步查询或者取消已预订的会议),禁止使用历史消息推理,专注解析结果,不要省略且结果中需要返回会议ID,不要触发其他操作,并根据结果给予用户相应自然语言反馈
'''
return False, book_promot
@@ -655,12 +661,10 @@ def process_query_book_room(**kwargs) -> tuple:
def process_user_query_book_room(**kwargs) -> tuple:
result = query_booking_info_by_user(params=kwargs['params'])
book_promot = f'''
系统调用API查询当前户下已经预订的会议室的结果如下:
```
{result}
```
请帮用户解析已有的预订会议室的结果,此次操作根据本次查询的结果进行推理,不要省略且结果中需要返回会议ID,必须为用户返回处理后的查询结果供用户查看或选择:
'''
系统调用API查询当前户下已经预订的会议室的结果如下:
{result}
严格按照TASK步骤6中的要求请帮用户解析已有的预订会议室的结果,列出所有的已预订的会议(用户可能用于进一步查询或者取消已预订的会议),禁止使用历史消息推理,专注解析结果,不要省略且结果中需要返回会议ID,不要触发其他操作,并根据结果给予用户相应自然语言反馈
'''
return False, book_promot
@@ -698,6 +702,7 @@ def process_query_avali_room(data, params) -> tuple:
logger.info("current data is :{}".format(data))
start_time = data.get("start_time", None)
end_time = data.get("end_time", None)
Region = data.get("Region", None)
all_meeting_rooms = query_room_info(data=data, params=params)
booked_rooms = query_booking_info(params=params)
book_promot = f'''
@@ -706,10 +711,17 @@ def process_query_avali_room(data, params) -> tuple:
开始时间:{start_time}
结束时间:{end_time}
所有会议室:{all_meeting_rooms}
区域信息:{Region}
已预定会议室:{booked_rooms}
```
请帮用户解析结果,给用户推荐可用会议室,如果用户给出的开始和结束时间不为空,且已预定会议室中有与该时间段冲突的预定,则把该会议室排除,不予推荐,并根据结果给予用户相应自然语言反馈
注意name或typeName字段里面可能包含了区域信息,isApprove 代表是否需要审批state是会议室的状态注意根据地理信息过滤
注意:所有会议室信息中name或typeName字段里面可能包含了区域信息,注意根据区域信息过滤,isApprove 代表是否需要审批state是会议室的状态返回结果建议如下:
```
会议室名称: <name>
会议室Id: <id>
容量: <capacity>
是否需要审批: <isApprove>
```
'''
return True, book_promot
@@ -746,35 +758,31 @@ def extract_json_blocks(text):
'''
消息对话入口函数
'''
from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIModel
from pydantic_ai.providers.openai import OpenAIProvider
provider = OpenAIProvider(api_key=config('MODEL_API_KEY'), base_url=BASE_URL)
model = OpenAIModel(MODEL_NAME, provider=provider)
agent = Agent(model, system_prompt=build_prompt({'tenantId':config('TEMP_TENANT_ID')}))
def process_chat(covers_id:str,user_id: str, user_input: str, params: dict):
history = []
query_history = dialog_manager.get_history(covers_id)
history.extend(query_history)
prompt = ''
if history is None or len(history) == 0:
prompt = build_prompt(params)
add_message_async(dialog_manager, covers_id, 'user', prompt)
logger.info("step1---userinput----------{0}".format(user_input))
add_message_async(dialog_manager, covers_id, 'user', user_input)
resp = call_openai_api(model=MODEL_NAME, system_prompt=prompt, user_query=user_input,
api_key=config('MODEL_API_KEY'),
history=history, temperature=config("MODEL_TEMPERATURE", cast=float, default=0.5))
content = resp["choices"][0]["message"]["content"]
reasoning_content = resp["choices"][0]["message"].get('reasoning_content')
req = agent.run_sync(user_prompt=user_input, message_history=history if len(history) > 0 else None)
dialog_manager.set_msg(covers_id, req.all_messages())
content = req.output
logger.info(f"process chat content is : {content}")
if "func_name" in content:
# new_content = check_and_process_think(content=content)
add_message_async(dialog_manager, covers_id, 'assistant', content)
json_content = extract_json_blocks(content)
logger.info("step3--jsoncontent----------{0}".format(json_content))
for json_item in json_content:
logger.info("jsonitem:{0} type{1}".format(json_item,type(json_item)))
# new_content = new_content.split('```json')[-1].split('```')[0]
# new_content = new_content.replace("`", '')
data = json.loads(json_item)
fun_name = data.get("func_name", None)
book_promot = ''
@@ -787,7 +795,6 @@ def process_chat(covers_id:str,user_id: str, user_input: str, params: dict):
logger.info(f"触发系统函数调用==>:{fun_name}")
params["user_id"] = user_id
add_to_content, book_promot = func(data=data, params=params)
logger.info("test point book_promot => {0} ".format(book_promot))
else:
@@ -802,29 +809,15 @@ def process_chat(covers_id:str,user_id: str, user_input: str, params: dict):
{result_false}
请帮用户解析结果,并根据结果给予用户相应自然语言反馈
'''
new_history = []
logger.info("test point completed the function call ")
query_history = dialog_manager.get_history(covers_id)
new_history.extend(query_history)
resp = call_openai_api(model=MODEL_NAME, user_query=book_promot,
api_key=config('MODEL_API_KEY'),
history=new_history,
system_prompt='',
temperature=config("MODEL_TEMPERATURE", cast=float, default=0.5),
)
content = resp["choices"][0]["message"]["content"]
resp = agent.run_sync(user_prompt=book_promot)
content=resp.output
logger.info("final content => {0}".format(content))
new_content = check_and_process_think(content)
if add_to_content:
dialog_manager.add_message(covers_id, 'user', book_promot)
add_message_async(dialog_manager, covers_id, 'assistant', new_content)
dialog_manager.add_message2(covers_id, resp.new_messages()[-1])
return {'response': new_content}
return {'response': content}
else:
new_content = check_and_process_think(content=content)
logger.info("no func ")
add_message_async(dialog_manager, covers_id, 'assistant', new_content)
if reasoning_content:
add_message_async(dialog_manager, covers_id, 'assistant', reasoning_content)
return {'response': new_content}