Showing
3 changed files
with
117 additions
and
4 deletions
| ... | @@ -13,7 +13,7 @@ API_CONFIG = { | ... | @@ -13,7 +13,7 @@ API_CONFIG = { |
| 13 | "headers": { | 13 | "headers": { |
| 14 | "accept": "*/*", | 14 | "accept": "*/*", |
| 15 | "Content-Type": "application/json", | 15 | "Content-Type": "application/json", |
| 16 | - "Authorization": os.getenv("API_AUTHORIZATION", "Bearer 2.787c2f8b84f1462a83abba60fbb5553d"), | 16 | + "Authorization": os.getenv("API_AUTHORIZATION", "Bearer 2.21e3deecca904c7697ab891b8276cf36"), |
| 17 | "Ver": os.getenv("API_VER", "033BD94B1168D7E4F0D644C3C95E35BF.D73E33B659AD1D6B7D181D1DF8D05760"), | 17 | "Ver": os.getenv("API_VER", "033BD94B1168D7E4F0D644C3C95E35BF.D73E33B659AD1D6B7D181D1DF8D05760"), |
| 18 | "Referer": os.getenv("API_REFERER", "http://192.168.1.251/") | 18 | "Referer": os.getenv("API_REFERER", "http://192.168.1.251/") |
| 19 | } | 19 | } | ... | ... |
| ... | @@ -133,6 +133,110 @@ def create_waybill_d(consignmentCode: str, Authorization: str = None) -> str: | ... | @@ -133,6 +133,110 @@ def create_waybill_d(consignmentCode: str, Authorization: str = None) -> str: |
| 133 | return f"❌ 创建D类运单失败: {str(e)}" | 133 | return f"❌ 创建D类运单失败: {str(e)}" |
| 134 | 134 | ||
| 135 | 135 | ||
| 136 | +def query_waybill_info(consignmentCode: str, Authorization: str = None) -> str: | ||
| 137 | + """根据运单编号查询运单信息 | ||
| 138 | + | ||
| 139 | + Args: | ||
| 140 | + consignmentCode: 运单编号(必填) | ||
| 141 | + Authorization: 授权令牌,如果提供则使用该值,否则使用 API_CONFIG 中的默认值 | ||
| 142 | + | ||
| 143 | + Returns: | ||
| 144 | + 运单信息,格式与 create_waybill_d 返回的数据结构相同 | ||
| 145 | + """ | ||
| 146 | + try: | ||
| 147 | + # 构建 headers,优先使用传入的 Authorization | ||
| 148 | + headers = dict(API_CONFIG['headers']) | ||
| 149 | + if Authorization: | ||
| 150 | + headers['Authorization'] = Authorization | ||
| 151 | + | ||
| 152 | + # 初始化返回数据 | ||
| 153 | + result_data = { | ||
| 154 | + "consignmentCode": consignmentCode, | ||
| 155 | + "waybill_id": "", | ||
| 156 | + "operate_unit_name": "", | ||
| 157 | + "operate_unit_code": "", | ||
| 158 | + "detailList": [] | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + # 请求表头详情,使用运单编号(chmCode)查询 | ||
| 162 | + head_url = f"{API_CONFIG['base_url']}/Exp/bus-customer/consignment/headInfo" | ||
| 163 | + waybill_id = None | ||
| 164 | + cons_type_code = "consType_D" # 默认值 | ||
| 165 | + try: | ||
| 166 | + head_resp = requests.post( | ||
| 167 | + head_url, | ||
| 168 | + headers=headers, | ||
| 169 | + json={"chmCode": consignmentCode}, | ||
| 170 | + timeout=30, | ||
| 171 | + ) | ||
| 172 | + if head_resp.status_code == 200: | ||
| 173 | + head_json = head_resp.json() | ||
| 174 | + head_extra = (head_json.get("data") or {}).get("extra") or {} | ||
| 175 | + | ||
| 176 | + # 提取运单ID | ||
| 177 | + waybill_id = head_extra.get("id") | ||
| 178 | + | ||
| 179 | + # 提取运单编号(如果返回的与输入不一致,使用返回的) | ||
| 180 | + returned_code = head_extra.get("consignmentCode") or consignmentCode | ||
| 181 | + result_data["consignmentCode"] = returned_code | ||
| 182 | + result_data["waybill_id"] = str(waybill_id) if waybill_id else "" | ||
| 183 | + | ||
| 184 | + # 提取公司信息 | ||
| 185 | + result_data["operate_unit_name"] = head_extra.get("operateUnitName") or "" | ||
| 186 | + result_data["operate_unit_code"] = head_extra.get("operateUnitCode") or "" | ||
| 187 | + | ||
| 188 | + # 提取运单类型(用于后续查询明细) | ||
| 189 | + cons_type_code = head_extra.get("consTypeDicCode") or "consType_D" | ||
| 190 | + else: | ||
| 191 | + return f"❌ 查询运单信息失败: HTTP {head_resp.status_code}, 错误信息: {head_resp.text}" | ||
| 192 | + except Exception as e: | ||
| 193 | + return f"❌ 查询表头信息失败: {str(e)}" | ||
| 194 | + | ||
| 195 | + # 若拿不到ID,直接返回已有数据 | ||
| 196 | + if not waybill_id: | ||
| 197 | + return json.dumps(result_data, ensure_ascii=False, indent=2) | ||
| 198 | + | ||
| 199 | + # 请求表体明细获取所有商品明细(sku_code 和 sku_name) | ||
| 200 | + detail_url = f"{API_CONFIG['base_url']}/Exp/bus-customer/consignment/detail/list" | ||
| 201 | + try: | ||
| 202 | + detail_payload = { | ||
| 203 | + "consType": cons_type_code, | ||
| 204 | + "consignmentId": waybill_id, | ||
| 205 | + "pageIndex": 1, | ||
| 206 | + "pageSize": 100, # 增加页面大小以获取更多记录 | ||
| 207 | + } | ||
| 208 | + detail_resp = requests.post( | ||
| 209 | + detail_url, | ||
| 210 | + headers=headers, | ||
| 211 | + json=detail_payload, | ||
| 212 | + timeout=30, | ||
| 213 | + ) | ||
| 214 | + if detail_resp.status_code == 200: | ||
| 215 | + detail_json = detail_resp.json() | ||
| 216 | + records = (detail_json.get("data") or {}).get("records") or [] | ||
| 217 | + if isinstance(records, list): | ||
| 218 | + # 遍历所有记录,构建 detailList | ||
| 219 | + for item in records: | ||
| 220 | + if isinstance(item, dict): | ||
| 221 | + detail_item = { | ||
| 222 | + "sku_code": item.get("skuCode") or "", | ||
| 223 | + "sku_name": item.get("skuName") or "" | ||
| 224 | + } | ||
| 225 | + result_data["detailList"].append(detail_item) | ||
| 226 | + except Exception: | ||
| 227 | + pass | ||
| 228 | + | ||
| 229 | + # 返回 JSON 格式数据 | ||
| 230 | + return json.dumps(result_data, ensure_ascii=False, indent=2) | ||
| 231 | + | ||
| 232 | + except requests.exceptions.RequestException as e: | ||
| 233 | + return f"❌ 网络请求失败: {str(e)}" | ||
| 234 | + except json.JSONDecodeError as e: | ||
| 235 | + return f"❌ 响应解析失败: {str(e)}" | ||
| 236 | + except Exception as e: | ||
| 237 | + return f"❌ 查询运单信息失败: {str(e)}" | ||
| 238 | + | ||
| 239 | + | ||
| 136 | def query_waybill_list(initialize: int = 1, consStatusName: str = "等待录入", Authorization: str = None) -> str: | 240 | def query_waybill_list(initialize: int = 1, consStatusName: str = "等待录入", Authorization: str = None) -> str: |
| 137 | """查询运单列表信息 | 241 | """查询运单列表信息 |
| 138 | 242 | ... | ... |
| ... | @@ -12,7 +12,7 @@ from langchain_core.messages import AnyMessage | ... | @@ -12,7 +12,7 @@ from langchain_core.messages import AnyMessage |
| 12 | sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | 12 | sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) |
| 13 | 13 | ||
| 14 | # 导入 API 模块 | 14 | # 导入 API 模块 |
| 15 | -from API.waybill_api import query_waybill_list, create_waybill_d, push_waybill_for_ocr | 15 | +from API.waybill_api import query_waybill_list, create_waybill_d, push_waybill_for_ocr, query_waybill_info |
| 16 | from API.paperless_api import upload_clearance_file | 16 | from API.paperless_api import upload_clearance_file |
| 17 | 17 | ||
| 18 | # 导入工具类 | 18 | # 导入工具类 |
| ... | @@ -179,7 +179,9 @@ def _create_system_prompt(state: Dict[str, Any], config: RunnableConfig) -> List | ... | @@ -179,7 +179,9 @@ def _create_system_prompt(state: Dict[str, Any], config: RunnableConfig) -> List |
| 179 | system_msg = f"""你是一个专业的出口物流系统智能助手,专门帮助用户处理运单相关的业务操作。 | 179 | system_msg = f"""你是一个专业的出口物流系统智能助手,专门帮助用户处理运单相关的业务操作。 |
| 180 | 180 | ||
| 181 | ## 你的主要职责: | 181 | ## 你的主要职责: |
| 182 | -1. **运单查询**:根据用户需求查询运单列表,支持按状态、时间等条件筛选,结果以JSON形式展示,AI不用对返回数据JSON进行加工 | 182 | +1. **运单查询**:根据用户需求查询运单信息 |
| 183 | + - **查询运单列表**:当用户查询运单但不提供运单号时,使用 query_waybill_list 查询运单列表,支持按状态、时间等条件筛选,结果以JSON形式展示,AI不用对返回数据JSON进行加工 | ||
| 184 | + - **查询单个运单详情**:当用户提供运单号查询时,使用 query_waybill_info 查询该运单的详细信息(包括运单基本信息、公司信息、商品明细等),返回格式与 create_waybill_d 相同 | ||
| 183 | 2. **运单创建**:协助用户创建D类运单,确保信息完整准确 | 185 | 2. **运单创建**:协助用户创建D类运单,确保信息完整准确 |
| 184 | - **重要说明**:当用户输入"创建运单"或"申报"时,都理解为"创建运单"操作,应调用 create_waybill_d 工具 | 186 | - **重要说明**:当用户输入"创建运单"或"申报"时,都理解为"创建运单"操作,应调用 create_waybill_d 工具 |
| 185 | 3. **业务咨询**:解答用户关于出口物流流程、运单状态、操作规范等问题 | 187 | 3. **业务咨询**:解答用户关于出口物流流程、运单状态、操作规范等问题 |
| ... | @@ -197,6 +199,9 @@ def _create_system_prompt(state: Dict[str, Any], config: RunnableConfig) -> List | ... | @@ -197,6 +199,9 @@ def _create_system_prompt(state: Dict[str, Any], config: RunnableConfig) -> List |
| 197 | 199 | ||
| 198 | ## 可用工具: | 200 | ## 可用工具: |
| 199 | - query_waybill_list: 查询运单列表,支持按状态筛选,需提供Authorization,结果以JSON形式展示,AI不用对返回数据JSON进行加工 | 201 | - query_waybill_list: 查询运单列表,支持按状态筛选,需提供Authorization,结果以JSON形式展示,AI不用对返回数据JSON进行加工 |
| 202 | + - **使用场景**:当用户查询运单但不提供运单号时使用此工具 | ||
| 203 | +- query_waybill_info: 根据运单编号查询单个运单的详细信息(包括运单基本信息、公司信息、商品明细等),需要提供参数(运单编号、Authorization),返回格式与 create_waybill_d 相同 | ||
| 204 | + - **使用场景**:当用户提供运单号查询运单详情时使用此工具 | ||
| 200 | - create_waybill_d: 根据运单号创建D类运单,需要提供参数(运单号、Authorization) | 205 | - create_waybill_d: 根据运单号创建D类运单,需要提供参数(运单号、Authorization) |
| 201 | - **注意**:当用户说"创建运单"或"申报"时,都应调用此工具 | 206 | - **注意**:当用户说"创建运单"或"申报"时,都应调用此工具 |
| 202 | - upload_clearance_file: 上传清关PDF文件,需要 code、slip_id、pdf_path、Authorization,上传时文件路径不用确认,路径肯定是完整的,文件肯定是存在的,不用确认文件索引,工具会自动设置索引为0,请直接调用工具接口 | 207 | - upload_clearance_file: 上传清关PDF文件,需要 code、slip_id、pdf_path、Authorization,上传时文件路径不用确认,路径肯定是完整的,文件肯定是存在的,不用确认文件索引,工具会自动设置索引为0,请直接调用工具接口 |
| ... | @@ -207,6 +212,10 @@ def _create_system_prompt(state: Dict[str, Any], config: RunnableConfig) -> List | ... | @@ -207,6 +212,10 @@ def _create_system_prompt(state: Dict[str, Any], config: RunnableConfig) -> List |
| 207 | - 空字段会显示为空单元格 | 212 | - 空字段会显示为空单元格 |
| 208 | - 运单创建结果会显示成功/失败状态和详细信息 | 213 | - 运单创建结果会显示成功/失败状态和详细信息 |
| 209 | 214 | ||
| 215 | +## query_waybill_info数据展示说明: | ||
| 216 | +- 返回格式与 create_waybill_d 相同,包含:运单编号、运单ID、公司名称、公司编码、商品明细列表 | ||
| 217 | +- 按照数据返回的原本格式进行展示,不得增删前后缀或改写内容 | ||
| 218 | + | ||
| 210 | ## create_waybill_d数据展示说明: | 219 | ## create_waybill_d数据展示说明: |
| 211 | - 按照数据返回的原本格式进行展示,不得增删前后缀或改写内容。 | 220 | - 按照数据返回的原本格式进行展示,不得增删前后缀或改写内容。 |
| 212 | 221 | ||
| ... | @@ -222,7 +231,7 @@ def _create_system_prompt(state: Dict[str, Any], config: RunnableConfig) -> List | ... | @@ -222,7 +231,7 @@ def _create_system_prompt(state: Dict[str, Any], config: RunnableConfig) -> List |
| 222 | # 创建 ReAct 智能体 | 231 | # 创建 ReAct 智能体 |
| 223 | agent = create_react_agent( | 232 | agent = create_react_agent( |
| 224 | model=model, | 233 | model=model, |
| 225 | - tools=[query_waybill_list, create_waybill_d, upload_clearance_file, push_waybill_for_ocr], | 234 | + tools=[query_waybill_list, query_waybill_info, create_waybill_d, upload_clearance_file, push_waybill_for_ocr], |
| 226 | pre_model_hook=pre_model_inspect_attachments, | 235 | pre_model_hook=pre_model_inspect_attachments, |
| 227 | prompt=_create_system_prompt, | 236 | prompt=_create_system_prompt, |
| 228 | ) | 237 | ) | ... | ... |
-
Please register or login to post a comment