feat:接入调用框架,整理部分提示词
This commit is contained in:
@@ -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
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user