zhouhui.jiang

update

...@@ -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 )
......