From fa61b11b0220ff35e921fa304ece234ddfee5cf9 Mon Sep 17 00:00:00 2001 From: jimi <1847930177@qq.com> Date: Wed, 4 Mar 2026 21:52:24 +0800 Subject: [PATCH] refactor: migrate workflow to v2 core and archive legacy modules --- .env.tianwang | 20 - __pycache__/chat_log_db.cpython-310.pyc | Bin 7764 -> 0 bytes __pycache__/customer_db.cpython-310.pyc | Bin 22395 -> 0 bytes __pycache__/daily_summary.cpython-310.pyc | Bin 7440 -> 0 bytes __pycache__/email_receiver.cpython-310.pyc | Bin 10324 -> 0 bytes __pycache__/email_sender.cpython-310.pyc | Bin 3175 -> 0 bytes __pycache__/image_analyzer.cpython-310.pyc | Bin 10592 -> 0 bytes __pycache__/image_processor.cpython-310.pyc | Bin 8919 -> 0 bytes __pycache__/image_qa.cpython-310.pyc | Bin 5737 -> 0 bytes __pycache__/image_tools.cpython-310.pyc | Bin 8023 -> 0 bytes __pycache__/perspective_fix.cpython-310.pyc | Bin 12396 -> 0 bytes __pycache__/pydantic_ai_agent.cpython-310.pyc | Bin 40286 -> 0 bytes __pycache__/service_gemini.cpython-310.pyc | Bin 13319 -> 0 bytes __pycache__/service_qwen.cpython-310.pyc | Bin 6651 -> 0 bytes __pycache__/workflow.cpython-310.pyc | Bin 17866 -> 0 bytes api/__pycache__/http_server.cpython-311.pyc | Bin 10863 -> 0 bytes config/__pycache__/__init__.cpython-310.pyc | Bin 125 -> 117 bytes config/__pycache__/config.cpython-310.pyc | Bin 1309 -> 2129 bytes core/__pycache__/__init__.cpython-310.pyc | Bin 125 -> 115 bytes .../pydantic_ai_agent.cpython-310.pyc | Bin 59328 -> 0 bytes .../websocket_client.cpython-310.pyc | Bin 38692 -> 0 bytes core/__pycache__/workflow.cpython-310.pyc | Bin 18135 -> 0 bytes core/adapters/base.py | 29 + core/adapters/qianniu_adapter.py | 92 ++ core/agent_tools.py | 713 +------------- core/engine.py | 63 ++ core/events/event_bus.py | 36 + core/orchestrator.py | 156 +++ core/pydantic_ai_agent_v2.py | 91 ++ core/repository.py | 69 ++ core/schema.py | 29 + core/skill_manager.py | 56 ++ core/websocket_client_v2.py | 81 ++ core/websocket_connection_flow.py | 35 +- core/websocket_send_flow.py | 11 +- core/提示词.MD | 19 + customer_db/customers.json | 890 +----------------- db/__pycache__/__init__.cpython-310.pyc | Bin 123 -> 113 bytes db/__pycache__/chat_log_db.cpython-310.pyc | Bin 8747 -> 14761 bytes db/__pycache__/customer_db.cpython-310.pyc | Bin 23231 -> 27380 bytes .../deal_outcome_db.cpython-310.pyc | Bin 5518 -> 0 bytes .../designer_roster_db.cpython-310.pyc | Bin 5762 -> 0 bytes db/chat_log_db.py | 14 +- db/chat_log_db/chats.db | Bin 94208 -> 102400 bytes db/image_tasks.db | Bin 0 -> 20480 bytes db/image_tasks_db.py | 501 ++-------- .../__pycache__/task_model.cpython-311.pyc | Bin 17572 -> 0 bytes image/__pycache__/__init__.cpython-310.pyc | Bin 124 -> 116 bytes .../image_analyzer.cpython-310.pyc | Bin 18719 -> 23835 bytes .../image_precheck.cpython-310.pyc | Bin 1907 -> 0 bytes .../image_processor.cpython-310.pyc | Bin 11275 -> 0 bytes image/__pycache__/image_qa.cpython-310.pyc | Bin 5875 -> 0 bytes {core => legacy}/agent_pre_rules.py | 0 {core => legacy}/agent_prompts.py | 0 {core => legacy}/ai_reply_flow.py | 0 {core => legacy}/batch_quote_helpers.py | 0 {chat_log_db => legacy/chat_log_db}/chats.db | Bin {core => legacy}/collection_intent_helpers.py | 0 {core => legacy}/context_helpers.py | 0 {core => legacy}/conversation_state_store.py | 0 legacy/customer_db/customers.json | 889 +++++++++++++++++ {db => legacy}/customer_risk_db.py | 0 {utils => legacy}/daily_summary.py | 0 {db => legacy}/deal_outcome_db.py | 0 {db => legacy}/designer_roster_db.py | 0 {evolution => legacy/evolution}/__init__.py | 0 {evolution => legacy/evolution}/mvp.py | 0 .../price_negotiation_with_registration.md | 0 .../features}/risk_customer_detection.md | 0 .../features}/self_evolution_mvp.md | 0 .../features}/text_surcharge.md | 0 {features => legacy/features}/tuhui_upload.md | 0 {core => legacy}/find_image_flow.py | 0 {core => legacy}/image_workflow_router.py | 0 {utils => legacy}/intent_analyzer.py | 0 {mail => legacy/mail}/__init__.py | 0 {mail => legacy/mail}/email_receiver.py | 0 {mail => legacy/mail}/email_sender.py | 0 {core => legacy}/message_orchestrator.py | 0 {core => legacy}/order_flow.py | 0 {core => legacy}/post_ops.py | 0 {core => legacy}/prompt_builder.py | 0 {core => legacy}/prompt_flow.py | 0 {core => legacy}/pydantic_ai_agent.py | 0 {core => legacy}/reply_finalize_flow.py | 0 .../results}/20260225211854.jpg | Bin ...debug_7debc0124b0441da9945feaeceef93b1.jpg | Bin ...final_73bc9c0c4bed4be198b200158be6f813.jpg | Bin ...final_7debc0124b0441da9945feaeceef93b1.jpg | Bin ...final_b3dd76cbc37e403ca9425ece8ba2ebcd.jpg | Bin ...final_bc3c45fd447749f38f62dbb87a942aba.jpg | Bin ...final_d9679c27640b43c18b9f590047e6c2dd.jpg | Bin ...esize_95152a96618146738c3e6a12a6a6d9d8.jpg | Bin ...esize_d9ef87fa8de14b0b8d030067d0de163e.jpg | Bin ...esult_2d5b47961e7b42eabe2fd7beb8c9be1f.jpg | Bin ...esult_3e60b204f3a748eabb41a05cc28e1a11.jpg | Bin ...esult_4cd07206b2d24c21a81c3d45a3c4e16f.jpg | Bin ...esult_5c19d435fc8e4b2caa03c589f53d61ac.jpg | Bin ...esult_90eaf777934445af81abbd60fe4778c5.jpg | Bin {core => legacy}/risk_text_helpers.py | 0 {core => legacy}/rules/__init__.py | 0 {core => legacy}/rules/engine.py | 0 .../scripts}/chat_log_viewer.py | 0 {scripts => legacy/scripts}/chat_ui.py | 0 .../scripts}/evolution_cycle.py | 0 .../scripts}/init_designer_roster.py | 0 .../scripts}/migrate_chat_logs_to_mysql.py | 0 .../migrate_customers_json_to_mysql.py | 0 .../migrate_remaining_sqlite_to_mysql.py | 0 .../scripts}/multi_process_launcher.py | 0 .../scripts}/run_test_ai_chat.ps1 | 0 .../websocket_agent_reply_flow.py | 0 {core => legacy}/websocket_auto_quote_flow.py | 0 {core => legacy}/websocket_brain_flow.py | 0 {core => legacy}/websocket_callback_flow.py | 0 {core => legacy}/websocket_client.py | 0 .../websocket_customer_profile_flow.py | 0 {core => legacy}/websocket_debounce_flow.py | 0 {core => legacy}/websocket_dispatch_flow.py | 0 {core => legacy}/websocket_followup_flow.py | 0 {core => legacy}/websocket_helpers_flow.py | 0 .../websocket_image_entry_flow.py | 0 {core => legacy}/websocket_inbound_flow.py | 0 .../websocket_message_utils_flow.py | 0 {core => legacy}/websocket_misc_rules_flow.py | 0 .../websocket_outbound_arbiter_flow.py | 0 {core => legacy}/websocket_outbound_flow.py | 0 {core => legacy}/websocket_quote_flow.py | 0 {core => legacy}/websocket_summary_flow.py | 0 .../websocket_system_inquiry_flow.py | 0 {core => legacy}/websocket_transfer_flow.py | 0 {core => legacy}/websocket_workflow_flow.py | 0 {utils => legacy}/wechat_chat_log.py | 0 {core => legacy}/workflow.py | 0 部署文档.md => legacy/部署文档.md | 0 项目功能汇总.md => legacy/项目功能汇总.md | 0 mail/__pycache__/__init__.cpython-310.pyc | Bin 126 -> 0 bytes .../email_receiver.cpython-310.pyc | Bin 10370 -> 0 bytes mail/__pycache__/email_sender.cpython-310.pyc | Bin 3368 -> 0 bytes run.py | 4 +- scripts/__pycache__/chat_ui.cpython-310.pyc | Bin 13624 -> 0 bytes services/__pycache__/__init__.cpython-310.pyc | Bin 127 -> 119 bytes .../service_gemini.cpython-310.pyc | Bin 13464 -> 0 bytes .../__pycache__/service_meitu.cpython-310.pyc | Bin 21706 -> 0 bytes .../service_vectorizer.cpython-310.pyc | Bin 12491 -> 0 bytes services/dispatch_service.py | 49 + utils/__pycache__/__init__.cpython-310.pyc | Bin 124 -> 116 bytes .../api_cost_tracker.cpython-310.pyc | Bin 3139 -> 0 bytes .../content_filter.cpython-310.pyc | Bin 4675 -> 0 bytes .../__pycache__/daily_summary.cpython-310.pyc | Bin 8677 -> 0 bytes .../designer_roster.cpython-310.pyc | Bin 1560 -> 0 bytes .../__pycache__/health_check.cpython-310.pyc | Bin 3797 -> 0 bytes utils/__pycache__/image_queue.cpython-310.pyc | Bin 1602 -> 0 bytes .../intent_analyzer.cpython-310.pyc | Bin 4480 -> 0 bytes .../__pycache__/service_base.cpython-310.pyc | Bin 4136 -> 0 bytes .../wechat_chat_log.cpython-310.pyc | Bin 4304 -> 0 bytes 156 files changed, 1781 insertions(+), 2066 deletions(-) delete mode 100644 .env.tianwang delete mode 100755 __pycache__/chat_log_db.cpython-310.pyc delete mode 100755 __pycache__/customer_db.cpython-310.pyc delete mode 100755 __pycache__/daily_summary.cpython-310.pyc delete mode 100755 __pycache__/email_receiver.cpython-310.pyc delete mode 100755 __pycache__/email_sender.cpython-310.pyc delete mode 100755 __pycache__/image_analyzer.cpython-310.pyc delete mode 100755 __pycache__/image_processor.cpython-310.pyc delete mode 100755 __pycache__/image_qa.cpython-310.pyc delete mode 100755 __pycache__/image_tools.cpython-310.pyc delete mode 100755 __pycache__/perspective_fix.cpython-310.pyc delete mode 100755 __pycache__/pydantic_ai_agent.cpython-310.pyc delete mode 100755 __pycache__/service_gemini.cpython-310.pyc delete mode 100755 __pycache__/service_qwen.cpython-310.pyc delete mode 100755 __pycache__/workflow.cpython-310.pyc delete mode 100644 api/__pycache__/http_server.cpython-311.pyc delete mode 100755 core/__pycache__/pydantic_ai_agent.cpython-310.pyc delete mode 100755 core/__pycache__/websocket_client.cpython-310.pyc delete mode 100755 core/__pycache__/workflow.cpython-310.pyc create mode 100644 core/adapters/base.py create mode 100644 core/adapters/qianniu_adapter.py create mode 100644 core/engine.py create mode 100644 core/events/event_bus.py create mode 100644 core/orchestrator.py create mode 100644 core/pydantic_ai_agent_v2.py create mode 100644 core/repository.py create mode 100644 core/schema.py create mode 100644 core/skill_manager.py create mode 100644 core/websocket_client_v2.py create mode 100644 core/提示词.MD delete mode 100755 db/__pycache__/deal_outcome_db.cpython-310.pyc delete mode 100755 db/__pycache__/designer_roster_db.cpython-310.pyc create mode 100644 db/image_tasks.db delete mode 100644 db/task_db/__pycache__/task_model.cpython-311.pyc delete mode 100755 image/__pycache__/image_precheck.cpython-310.pyc delete mode 100755 image/__pycache__/image_processor.cpython-310.pyc delete mode 100755 image/__pycache__/image_qa.cpython-310.pyc rename {core => legacy}/agent_pre_rules.py (100%) rename {core => legacy}/agent_prompts.py (100%) rename {core => legacy}/ai_reply_flow.py (100%) rename {core => legacy}/batch_quote_helpers.py (100%) rename {chat_log_db => legacy/chat_log_db}/chats.db (100%) mode change 100755 => 100644 rename {core => legacy}/collection_intent_helpers.py (100%) rename {core => legacy}/context_helpers.py (100%) rename {core => legacy}/conversation_state_store.py (100%) create mode 100644 legacy/customer_db/customers.json rename {db => legacy}/customer_risk_db.py (100%) rename {utils => legacy}/daily_summary.py (100%) mode change 100755 => 100644 rename {db => legacy}/deal_outcome_db.py (100%) mode change 100755 => 100644 rename {db => legacy}/designer_roster_db.py (100%) mode change 100755 => 100644 rename {evolution => legacy/evolution}/__init__.py (100%) rename {evolution => legacy/evolution}/mvp.py (100%) rename {features => legacy/features}/price_negotiation_with_registration.md (100%) rename {features => legacy/features}/risk_customer_detection.md (100%) rename {features => legacy/features}/self_evolution_mvp.md (100%) rename {features => legacy/features}/text_surcharge.md (100%) rename {features => legacy/features}/tuhui_upload.md (100%) rename {core => legacy}/find_image_flow.py (100%) rename {core => legacy}/image_workflow_router.py (100%) rename {utils => legacy}/intent_analyzer.py (100%) mode change 100755 => 100644 rename {mail => legacy/mail}/__init__.py (100%) mode change 100755 => 100644 rename {mail => legacy/mail}/email_receiver.py (100%) mode change 100755 => 100644 rename {mail => legacy/mail}/email_sender.py (100%) mode change 100755 => 100644 rename {core => legacy}/message_orchestrator.py (100%) rename {core => legacy}/order_flow.py (100%) rename {core => legacy}/post_ops.py (100%) rename {core => legacy}/prompt_builder.py (100%) rename {core => legacy}/prompt_flow.py (100%) rename {core => legacy}/pydantic_ai_agent.py (100%) mode change 100755 => 100644 rename {core => legacy}/reply_finalize_flow.py (100%) rename {results => legacy/results}/20260225211854.jpg (100%) mode change 100755 => 100644 rename {results => legacy/results}/debug_7debc0124b0441da9945feaeceef93b1.jpg (100%) mode change 100755 => 100644 rename {results => legacy/results}/pfix_final_73bc9c0c4bed4be198b200158be6f813.jpg (100%) mode change 100755 => 100644 rename {results => legacy/results}/pfix_final_7debc0124b0441da9945feaeceef93b1.jpg (100%) mode change 100755 => 100644 rename {results => legacy/results}/pfix_final_b3dd76cbc37e403ca9425ece8ba2ebcd.jpg (100%) mode change 100755 => 100644 rename {results => legacy/results}/pfix_final_bc3c45fd447749f38f62dbb87a942aba.jpg (100%) mode change 100755 => 100644 rename {results => legacy/results}/pfix_final_d9679c27640b43c18b9f590047e6c2dd.jpg (100%) mode change 100755 => 100644 rename {results => legacy/results}/resize_95152a96618146738c3e6a12a6a6d9d8.jpg (100%) mode change 100755 => 100644 rename {results => legacy/results}/resize_d9ef87fa8de14b0b8d030067d0de163e.jpg (100%) mode change 100755 => 100644 rename {results => legacy/results}/result_2d5b47961e7b42eabe2fd7beb8c9be1f.jpg (100%) mode change 100755 => 100644 rename {results => legacy/results}/result_3e60b204f3a748eabb41a05cc28e1a11.jpg (100%) mode change 100755 => 100644 rename {results => legacy/results}/result_4cd07206b2d24c21a81c3d45a3c4e16f.jpg (100%) mode change 100755 => 100644 rename {results => legacy/results}/result_5c19d435fc8e4b2caa03c589f53d61ac.jpg (100%) mode change 100755 => 100644 rename {results => legacy/results}/result_90eaf777934445af81abbd60fe4778c5.jpg (100%) mode change 100755 => 100644 rename {core => legacy}/risk_text_helpers.py (100%) rename {core => legacy}/rules/__init__.py (100%) rename {core => legacy}/rules/engine.py (100%) rename {scripts => legacy/scripts}/chat_log_viewer.py (100%) mode change 100755 => 100644 rename {scripts => legacy/scripts}/chat_ui.py (100%) mode change 100755 => 100644 rename {scripts => legacy/scripts}/evolution_cycle.py (100%) rename {scripts => legacy/scripts}/init_designer_roster.py (100%) mode change 100755 => 100644 rename {scripts => legacy/scripts}/migrate_chat_logs_to_mysql.py (100%) rename {scripts => legacy/scripts}/migrate_customers_json_to_mysql.py (100%) rename {scripts => legacy/scripts}/migrate_remaining_sqlite_to_mysql.py (100%) rename {scripts => legacy/scripts}/multi_process_launcher.py (100%) rename {scripts => legacy/scripts}/run_test_ai_chat.ps1 (100%) rename {core => legacy}/websocket_agent_reply_flow.py (100%) rename {core => legacy}/websocket_auto_quote_flow.py (100%) rename {core => legacy}/websocket_brain_flow.py (100%) rename {core => legacy}/websocket_callback_flow.py (100%) rename {core => legacy}/websocket_client.py (100%) mode change 100755 => 100644 rename {core => legacy}/websocket_customer_profile_flow.py (100%) rename {core => legacy}/websocket_debounce_flow.py (100%) rename {core => legacy}/websocket_dispatch_flow.py (100%) rename {core => legacy}/websocket_followup_flow.py (100%) rename {core => legacy}/websocket_helpers_flow.py (100%) rename {core => legacy}/websocket_image_entry_flow.py (100%) rename {core => legacy}/websocket_inbound_flow.py (100%) rename {core => legacy}/websocket_message_utils_flow.py (100%) rename {core => legacy}/websocket_misc_rules_flow.py (100%) rename {core => legacy}/websocket_outbound_arbiter_flow.py (100%) rename {core => legacy}/websocket_outbound_flow.py (100%) rename {core => legacy}/websocket_quote_flow.py (100%) rename {core => legacy}/websocket_summary_flow.py (100%) rename {core => legacy}/websocket_system_inquiry_flow.py (100%) rename {core => legacy}/websocket_transfer_flow.py (100%) rename {core => legacy}/websocket_workflow_flow.py (100%) rename {utils => legacy}/wechat_chat_log.py (100%) mode change 100755 => 100644 rename {core => legacy}/workflow.py (100%) mode change 100755 => 100644 rename 部署文档.md => legacy/部署文档.md (100%) rename 项目功能汇总.md => legacy/项目功能汇总.md (100%) delete mode 100755 mail/__pycache__/__init__.cpython-310.pyc delete mode 100755 mail/__pycache__/email_receiver.cpython-310.pyc delete mode 100755 mail/__pycache__/email_sender.cpython-310.pyc delete mode 100755 scripts/__pycache__/chat_ui.cpython-310.pyc delete mode 100755 services/__pycache__/service_gemini.cpython-310.pyc delete mode 100755 services/__pycache__/service_meitu.cpython-310.pyc delete mode 100755 services/__pycache__/service_vectorizer.cpython-310.pyc create mode 100644 services/dispatch_service.py delete mode 100755 utils/__pycache__/api_cost_tracker.cpython-310.pyc delete mode 100755 utils/__pycache__/content_filter.cpython-310.pyc delete mode 100755 utils/__pycache__/daily_summary.cpython-310.pyc delete mode 100755 utils/__pycache__/designer_roster.cpython-310.pyc delete mode 100755 utils/__pycache__/health_check.cpython-310.pyc delete mode 100755 utils/__pycache__/image_queue.cpython-310.pyc delete mode 100755 utils/__pycache__/intent_analyzer.cpython-310.pyc delete mode 100755 utils/__pycache__/service_base.cpython-310.pyc delete mode 100755 utils/__pycache__/wechat_chat_log.cpython-310.pyc diff --git a/.env.tianwang b/.env.tianwang deleted file mode 100644 index bdc3ed5..0000000 --- a/.env.tianwang +++ /dev/null @@ -1,20 +0,0 @@ -# AI 客服配置 -AI_CS_HOST=127.0.0.1 -AI_CS_PORT=6060 - -# AI 客服 HTTP API 地址(本地) -AI_CS_API_URL=http://127.0.0.1:6060 - -# 天网服务器配置(公网 IP,用户自行配置) -# TIANWANG_PUBLIC_IP=你的公网 IP -# TIANWANG_PUBLIC_PORT=你的公网端口 - -# 天网回调地址(AI 客服完成任务后回调天网) -TIANWANG_CALLBACK_URL=http://127.0.0.1:6060/api/task/callback - -# API 接口 -TASK_RECEIVE=/api/task/receive -TASK_STATUS=/api/task/status -TASK_CANCEL=/api/task/cancel -TASK_LIST=/api/task/list -HEALTH=/api/health diff --git a/__pycache__/chat_log_db.cpython-310.pyc b/__pycache__/chat_log_db.cpython-310.pyc deleted file mode 100755 index 927e77040fdc36dd8693270ae9336af9ba494b8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7764 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 DS>9`< diff --git a/__pycache__/email_receiver.cpython-310.pyc b/__pycache__/email_receiver.cpython-310.pyc deleted file mode 100755 index 8104f57dcce6c65b64f46a911424a5a5f4c5ea7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10324 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 diff --git a/__pycache__/email_sender.cpython-310.pyc b/__pycache__/email_sender.cpython-310.pyc deleted file mode 100755 index 4813bd2512339d9a57efbcdcbef92f1abe0c293f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3175 zcma)8>u(#!5#QT89*@U|s7D@7o0c#N6hvbgZIjjz2q8wKGzKc!5LFo2x;RkWvqblf zNAKOmwn_%Fr6g7!wS&5KU`sXW#DUX?oV0H_TU1VThgzCNygd&2dM6o3iNwktI0SW#Oen&_)m%+`r6`cW%xCrH9hlBD1@D`oeP9toK}^GHI!Kr}}61w{3E zOwwk09+6&(^C%nl`@o5fGb_#2o2_&2Z_J%;UvIRQFK&Pojc27GId))dbj-KBQl-E= z5NKR5X`bZ$81Emj3)3br>MLe}nkoGs~|Px#{i_ z2j)enE(KyDhy&s=ATq^NUO+^NDYTbH%m`JXMxkn^YC^jU?Sgfg+EJbAG`Pt}FaUdS5i=ArV zDl)Jq3tpy51J6q!Q3M~MSd2#mr*=41a8as>u_#60OKhCP@?(>Sj8_ikCj-=B4jr7B zB=QUUe%|4Kl^>lTNuhUWe?EWs;KT@t=SRm!MkkE%{bQqI4b87tT9?0Stz2y{y_eMj z?6`qCZSt50G1vAg#*E{7fm|wk9lqkQ&93j7EJzBiO2KtcIE)5ySH#CC7i_-4ifdX& zKS68&f^h%Yk)b1#CbLWBg6FU!CJ(0(>JL^<1)5=$$|cV*dU@FRc}PipQVPC4X?CD1 z_=B5@XXPT_j?KdNj++L88wtdYCHnQZ3@iFs9JRJg!F?=rW>07ux8uQiasYp{fLJ3|b7W4sE2a zdeN#(<1kBZND`_l%=WY@*c(B=dHx8lskNvVJEqs;)o4RvmY1kTX<{Cqd$y)|$*NXQ zH4yweR*ltrXp*L?s`#JWz+elkS7Y4jVMKcrq@a0OLS^m8$elg`QvSUP_4qz7UGL?q zgWA`?HNC3W`x`In$^%UgoI`yf9 zYHMt&D*T!D)Z(wl^PTpDbOL4jeVBptOs9mn5n{-eaI3SQ zO}j%|9G|ke%|n^?g`0po&D*zO^4iL0JG43}Fq8=mH@{fjxcb2k4W1jD!|lI+*#6U7 zJBGug8Op$sSX+E+{nm}vR|~DP7uOrtx74;e6C$x5@$+}PUB6f~U3d3TX3BA_=Q6u( z;2;%2;CigKHT`A3A5yTr^p}k{-dnr75_-%JYZep8WnmRNy5I_pZ!Xbmi3a$aMES0AN<+xu0I2t`!G{yZ9$S{yiFdkd>6emw}vWt^v zfCRGbP7}FAPZF(UPaDEf=_p9-X`%w2y#|mbnF6mu@&um+Fjl7AlKV3tiGE$eSi`#| z4Zc2Ek<(H_d;>tg`w-8iRZU7u12CGvDV&kCIsEV0bT@=?gF&+ByPgA)6L1;yiaj!@ z=@wZjTuzdiE?lHWn3y|IEDD~ePz8!T2OTO^WquB8aFJ9opoPqNsw_upfLC>aQB}37 zH28HE@%h3!`@ZsS`|SC(OAF1rORYbg_P+-s?K9W8K->o;y~ zTsqgjcys;qg|&aKhQ5M}|ChzJYs)-57p}BFUu`cew!Z$W2uYXkxxG7s4Ds5r2U&^z z2>j1RyG{bn5w?euK~A<02EUxUlD(hjrcre4iUkh=YQVkz+c8jaIa25v##mM!;)wPj zotpjrqdEP^ysR{yjq{tGzXuE>&<(?OsBiIp!Z42e1*HQ=pRGz|76_vVM3@a$$h z%>#v&ik?^z+slR99*Z7NWflX%J#?Q3q9H{BPZP=maQ9zW#t*TAztto70ao?<_=Rq% zDx|6V!a}x>{ghkdIL3YegbaxH#h_iX%|UzfQ7d4P^mGk*@Vpgh2ybPMQsD$~ZUy#{ zL?{k%PatZbdZ#LYV%rNPYWUt|8vi|CQ4mh+Jd^(0!UHWAhIE)eJ6*o53gW;NLQ(>N MC?TmhCF{Tb4;y`}b^rhX diff --git a/__pycache__/image_analyzer.cpython-310.pyc b/__pycache__/image_analyzer.cpython-310.pyc deleted file mode 100755 index c7887a5417a7c251990207f6627985e95a2a68d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10592 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 diff --git a/__pycache__/image_processor.cpython-310.pyc b/__pycache__/image_processor.cpython-310.pyc deleted file mode 100755 index 3222338c0de5be9ec3cc8c0f9c1e6468d37f88ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8919 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 vfdK8t@;bJBF#PwnY%X7-wcPao!fPPa diff --git a/__pycache__/image_tools.cpython-310.pyc b/__pycache__/image_tools.cpython-310.pyc deleted file mode 100755 index 3a673e8eb7e807a6e332a6ecb9f2e32aaa9dd010..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8023 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 diff --git a/__pycache__/pydantic_ai_agent.cpython-310.pyc b/__pycache__/pydantic_ai_agent.cpython-310.pyc deleted file mode 100755 index 944455bf5d39dedf7f5ed12687b7a2b081721ab9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40286 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 qJ*08pbQscKpAPI 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 NUG9dOt@KO({eM#N`P={i diff --git a/__pycache__/service_qwen.cpython-310.pyc b/__pycache__/service_qwen.cpython-310.pyc deleted file mode 100755 index 5563e6e603ed23973c9fce0e4496b5db37c376dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6651 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 diff --git a/api/__pycache__/http_server.cpython-311.pyc b/api/__pycache__/http_server.cpython-311.pyc deleted file mode 100644 index f98aae378ed44d0056c59be44e115e46e6eadc49..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10863 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 diff --git a/config/__pycache__/__init__.cpython-310.pyc b/config/__pycache__/__init__.cpython-310.pyc index 0e2270a5b5b92694e1ae733326a3ccb1c8f71d53..d777f27204c405c0c198d03ba87ad78539f1c448 100755 GIT binary patch delta 29 jcmb;|<;~~iVb5N>1dpVv}&OiYY0d7^(pPa?c1h delta 37 rcmXS|<;~~ihV~(i?F`JKv@v->XD~I`>adZ|!pRP4I0Qmb|CP!8$3Caaqii>_<4 z`DUd>*L7LlsyKCBuXnd8t|YTmmZTKh4Jz1>&9o~WdZv+NE-IahDaiyKdPCQ~h9=$X zR*vBz%}I(33byFpapeT=Y1Qio>&&yIDFLNF^2n6VsMTz&5g6Dl6{yYao;O04xi0JOb zl%W(iJu-B~QH7r!#!JFEuNy$o8wAkDb7z1kK|hdyAR_BO0agGk6o>rC+{a4p0Z0N~ zKZ~0X)82usdoIhdz5pJFZ|ar>0dVdBqC1hTAFz@v0H~+pa7gAQ00GDL`G7~W;Qc)i z$tLhSxdA63L%Yj`tow#!6XF0rC?bm(5GCM;UT#SC3W2|qk^O-00sXA(i%XDoOJ1Hs zxzW&=8jhjz|K=npfI(ki{49RH^z>?K<-@P{_cGg$GauijHs7QdHd3>%Gi%GKxrgbE z+4R&JUfo%pOU>WkSy=zRwUydjNxfQ5Kby;JKF@4FO})6YGk^En?P=sMJ#f3dm#`ji z1=$Bg*zfg$o7U)LG^SpKq44$bkTwam@i8^(yb_Is9j?R|gAMO%#?VR!6Bc7NW{=Sx z&%+O`<&!UK2!&%>A(1A6Lj;EjN-$8)SY$%gv?IhQBd`)2C9o0L2`UJx2&yqq&gfWV zB&O96qn4nKpnQPvnzf%3|E8lgP*`yO61wF-jqYDVRZ1eR3X?A7j+y zy-W(6QEbWid1;yHQInrB1p~#bnCAk?8_ac+8(D;btf?#}a+->_*yH0<@{{A^Z!zT; z-(oLFEXl~pOe$gm+7vZ;J)17$t;u)Ulo)SKVwbIF1qv3i0f}48nRz8e93U!#kQb1xQLy-oE4I+NYxmd-7q!#67 f<|UTo7sWt)0Hr2BW*1^Kn*5F3fR$N*QG^)){0~N{ diff --git a/core/__pycache__/__init__.cpython-310.pyc b/core/__pycache__/__init__.cpython-310.pyc index 735cef9bdb3455f3406d8dd35e7332a581b7ef26..12c75961ca7205ff15237ca8823cf203d2a5b324 100755 GIT binary patch delta 27 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 diff --git a/core/__pycache__/websocket_client.cpython-310.pyc b/core/__pycache__/websocket_client.cpython-310.pyc deleted file mode 100755 index cbcd6fe0442dcb246fdc4e2cea632026d88a9ac9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38692 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�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 Sm|v=iiP71@-}67^C;tzK?squ= diff --git a/core/adapters/base.py b/core/adapters/base.py new file mode 100644 index 0000000..9a9a363 --- /dev/null +++ b/core/adapters/base.py @@ -0,0 +1,29 @@ +from abc import ABC, abstractmethod +from core.schema import StandardMessage, StandardResponse + +class BaseAdapter(ABC): + """ + 消息适配器基类 (Interface) + 所有的平台接口(千牛、微信等)都必须继承并实现这几个方法 + """ + + @abstractmethod + async def translate_inbound(self, raw_msg: any) -> StandardMessage: + """ + [接收]:把各个平台的原始 JSON 数据,格式化为大脑认的 StandardMessage + """ + pass + + @abstractmethod + async def translate_outbound(self, response: StandardResponse, user_id: str): + """ + [发送]:把大脑生成的 StandardResponse,翻译回平台原生的接口发出去 + """ + pass + + @abstractmethod + def platform_id(self) -> str: + """ + 标识当前平台名称 (如 'qianniu', 'wechat') + """ + pass diff --git a/core/adapters/qianniu_adapter.py b/core/adapters/qianniu_adapter.py new file mode 100644 index 0000000..69abb25 --- /dev/null +++ b/core/adapters/qianniu_adapter.py @@ -0,0 +1,92 @@ +import re +import logging +import json +from pathlib import Path +from typing import List, Tuple +from core.adapters.base import BaseAdapter +from core.schema import StandardMessage, StandardResponse + +logger = logging.getLogger("cs_agent") + +class QianniuAdapter(BaseAdapter): + """ + 千牛适配器:支持识别消息来源(客户 vs 商家人工)。 + """ + def __init__(self, ws_client=None): + self.ws_client = ws_client + self._default_group_id = "20252916034" + + def platform_id(self) -> str: + return "qianniu" + + def _resolve_group_id(self, acc_id: str) -> str: + try: + config_path = Path("config/transfer_groups.json") + if config_path.exists(): + with open(config_path, "r", encoding="utf-8") as f: + cfg = json.load(f) + return cfg.get(acc_id, self._default_group_id) + except Exception: pass + return self._default_group_id + + async def translate_inbound(self, raw: dict) -> Tuple[StandardMessage, str]: + """ + 返回: (标准消息, 消息方向) + direction: 'in' (客户发给商家), 'out' (商家人工在后台回复) + """ + if not isinstance(raw, dict): raw = {} + + acc_id = str(raw.get("acc_id") or raw.get("shop_id") or "") + from_id = str(raw.get("from_id") or raw.get("cy_id") or "") + msg_text = str(raw.get("msg") or raw.get("content") or "") + + # 判断方向:如果 from_id 包含了店铺名或 acc_id,通常说明是商家自己在说话 + # 或者逆向接口通常有一个特定的标识,这里我们做一个通用的逻辑判断 + direction = "in" + user_id = from_id + + # 逻辑:如果发送者 ID 等于 店铺 ID,说明是【商家人工回复】 + if from_id == acc_id and acc_id != "": + direction = "out" + # 此时 cy_id (客户ID) 通常在另一个字段里 + user_id = str(raw.get("cy_id") or "") + + msg = StandardMessage( + platform=self.platform_id(), + msg_id=str(raw.get("msg_id", "")), + user_id=user_id, + user_name=str(raw.get("from_name", "")), + content=msg_text, + image_urls=self._extract_urls(msg_text), + acc_id=acc_id, + acc_type=str(raw.get("acc_type") or "AliWorkbench"), + raw_data=raw + ) + return msg, direction + + async def translate_outbound(self, res: StandardResponse, user_id: str): + if not self.ws_client: return + if not res or (not res.should_reply and not res.need_transfer): return + + meta = res.metadata if isinstance(res.metadata, dict) else {} + acc_id = meta.get("acc_id", "") + acc_type = meta.get("acc_type", "AliWorkbench") + + if "[转移会话]" in res.reply_content: + content = res.reply_content + elif res.need_transfer: + group_id = self._resolve_group_id(acc_id) + content = f"正在为您转接|[转移会话],分组{group_id},无原因" + else: + content = res.reply_content + + try: + await self.ws_client.send(customer_id=user_id, acc_id=acc_id, acc_type=acc_type, content=content, msg_type=res.msg_type) + except Exception as e: + logger.error(f"[QianniuAdapter] 发送失败: {e}") + + def _extract_urls(self, text: str) -> List[str]: + if not text: return [] + image_exts = (".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp") + candidates = re.findall(r'https?://[^\s#]+', text) + return [u for u in candidates if any(ext in u.lower() for ext in image_exts)] diff --git a/core/agent_tools.py b/core/agent_tools.py index 76c16fb..b1f4505 100644 --- a/core/agent_tools.py +++ b/core/agent_tools.py @@ -1,688 +1,39 @@ -from __future__ import annotations - import logging -from typing import Any - +import asyncio +from typing import List, Optional, Dict, Any +from pydantic import BaseModel, Field from pydantic_ai import RunContext - -from db.customer_risk_db import risk_db -from services.service_tuhui_upload import upload_to_tuhui -from core.order_helpers import parse_order_info +from core.schema import StandardResponse +from services.dispatch_service import dispatch_service logger = logging.getLogger("cs_agent") +async def transfer_to_human_tool(ctx: RunContext[Any], reason: str = Field(description="转人工的原因")) -> str: + """ + 【核心工具】执行转人工逻辑。 + 获取设计师姓名并生成精准转接指令。 + """ + logger.info(f"[Tool] 尝试呼叫设计师接手: {reason}") + + # 1. 尝试派单获取设计师姓名 + designer_name = await dispatch_service.assign_designer() + + if designer_name: + # 2. 有设计师在线:生成标准转接指令 + magic_cmd = f"正在为您转接|[转移会话],{designer_name},无原因" + logger.info(f"[Tool] 成功呼叫设计师: {designer_name}") + return magic_cmd + else: + # 3. 设计师下线:返回特定信号 + logger.warning("[Tool] 派单失败:设计师们已下线或不在位") + return "ERROR_NO_DESIGNER_ONLINE" -def register_tools(agent) -> None: - """注册所有 Tool,让 Agent 可以主动调用。""" +async def check_order_status_tool(ctx: RunContext[Any], customer_id: str = Field(description="客户ID")) -> str: + """查询订单状态。""" + return "设计师正在后台加急处理中,请稍等哈。" - @agent.agent.tool - async def analyze_image(ctx: RunContext[Any], image_url: str) -> str: - """ - 分析客户发来的图片复杂度,用于报价。 - 收到图片URL时调用此工具,返回复杂度和建议报价。 - """ - try: - from image.image_analyzer import image_analyzer - result = await image_analyzer.analyze(image_url) - complexity_label = { - "simple": "简单(画面干净)", - "normal": "一般复杂度", - "complex": "细节偏多", - "hard": "非常复杂", - }.get(result["complexity"], result["complexity"]) - # 持久化图片URL和复杂度,重启后仍能记住这张图 - try: - from db.customer_db import db - db.update_last_image( - ctx.deps.from_id, - image_url, - complexity=result["complexity"], - gemini_prompt=result.get("gemini_prompt", ""), - aspect_ratio=result.get("aspect_ratio", "1:1"), - perspective=result.get("perspective", "no"), - ) - except Exception: - pass - - # 存图片类型到客户画像 - try: - from db.customer_db import db as _db - if result.get("subject"): - _db.add_image_type(ctx.deps.from_id, result["subject"]) - except Exception: - pass - - # 在 workflow 里创建待处理任务(付款后自动触发 Gemini) - try: - from core.workflow import workflow - await workflow.image_analysis_result( - customer_id=ctx.deps.from_id, - image_url=image_url, - complexity=result["complexity"], - acc_id=ctx.deps.acc_id, - acc_type=ctx.deps.platform, - gemini_prompt=result.get("gemini_prompt", ""), - aspect_ratio=result.get("aspect_ratio", "1:1"), - perspective=result.get("perspective", "no"), - proc_type=result.get("proc_type", ""), - subject=result.get("subject", ""), - quality=result.get("quality", ""), - ) - logger.info( - "[Agent] Workflow 任务已创建 | 客户: %s | 比例: %s | 透视: %s | 图片: %s...", - ctx.deps.from_id, - result.get("aspect_ratio"), - result.get("perspective"), - image_url[:60], - ) - except Exception as e: - logger.exception("[Agent] Workflow 任务创建失败: %s", e) - - # 组装给 AI 的分析报告 - risk = result.get("risk", "none") - has_face = result.get("has_face", "no") - feasibility = result.get("feasibility", "yes") - note = result.get("note", "") - - lines = [ - f"图片主体:{result['subject'] or '未识别'}", - f"处理类型:{result['proc_type'] or '高清修复'}", - f"原图质量:{result['quality'] or '未知'}", - f"图片类型:{result.get('category', '') or '通用'}", - f"图片尺寸:{(result.get('width') or 0)}x{(result.get('height') or 0)}({result.get('megapixels', 0.0)}MP)", - f"含人脸:{'是' if has_face == 'yes' else '否'}", - f"复杂度:{complexity_label}", - f"原因:{result['reason']}", - ] - if result.get("size_surcharge"): - lines.append(f"尺寸加价:+{result['size_surcharge']}元") - if result.get("size_note"): - lines.append(f"尺寸提示:{result['size_note']}") - try: - st = agent._get_conversation_state(ctx.deps.from_id) - if isinstance(result.get("price_min"), (int, float)): - st.last_min_price = int(result.get("price_min") or 0) - try: - from db.customer_db import db as _db - _db.update_last_min_price(ctx.deps.from_id, st.last_min_price) - except Exception: - pass - except Exception: - pass - - # 根据可做性和风险等级给 AI 不同的行动指引 - if feasibility == "no": - if "敏感" in (note or ""): - lines.append("【拒绝】图片含敏感/黄色/擦边内容,不接单。") - lines.append("→ 直接拒绝,不说「发图来看看」,自然回复如:这类不做/不接。") - else: - lines.append("【无法处理】此图无法处理(纯黑/纯白/完全损坏/要找原始RAW文件)。") - lines.append("→ 告知客户无法处理,建议换图或说明原因,不要报价。") - elif risk == "high": - lines.append(f"【高风险】此图处理风险高:{note or 'AI修复后效果不能保证与原图一致'}") - lines.append(f"建议报价:{result['price_suggest']}元") - lines.append("→ 先自然说明风险(人脸/效果可能不完美),再报价,满意再拍。话术自然。") - elif risk == "low": - lines.append(f"【低风险-含人脸】修复后人脸相似度约70-90%,效果不稳定。") - lines.append(f"建议报价:{result['price_suggest']}元") - lines.append(f"→ 报价时自然加一句风险提示(人脸可能有轻微变化、满意再付等)") - else: - # 无风险,正常报价 - base_price = result.get('price_suggest', 20) - text_surcharge = result.get('text_surcharge', 0) - layer_surcharge = result.get('layer_surcharge', 0) - total_price = base_price + text_surcharge + layer_surcharge - - # 构建报价说明 - price_explanation = f"建议报价:{total_price}元" - if text_surcharge > 0: - price_explanation += f"(含文字处理 +{text_surcharge}元)" - if layer_surcharge > 0: - price_explanation += f"(含分层 +{layer_surcharge}元)" - - lines.append(price_explanation) - - # 添加文字数量说明 - text_amount = result.get('text_amount', 'none') - if text_amount != 'none': - lines.append(f"文字数量:{text_amount},需要精细处理") - - if feasibility == "partial": - lines.append(f"⚠️ 此图有一定难度:{note or '效果可能不完美'},回复时可加「效果不满意退款」") - if note and note not in ("无", ""): - lines.append(f"提示:{note}") - lines.append(f"【立刻回复客户报价 {total_price} 元,话术自然多变】") - - return "\n".join(lines) - except Exception as e: - return f"图片分析失败: {e},请根据经验判断报价" - - @agent.agent.tool - async def get_customer_info(ctx: RunContext[Any], customer_id: str) -> str: - """ - 查询客户历史信息:消费记录、性格标签、报价历史等。 - 对话开始时或需要了解客户背景时调用。 - """ - try: - from db.customer_db import db - return db.get_profile_text(customer_id) - except Exception as e: - return f"查询失败: {e}" - - @agent.agent.tool - async def transfer_to_human(ctx: RunContext[Any]) -> str: - """ - 转接人工客服。 - 遇到退款/投诉/情绪激动/复杂售后时调用。 - """ - return "TRANSFER_REQUESTED" - - @agent.agent.tool - async def get_customer_risk_profile(ctx: RunContext[Any], customer_id: str = "") -> str: - """查询客户风控画像:退款/不付款/差评/人工黑名单等。""" - cid = customer_id or ctx.deps.from_id - try: - info = risk_db.evaluate_customer(cid) - return ( - f"客户:{cid}\n" - f"不接单:{'是' if info.get('do_not_serve') else '否'}\n" - f"风险等级:{info.get('computed_level','low')} 分数:{info.get('computed_score',0)}\n" - f"近30天退款:{info.get('refund_30d',0)}\n" - f"近7天未付款下单:{info.get('unpaid_7d',0)}\n" - f"近90天差评:{info.get('bad_review_90d',0)}\n" - f"备注:{info.get('note','') or '无'}" - ) - except Exception as e: - return f"查询风控画像失败: {e}" - - @agent.agent.tool - async def mark_customer_risk( - ctx: RunContext[Any], - customer_id: str, - do_not_serve: bool = False, - risk_level: str = "low", - risk_score: int = 0, - note: str = "", - tag: str = "", - ) -> str: - """人工标记客户风控画像(不接单/高风险/备注标签)。""" - try: - tags = [tag] if tag else [] - risk_db.set_profile( - customer_id=customer_id, - do_not_serve=do_not_serve, - risk_level=risk_level, - risk_score=risk_score, - note=note, - tags=tags, - ) - return "风控画像已更新" - except Exception as e: - return f"更新风控画像失败: {e}" - - @agent.agent.tool - async def record_customer_risk_event( - ctx: RunContext[Any], - customer_id: str, - event_type: str, - event_count: int = 1, - note: str = "", - ) -> str: - """记录风控事件:refund/unpaid_order/bad_review/blacklist_hit 等。""" - try: - risk_db.record_event( - customer_id=customer_id, - event_type=event_type, - event_count=event_count, - note=note, - ) - return "风控事件已记录" - except Exception as e: - return f"记录风控事件失败: {e}" - - @agent.agent.tool - async def save_customer_note( - ctx: RunContext[Any], - customer_id: str, - note: str - ) -> str: - """ - 记录客户关键信息到画像(邮箱/微信/特殊需求等)。 - 客户提供联系方式或重要信息时调用。 - """ - try: - from db.customer_db import db - db.add_note(customer_id, note) - return "已记录" - except Exception as e: - return f"记录失败: {e}" - - @agent.agent.tool - async def update_contact_info( - ctx: RunContext[Any], - customer_id: str, - contact_type: str, - value: str - ) -> str: - """ - 更新客户联系方式。 - 当客户说出邮箱/手机/微信时调用,比正则提取更准确。 - - contact_type 枚举值: - email - 邮箱 - phone - 手机号 - wechat - 微信号 - """ - try: - from db.customer_db import db - if contact_type == "email": - db.update_email(customer_id, value) - elif contact_type == "phone": - db.update_phone(customer_id, value) - elif contact_type == "wechat": - db.update_wechat(customer_id, value) - else: - return f"未知联系方式类型: {contact_type}" - return f"已保存 {contact_type}: {value}" - except Exception as e: - return f"保存失败: {e}" - - @agent.agent.tool - async def record_quote( - ctx: RunContext[Any], - customer_id: str, - price: int, - description: str = "" - ) -> str: - """ - 记录本次报价到客户画像,用于后续对话保持价格一致。 - 每次给客户报价后调用。 - - Args: - customer_id: 客户ID - price: 报价金额(元) - description: 报价描述,如"单图处理"/"三图打包" - """ - try: - from db.customer_db import db - db.update_last_price(customer_id, price) - if description: - db.add_note(customer_id, f"报价 {price}元({description})") - # 同步到内存状态 - state = agent.conversations.get(customer_id) - if state: - state.last_price = price - return f"已记录报价 {price}元" - except Exception as e: - return f"记录失败: {e}" - - @agent.agent.tool - async def process_image_gemini(ctx: RunContext[Any], customer_id: str = "") -> str: - """ - 触发 Gemini 作图处理。客户付款后或说「安排一下」「处理一下」时调用。 - 会从客户档案读取上次发图的 URL 和处理参数(提示词、比例、透视),启动 Gemini 流程。 - 处理完成后会自动发图给客户。 - """ - try: - from config.config import IMAGE_MODULE_ENABLED - if not IMAGE_MODULE_ENABLED: - return "现在处理模块暂时暂停,先不自动作图" - except Exception: - return "现在处理模块暂时暂停,先不自动作图" - cid = customer_id or ctx.deps.from_id - try: - from core.workflow import workflow - ok = await workflow.trigger_processing_on_payment( - customer_id=cid, - acc_id=ctx.deps.acc_id, - acc_type=ctx.deps.platform, - ) - if ok: - return "已安排,稍后发你" - return "该客户暂无待处理图片,请先发图" - except Exception as e: - return f"触发作图失败: {e},请稍后重试或转人工" - - @agent.agent_pricing.tool - async def analyze_image_pricing(ctx: RunContext[Any], image_url: str) -> str: - try: - from image.image_analyzer import image_analyzer - result = await image_analyzer.analyze(image_url) - if result.get("feasibility") == "no" or result.get("risk") == "high": - return "该图风险高或不可做:不报价,建议换图或转人工评估。" - if not result.get("success", False): - return "图片识别异常:先不报价,建议客户重发更清晰图片。" - p = result.get("price_suggest", 20) - try: - st = agent._get_conversation_state(ctx.deps.from_id) - if isinstance(result.get("price_min"), (int, float)): - st.last_min_price = int(result.get("price_min") or 0) - try: - from db.customer_db import db as _db - _db.update_last_min_price(ctx.deps.from_id, st.last_min_price) - except Exception: - pass - except Exception: - pass - return f"建议报价:{p}元" - except Exception as e: - return f"图片分析失败: {e}" - - @agent.agent_pricing.tool - async def record_quote_pricing( - ctx: RunContext[Any], - customer_id: str, - price: int, - description: str = "" - ) -> str: - try: - from db.customer_db import db - db.update_last_price(customer_id, price) - return "ok" - except Exception as e: - return f"记录失败: {e}" - - @agent.agent_processing.tool - async def process_image_gemini_run(ctx: RunContext[Any], customer_id: str = "") -> str: - """触发 Gemini 作图处理(processing agent 专用入口)。""" - return await process_image_gemini(ctx, customer_id) - - @agent.agent_similar.tool - async def recommend_similar(ctx: RunContext[Any], hint: str = "") -> str: - try: - return "有类似款,拍下我发你参考图。" - except Exception as e: - return f"推荐失败: {e}" - - @agent.agent_order.tool - async def handle_order(ctx: RunContext[Any], raw_msg: str = "") -> str: - try: - info = parse_order_info(raw_msg or "") - paid_kw = ["等待发货", "已付款", "付款成功", "买家已付款"] - if any(k in (info.get("pay_status", "") or "") for k in paid_kw) or any(k in (info.get("order_status", "") or "") for k in paid_kw): - return "已安排,稍后发你" - return "" - except Exception: - return "" - - @agent.agent_risk.tool - async def risk_filter(ctx: RunContext[Any], text: str = "") -> str: - return "这类不做哈,政治/敏感内容都不接。" - - @agent.agent_risk.tool - async def get_customer_risk_profile_risk(ctx: RunContext[Any], customer_id: str = "") -> str: - return await get_customer_risk_profile(ctx, customer_id) - - @agent.agent_risk.tool - async def mark_customer_risk_risk( - ctx: RunContext[Any], - customer_id: str, - do_not_serve: bool = False, - risk_level: str = "low", - risk_score: int = 0, - note: str = "", - tag: str = "", - ) -> str: - return await mark_customer_risk( - ctx=ctx, - customer_id=customer_id, - do_not_serve=do_not_serve, - risk_level=risk_level, - risk_score=risk_score, - note=note, - tag=tag, - ) - - @agent.agent_risk.tool - async def record_customer_risk_event_risk( - ctx: RunContext[Any], - customer_id: str, - event_type: str, - event_count: int = 1, - note: str = "", - ) -> str: - return await record_customer_risk_event( - ctx=ctx, - customer_id=customer_id, - event_type=event_type, - event_count=event_count, - note=note, - ) - - @agent.agent.tool - async def remove_background(ctx: RunContext[Any], image_url: str) -> str: - try: - from config.config import IMAGE_MODULE_ENABLED - if not IMAGE_MODULE_ENABLED: - return "现在处理模块暂时暂停,先不处理图片" - except Exception: - return "现在处理模块暂时暂停,先不处理图片" - """【独立工具】去背景,输出白底图。客户只要去背景时调用。""" - try: - from image.image_tools import remove_background as _rb - r = await _rb(image_url) - if r["success"]: - return f"去背景完成,已保存。自然回复客户好了发你" - return f"去背景失败:{r['message']}" - except Exception as e: - return f"去背景失败:{e}" - - @agent.agent.tool - async def perspective_correct(ctx: RunContext[Any], image_url: str) -> str: - try: - from config.config import IMAGE_MODULE_ENABLED - if not IMAGE_MODULE_ENABLED: - return "现在处理模块暂时暂停,先不处理图片" - except Exception: - return "现在处理模块暂时暂停,先不处理图片" - """【独立工具】透视矫正。输入需白底图,输出展平图。""" - try: - from image.image_tools import perspective_correct as _pc - r = await _pc(image_url) - if r["success"]: - return f"透视矫正完成。自然回复客户好了" - return f"透视矫正失败:{r['message']}" - except Exception as e: - return f"透视矫正失败:{e}" - - @agent.agent.tool - async def extract_pattern_tool( - ctx: RunContext[Any], - image_url: str, - prompt: str = "", - aspect_ratio: str = "1:1" - ) -> str: - try: - from config.config import IMAGE_MODULE_ENABLED - if not IMAGE_MODULE_ENABLED: - return "现在处理模块暂时暂停,先不处理图片" - except Exception: - return "现在处理模块暂时暂停,先不处理图片" - """【独立工具】印花提取/主处理。按提示词和比例处理。""" - try: - from image.image_tools import extract_pattern - r = await extract_pattern(image_url, prompt=prompt, aspect_ratio=aspect_ratio) - if r["success"]: - return f"提取完成。自然回复客户好了发你" - return f"提取失败:{r['message']}" - except Exception as e: - return f"提取失败:{e}" - - @agent.agent.tool - async def enhance_image_tool(ctx: RunContext[Any], image_url: str) -> str: - try: - from config.config import IMAGE_MODULE_ENABLED - if not IMAGE_MODULE_ENABLED: - return "现在处理模块暂时暂停,先不处理图片" - except Exception: - return "现在处理模块暂时暂停,先不处理图片" - """【独立工具】高清增强。客户只要清晰化时调用。""" - try: - from image.image_tools import enhance_image - r = await enhance_image(image_url) - if r["success"]: - return f"高清增强完成。自然回复客户好了" - return f"增强失败:{r['message']}" - except Exception as e: - return f"增强失败:{e}" - - @agent.agent.tool - async def color_match_tool( - ctx: RunContext[Any], - orig_url: str, - result_url: str, - strength: float = 0.75 - ) -> str: - try: - from config.config import IMAGE_MODULE_ENABLED - if not IMAGE_MODULE_ENABLED: - return "现在处理模块暂时暂停,先不处理图片" - except Exception: - return "现在处理模块暂时暂停,先不处理图片" - """【独立工具】颜色匹配。将 result 色调匹配到 orig。""" - try: - from image.image_tools import color_match_images - r = await color_match_images(orig_url, result_url, strength=strength) - if r["success"]: - return f"颜色匹配完成" - return f"颜色匹配失败:{r['message']}" - except Exception as e: - return f"颜色匹配失败:{e}" - - @agent.agent.tool - async def trim_border_tool(ctx: RunContext[Any], image_url: str) -> str: - try: - from config.config import IMAGE_MODULE_ENABLED - if not IMAGE_MODULE_ENABLED: - return "现在处理模块暂时暂停,先不处理图片" - except Exception: - return "现在处理模块暂时暂停,先不处理图片" - """【独立工具】裁切四周背景边(白/黄/米等)。""" - try: - from image.image_tools import trim_border - r = await trim_border(image_url) - if r["success"]: - return f"裁边完成" - return f"裁边失败:{r['message']}" - except Exception as e: - return f"裁边失败:{e}" - - @agent.agent.tool - async def vectorize_to_eps_tool(ctx: RunContext[Any], image_url: str) -> str: - try: - from config.config import IMAGE_MODULE_ENABLED - if not IMAGE_MODULE_ENABLED: - return "现在处理模块暂时暂停,先不处理图片" - except Exception: - return "现在处理模块暂时暂停,先不处理图片" - """【独立工具】矢量化 - 将图片转为 EPS 矢量文件。客户要做矢量图、转 EPS、转 AI 格式时调用。""" - try: - from image.image_tools import vectorize_to_eps - r = await vectorize_to_eps(image_url) - if r["success"]: - return f"矢量化完成,已生成 EPS 文件。自然回复客户好了发你" - return f"矢量化失败:{r['message']}" - except Exception as e: - return f"矢量化失败:{e}" - - @agent.agent.tool - async def meitu_enhance_tool( - ctx: RunContext[Any], - image_url: str, - mode: str = "standard" - ) -> str: - try: - from config.config import IMAGE_MODULE_ENABLED - if not IMAGE_MODULE_ENABLED: - return "现在处理模块暂时暂停,先不处理图片" - except Exception: - return "现在处理模块暂时暂停,先不处理图片" - """ - 【独立工具】美图画质增强。客户要画质增强、清晰化、美图处理时调用。 - - Args: - image_url: 图片 URL 或本地路径 - mode: 处理模式。crystal(极速重绘) standard(标准) enhance(增强) hdr(HDR) portrait(人像优化) - """ - try: - from image.image_tools import meitu_enhance - r = await meitu_enhance(image_url, mode=mode) - if r["success"]: - return f"画质增强完成。自然回复客户好了发你" - return f"画质增强失败:{r['message']}" - except Exception as e: - return f"画质增强失败:{e}" - - @agent.agent.tool - async def resize_image( - ctx: RunContext[Any], - image_url: str, - width: int, - height: int = 0 - ) -> str: - try: - from config.config import IMAGE_MODULE_ENABLED - if not IMAGE_MODULE_ENABLED: - return "现在处理模块暂时暂停,先不处理图片" - except Exception: - return "现在处理模块暂时暂停,先不处理图片" - """ - 改图片尺寸。客户说「改成1920x1080」「弄成横图」「改下尺寸」时调用。 - - Args: - image_url: 图片URL(客户刚发的图,或从对话中获取) - width: 目标宽度(像素),如 1920 - height: 目标高度(0=按宽度等比缩放),如 1080 - - 常用尺寸:1920x1080(横屏) 1080x1920(竖屏) 2000x2000(方图) - """ - try: - from image.image_processor import image_processor - result = await image_processor.resize(image_url, width, height) - if result["success"]: - return f"改尺寸完成:{width}x{height},已保存。自然回复客户改好了" - else: - return f"改尺寸失败:{result['message']},告知客户稍后重试" - except Exception as e: - return f"改尺寸失败:{e}" - - @agent.agent.tool - async def calculate_bulk_price( - ctx: RunContext[Any], - image_count: int, - complexities: str = "" - ) -> str: - """ - 计算多图打包价格。 - 客户要做多张图时调用,返回建议总价。 - - Args: - image_count: 图片数量 - complexities: 各图复杂度,逗号分隔,如 "normal,complex,simple" - 没有识别结果时留空,按平均价格估算 - """ - if image_count <= 0: - return "图片数量无效" - - # 各复杂度单价(必须为5的整数倍) - unit_price = {"simple": 15, "normal": 20, "complex": 25, "hard": 30} - default_unit = 20 # 没有识别结果时的默认单价 - - if complexities: - levels = [c.strip() for c in complexities.split(",")] - total = sum(unit_price.get(lv, default_unit) for lv in levels) - else: - total = image_count * default_unit - - # 打包优惠:3张以上9折,5张以上8折,价格必须为5的整数倍 - if image_count >= 5: - discounted = round(total * 0.8 / 5) * 5 - tip = f"({image_count}张8折优惠)" - elif image_count >= 3: - discounted = round(total * 0.9 / 5) * 5 - tip = f"({image_count}张9折优惠)" - else: - discounted = round(total / 5) * 5 - tip = "" - - return f"建议打包报价:{discounted}元{tip}(原价{total}元)" +def register_agent_tools(agent: Any): + """注册工具""" + agent.tool(transfer_to_human_tool) + agent.tool(check_order_status_tool) + logger.info("[Agent] 工具箱已更新:称呼统一为“设计师”。") diff --git a/core/engine.py b/core/engine.py new file mode 100644 index 0000000..191bc62 --- /dev/null +++ b/core/engine.py @@ -0,0 +1,63 @@ +import logging +from typing import Optional, Any +from core.schema import StandardMessage, StandardResponse +from core.events.event_bus import bus + +logger = logging.getLogger("cs_agent") + +class BusinessEngine: + """ + 业务逻辑中枢: + 1. 接收 StandardMessage。 + 2. 决定由哪个 AI 工具或流程处理。 + 3. 返回 StandardResponse。 + 4. 对外广播异步事件。 + """ + def __init__(self, agent_instance: Any = None): + """ + :param agent_instance: 核心 AI Agent 的实例(比如重构后的 CustomerServiceAgent) + """ + self.agent = agent_instance + + async def handle_message(self, msg: StandardMessage) -> StandardResponse: + """ + 大脑的思考主入口 + """ + logger.info(f"[Engine] 收到来自 {msg.platform} 的消息: {msg.user_id} -> {msg.content[:50]}") + + # TODO: 这里将接入重构后的 Single Agent + Tool Calling + # 目前模拟一个简单的规则响应,展示 StandardResponse 的用法 + + if "报价" in msg.content or msg.image_urls: + return StandardResponse( + reply_content="正在为你查看图片,请稍等...", + metadata={"acc_id": msg.acc_id, "acc_type": msg.acc_type} + ) + + if "转人工" in msg.content: + return StandardResponse( + reply_content="正在为你转接设计师...", + need_transfer=True, + metadata={"acc_id": msg.acc_id, "acc_type": msg.acc_type} + ) + + # 兜底回复 + return StandardResponse( + reply_content="你好,我是AI助手,有什么可以帮你的?", + metadata={"acc_id": msg.acc_id, "acc_type": msg.acc_type} + ) + + async def emit_image_result(self, user_id: str, platform: str, url: str, acc_id: str): + """ + 这是一个业务触发器示例:当图片处理完成时,由 Engine 主动发广播。 + """ + await bus.emit( + "MESSAGE_OUTBOUND", + user_id=user_id, + platform=platform, + response=StandardResponse( + reply_content=url, + msg_type=1, # 图片 + metadata={"acc_id": acc_id} + ) + ) diff --git a/core/events/event_bus.py b/core/events/event_bus.py new file mode 100644 index 0000000..cf8063e --- /dev/null +++ b/core/events/event_bus.py @@ -0,0 +1,36 @@ +import asyncio +import logging +from typing import Callable, Dict, List, Any, Awaitable + +logger = logging.getLogger("cs_agent") + +class AsyncEventBus: + """ + 异步事件总线:解耦业务触发与平台发送。 + 支持一个事件被多个订阅者监听。 + """ + def __init__(self): + self._listeners: Dict[str, List[Callable[..., Awaitable[None]]]] = {} + + def subscribe(self, event_type: str, callback: Callable[..., Awaitable[None]]): + """订阅事件""" + if event_type not in self._listeners: + self._listeners[event_type] = [] + self._listeners[event_type].append(callback) + logger.info(f"[EventBus] 新订阅者已注册到事件: {event_type}") + + async def emit(self, event_type: str, **kwargs): + """发布事件:异步广播给所有订阅者""" + if event_type not in self._listeners: + return + + tasks = [] + for callback in self._listeners[event_type]: + tasks.append(asyncio.create_task(callback(**kwargs))) + + if tasks: + await asyncio.gather(*tasks, return_exceptions=True) + logger.info(f"[EventBus] 事件 {event_type} 已成功广播给 {len(tasks)} 个订阅者") + +# 全局单例,所有模块共用这一个广播台 +bus = AsyncEventBus() diff --git a/core/orchestrator.py b/core/orchestrator.py new file mode 100644 index 0000000..421869f --- /dev/null +++ b/core/orchestrator.py @@ -0,0 +1,156 @@ +import logging +import asyncio +import re +import time +from typing import Optional, List, Any, Dict +from collections import deque +from core.schema import StandardMessage, StandardResponse +from core.adapters.qianniu_adapter import QianniuAdapter +from core.pydantic_ai_agent_v2 import CustomerServiceBrain +from core.events.event_bus import bus +from core.repository import repo + +logger = logging.getLogger("cs_agent") + +class SystemOrchestrator: + """ + 全系统总编排:具备转接冷却、防抖合并、多消息去重、以及精准日志。 + """ + def __init__(self, ws_client=None): + self.ws_client = ws_client + self.qianniu_adapter = QianniuAdapter(ws_client) + self.brain = CustomerServiceBrain() + + # 1. 消息 ID 去重 + self._processed_msg_ids = deque(maxlen=200) + + # 2. 转接冷却存储 (customer_id -> last_transfer_time) + self._last_transfer_time: Dict[str, float] = {} + + # 3. 防抖配置 + self._debounce_seconds = 5.0 + self._debounce_tasks: Dict[str, asyncio.Task] = {} + self._pending_messages: Dict[str, List[StandardMessage]] = {} + self._user_locks: Dict[str, asyncio.Lock] = {} + + bus.subscribe("MESSAGE_OUTBOUND", self.handle_outbound_event) + + def _get_user_lock(self, user_id: str) -> asyncio.Lock: + if user_id not in self._user_locks: + self._user_locks[user_id] = asyncio.Lock() + return self._user_locks[user_id] + + async def on_raw_message_received(self, platform: str, raw_data: dict): + """链路入口""" + try: + if platform != "qianniu": return + + std_msg, direction = await self.qianniu_adapter.translate_inbound(raw_data) + + # 过滤心跳 + if not std_msg.content.strip() and not std_msg.image_urls: return + + # 如果是商家人工回复,静默入库 + if direction == "out": + await repo.save_chat(platform, std_msg.user_id, std_msg.content, "out", acc_id=std_msg.acc_id) + return + + # 订单消息处理:静默记录 + if "[系统订单信息]" in std_msg.content: + await self._handle_order_packet(platform, std_msg) + await repo.save_chat(platform, std_msg.user_id, std_msg.content, "in", acc_id=std_msg.acc_id) + return + + # ID 去重 + if std_msg.msg_id: + if std_msg.msg_id in self._processed_msg_ids: return + self._processed_msg_ids.append(std_msg.msg_id) + + # 进入防抖 + user_id = std_msg.user_id + if user_id in self._debounce_tasks: self._debounce_tasks[user_id].cancel() + if user_id not in self._pending_messages: self._pending_messages[user_id] = [] + self._pending_messages[user_id].append(std_msg) + + self._debounce_tasks[user_id] = asyncio.create_task(self._debounced_process(user_id, platform)) + + except Exception as e: + logger.error(f"[Orchestrator] 处理失败: {e}") + + async def _handle_order_packet(self, platform: str, msg: StandardMessage): + try: + price_match = re.search(r"订单金额:金额:\s*([\d\.]+)元", msg.content) + if price_match: await repo.update_task_price(platform, msg.user_id, float(price_match.group(1))) + if "买家已付款" in msg.content: await repo.update_task_outcome(platform, msg.user_id, "deal_success") + elif any(k in msg.content for k in ["退款", "已关闭", "已取消"]): await repo.update_task_outcome(platform, msg.user_id, "refunded") + except Exception: pass + + async def _debounced_process(self, user_id: str, platform: str): + try: + await asyncio.sleep(self._debounce_seconds) + async with self._get_user_lock(user_id): + messages = self._pending_messages.pop(user_id, []) + if not messages: return + + # A. 合并与元数据修复 + combined_content = "\n".join([m.content for m in messages if m.content.strip()]) + all_image_urls = [] + acc_id = messages[-1].acc_id + acc_type = messages[-1].acc_type + for m in messages: + for url in m.image_urls: + if url not in all_image_urls: all_image_urls.append(url) + + # 防抖合并后的消息仍需有 msg_id,避免触发 StandardMessage 校验失败 + merged_msg_id = messages[-1].msg_id if messages[-1].msg_id else f"merged-{user_id}-{int(time.time() * 1000)}" + final_msg = StandardMessage( + platform=platform, + msg_id=merged_msg_id, + user_id=user_id, + content=combined_content, + image_urls=all_image_urls, + acc_id=acc_id, + acc_type=acc_type + ) + + # B. 持久化 + db_content = combined_content + if all_image_urls: db_content = f"【系统:已收到{len(all_image_urls)}张图】\n{combined_content}" + await repo.save_chat(platform, user_id, db_content, "in", acc_id=acc_id) + + # C. 冷却检查:如果 60秒内发过转接,告诉大脑“已处于转接中” + is_in_cooldown = (time.time() - self._last_transfer_time.get(user_id, 0)) < 60 + + # D. 思考 + history = await repo.get_chat_history(user_id, limit=10) + if history and history[-1]['content'] == db_content: history = history[:-1] + + # 如果在冷却中,在当前消息里注入“当前已在转接中”的信息 + if is_in_cooldown: + final_msg.content = f"【系统:当前已向设计师发出转接请求,请勿再次调用转接工具】\n{final_msg.content}" + + std_res = await self.brain.think_and_reply(final_msg, history=history) + + # E. 发送并记录时间 + if std_res.should_reply: + # 关键修复:补全发送时的元数据,解决日志 customer_id 为空的问题 + std_res.metadata = {"acc_id": acc_id, "acc_type": acc_type} + await self.qianniu_adapter.translate_outbound(std_res, user_id) + await repo.save_chat(platform, user_id, std_res.reply_content, "out", acc_id=acc_id) + + if "[转移会话]" in std_res.reply_content: + self._last_transfer_time[user_id] = time.time() + + except asyncio.CancelledError: pass + except Exception as e: logger.exception(f"[Orchestrator] 处理失败: {e}") + + async def handle_outbound_event(self, user_id: str, platform: str, response: StandardResponse): + if platform == "qianniu": + await self.qianniu_adapter.translate_outbound(response, user_id) + +# 全局单例 +orchestrator: Optional[SystemOrchestrator] = None +def init_orchestrator(ws_client): + global orchestrator + orchestrator = SystemOrchestrator(ws_client) + return orchestrator diff --git a/core/pydantic_ai_agent_v2.py b/core/pydantic_ai_agent_v2.py new file mode 100644 index 0000000..aa1394c --- /dev/null +++ b/core/pydantic_ai_agent_v2.py @@ -0,0 +1,91 @@ +import os +import logging +from typing import List, Optional, Any, Dict +from pydantic_ai import Agent, RunContext +from pydantic_ai.models.openai import OpenAIChatModel +from pydantic_ai.providers.openai import OpenAIProvider +from core.schema import StandardMessage, StandardResponse +from core.agent_tools import register_agent_tools + +logger = logging.getLogger("cs_agent") + +from core.skill_manager import skill_manager + +class CustomerServiceBrain: + """ + 重构后的单一 Agent 大脑: + 【全能终极版】统一称呼为“设计师”,支持下线安抚。 + """ + + def __init__(self, model_name: str = None): + self.api_key = os.getenv("OPENAI_API_KEY") + self.base_url = os.getenv("OPENAI_BASE_URL") + self.model_name = model_name or os.getenv("OPENAI_MODEL", "gpt-4o-mini") + + model = OpenAIChatModel( + model_name=self.model_name, + provider=OpenAIProvider(api_key=self.api_key, base_url=self.base_url) + ) + + all_skills = skill_manager.get_all_skills_text() + + # --- 统一口径后的 System Prompt --- + system_prompt = ( + "你是一位专注【高清修复】和【找原图】的专业店主。性格干脆,说话高端、专业。\n\n" + + "【统一称呼规范】\n" + "1. 严禁使用'师傅'、'客服'、'专员'等词汇!\n" + "2. 必须统一称呼为【设计师】。比如:'找设计师看下'、'设计师马上来'、'等设计师核价'。\n\n" + + "【核心逻辑】\n" + "1. 业务:只聊高清修复和找原图。引导发图 -> 问需求 -> 找设计师。\n" + "2. 下线安抚:如果工具返回 'ERROR_NO_DESIGNER_ONLINE',说明设计师们【下班/下线】了。回:'亲亲,设计师现在下班啦,需求我先记下,明天第一时间回您哈!'。\n" + "3. 正在转接中:如果看到系统提示已在转接,回:'设计师正在赶来,我再帮你催下哈!'。\n" + "4. 没转接时:引导发图 -> 问需求 -> 调工具转人工。\n\n" + "5. 语气:淘宝亲切风,多用'亲亲'、'铁子'。每句回复【严禁超过15字】!\n\n" + + "【必杀令】\n" + "1. 每句回复严禁超过15个字!\n" + "2. 严禁报价,严禁复读图片已收到的情况。\n" + "3. 必须原样输出工具返回的'正在为您转接|'指令。\n\n" + + f"业务参考:\n{all_skills}" + ) + + self.agent = Agent(model=model, system_prompt=system_prompt) + register_agent_tools(self.agent) + + async def think_and_reply(self, msg: StandardMessage, history: List[dict] = []) -> StandardResponse: + try: + # 构造增强上下文(强灌输) + user_content = msg.content + if msg.image_urls: + user_content = f"【系统通知:收到客户 {len(msg.image_urls)} 张图】\n{user_content}" + + recent_context = "" + if history: + lines = [f"{('客户' if h['role']=='user' else '我')}:{h['content']}" for h in history[-6:]] + recent_context = "【近期对话回顾】\n" + "\n".join(lines) + "\n----------------\n" + + full_input = f"{recent_context}现在的对话:{user_content}" + + result = await self.agent.run(full_input, message_history=history) + + if hasattr(result, 'data') and isinstance(result.data, str): + reply_text = result.data + elif hasattr(result, 'output') and isinstance(result.output, str): + reply_text = result.output + else: + reply_text = str(result.data) if hasattr(result, 'data') else "在呢铁子。" + + need_transfer = "[转移会话]" in reply_text + + return StandardResponse( + reply_content=reply_text, + need_transfer=need_transfer, + metadata={"acc_id": msg.acc_id, "acc_type": msg.acc_type} + ) + + except Exception as e: + logger.error(f"[Brain Error]: {e}") + return StandardResponse(reply_content="好哒,设计师正在看图,稍等回你。", metadata={"acc_id": msg.acc_id}) diff --git a/core/repository.py b/core/repository.py new file mode 100644 index 0000000..0a86175 --- /dev/null +++ b/core/repository.py @@ -0,0 +1,69 @@ +import logging +import asyncio +from typing import Optional, List, Any +from datetime import datetime +from db.customer_db import db as customer_db +from db.image_tasks_db import db as task_db +from db.chat_log_db import log_message, get_conversation + +logger = logging.getLogger("cs_agent") + +class DataRepository: + """ + 异步数据仓库:使用 asyncio.to_thread 屏蔽底层同步 IO 阻塞。 + """ + def __init__(self): + self.customer_db = customer_db + self.task_db = task_db + + # --- 聊天记录 (异步化) --- + + async def save_chat(self, platform: str, user_id: str, content: str, direction: str, acc_id: str = ""): + """异步持久化存储聊天记录""" + return await asyncio.to_thread( + log_message, + customer_id=user_id, + message=content, + direction=direction, + platform=platform, + acc_id=acc_id + ) + + async def get_chat_history(self, user_id: str, limit: int = 10) -> List[dict]: + """异步获取历史记录""" + rows = await asyncio.to_thread(get_conversation, user_id, limit=limit) + history = [] + for r in rows: + role = "user" if r["direction"] == "in" else "assistant" + history.append({"role": role, "content": r["message"]}) + return history + + # --- 客户相关 (异步化) --- + + async def get_customer(self, platform: str, user_id: str): + customer_key = f"{platform}:{user_id}" + return await asyncio.to_thread(self.customer_db.get_customer, customer_key) + + # --- 任务相关 (异步化) --- + + async def create_task(self, platform: str, user_id: str, image_url: str, operation: str, requirements: str = ""): + return await asyncio.to_thread( + self.task_db.add_task, + customer_id=user_id, + platform=platform, + original_image=image_url, + operation=operation, + requirements=requirements, + status="pending" + ) + + async def update_task_price(self, platform: str, user_id: str, price: float): + """异步记录成交价""" + return await asyncio.to_thread(self.task_db.update_price, user_id, platform, price) + + async def update_task_outcome(self, platform: str, user_id: str, outcome: str): + """异步记录最终结局""" + return await asyncio.to_thread(self.task_db.update_outcome, user_id, platform, outcome) + +# 全局异步仓库单例 +repo = DataRepository() diff --git a/core/schema.py b/core/schema.py new file mode 100644 index 0000000..a912734 --- /dev/null +++ b/core/schema.py @@ -0,0 +1,29 @@ +from pydantic import BaseModel, Field +from typing import List, Optional, Any +from datetime import datetime + +class StandardMessage(BaseModel): + """全平台通用的输入消息协议""" + platform: str = "qianniu" # 来源平台:qianniu, wechat, feishu, console + msg_id: str # 消息唯一ID + user_id: str # 发送者唯一ID + user_name: str = "" # 发送者昵称 + content: str # 消息文本内容 + image_urls: List[str] = [] # 提取出来的图片链接 + acc_id: str = "" # 商家/店铺账号ID + acc_type: str = "" # 平台类型标识 + timestamp: datetime = Field(default_factory=datetime.now) + raw_data: Any = None # 原始消息体(仅供调试或特殊逻辑备查) + + # 扩展字段:针对电商场景 + goods_name: Optional[str] = None + goods_order: Optional[str] = None + +class StandardResponse(BaseModel): + """大脑给出的通用回复协议""" + reply_content: str # 回复文本或图片URL + msg_type: int = 0 # 0: 文本, 1: 图片, 2: 撤回, 9: 转人工 + should_reply: bool = True # 是否需要发送 + need_transfer: bool = False # 是否触发转人工 + transfer_group: str = "" # 转人工的分组ID + metadata: dict = {} # 额外元数据(如埋点、调试信息) diff --git a/core/skill_manager.py b/core/skill_manager.py new file mode 100644 index 0000000..a929052 --- /dev/null +++ b/core/skill_manager.py @@ -0,0 +1,56 @@ +import os +import glob +import logging +from pathlib import Path +from typing import Dict, List, Optional + +logger = logging.getLogger("cs_agent") + +class SkillManager: + """ + 技能包管理器: + 1. 自动扫描 skills/ 目录下的 SKILL.md 文件。 + 2. 提供按需加载和组合技能的能力。 + 3. 支持热加载(无需重启即可更新 AI 知识)。 + """ + def __init__(self, skills_dir: str = "skills"): + self.skills_dir = Path(skills_dir) + self._skill_cache: Dict[str, str] = {} + self.reload_skills() + + def reload_skills(self): + """扫描并加载所有技能文件""" + new_cache = {} + skill_files = glob.glob(str(self.skills_dir / "**/SKILL.md"), recursive=True) + + for file_path in skill_files: + try: + path = Path(file_path) + skill_name = path.parent.name.lower() + content = path.read_text(encoding="utf-8") + new_cache[skill_name] = content + except Exception as e: + logger.error(f"[SkillManager] 加载技能失败 {file_path}: {e}") + + self._skill_cache = new_cache + logger.info(f"[SkillManager] 成功加载 {len(self._skill_cache)} 个技能包: {list(self._skill_cache.keys())}") + + def get_skill(self, name: str) -> str: + """获取单个技能内容""" + return self._skill_cache.get(name.lower(), "") + + def compose_skills(self, names: List[str]) -> str: + """组合多个技能内容,用于注入 System Prompt""" + parts = [] + for name in names: + content = self.get_skill(name) + if content: + parts.append(f"### 技能:{name}\n{content}") + return "\n\n".join(parts) + + def get_all_skills_text(self) -> str: + """获取所有技能的合集(用于全能大脑模式)""" + return self.compose_skills(list(self._skill_cache.keys())) + +# 全局单例 +skill_manager = SkillManager() diff --git a/core/websocket_client_v2.py b/core/websocket_client_v2.py new file mode 100644 index 0000000..78c0992 --- /dev/null +++ b/core/websocket_client_v2.py @@ -0,0 +1,81 @@ +import asyncio +import json +import logging +import os +from datetime import datetime +from core.orchestrator import init_orchestrator +from core.websocket_connection_flow import connect_flow, receive_messages_flow +from core.websocket_send_flow import send_message_flow +from utils.observability import emit_activity + +logger = logging.getLogger("cs_agent") + +class QingjianAPIClient: + """ + 重构后的轻简API客户端 (协议全复刻版) + """ + + def __init__(self, uri=None, enable_agent: bool = True): + from config.config import QINGJIAN_WS_URI + self.uri = uri or QINGJIAN_WS_URI + self.websocket = None + self.running = True + self.logger = logger + self.enable_agent = enable_agent + + # 初始化新架构总指挥部 + self.orchestrator = init_orchestrator(ws_client=self) + logger.info("[WebSocket] 新架构 Orchestrator 已就绪。") + + def _activity_log(self, event: str, **kwargs): + emit_activity(logger, event=event, **kwargs) + + async def connect(self): + await connect_flow(self) + + async def receive_messages(self): + await receive_messages_flow(self) + + async def handle_message(self, message): + """收到消息处理""" + try: + data = json.loads(message) + await self.orchestrator.on_raw_message_received(platform="qianniu", raw_data=data) + except Exception as e: + logger.error(f"[WebSocket] 处理消息异常: {e}") + + async def send(self, customer_id: str, acc_id: str, acc_type: str, content: str, msg_type: int = 0): + """ + 【协议全复刻】严格按照 legacy/websocket_outbound_flow.py 的结构 + """ + # 注意:在这里 from_id 竟然填的是 customer_id,这是逆向接口的特殊要求 + msg_payload = { + "msg_id": "", + "acc_id": acc_id, + "msg": content, + "from_id": customer_id, + "from_name": "", + "cy_id": customer_id, + "acc_type": acc_type, + "msg_type": msg_type, + "cy_name": "", + } + await self.send_message(msg_payload) + + async def send_message(self, message_dict: dict): + """底层的 WebSocket 发送""" + await send_message_flow(self, message_dict) + + def get_time(self): + return datetime.now().strftime("%H:%M:%S") + + async def run(self): + await self.connect() + await self.receive_messages() + +if __name__ == "__main__": + client = QingjianAPIClient() + try: + asyncio.run(client.run()) + except KeyboardInterrupt: + logger.info("已停止") diff --git a/core/websocket_connection_flow.py b/core/websocket_connection_flow.py index e4de8b0..4934da3 100644 --- a/core/websocket_connection_flow.py +++ b/core/websocket_connection_flow.py @@ -1,6 +1,8 @@ import asyncio import websockets +import logging +logger = logging.getLogger("cs_agent") async def connect_flow(client): """连接 WebSocket 服务器并自动重连。""" @@ -9,49 +11,22 @@ async def connect_flow(client): client.logger.info(f"[{client.get_time()}] 正在连接轻简API {client.uri}...") async with websockets.connect(client.uri) as websocket: client.websocket = websocket - from utils.health_check import set_qingjian_connected - set_qingjian_connected(True) client.logger.info(f"[{client.get_time()}] 连接成功!") - if client.enable_agent: - client.logger.info(f"[{client.get_time()}] AI Agent 已启用,将自动处理消息") client.logger.info(f"[{client.get_time()}] 等待接收消息...") - await client.receive_messages() - except ConnectionRefusedError: - from utils.health_check import set_qingjian_connected - set_qingjian_connected(False) - client.logger.info(f"[{client.get_time()}] 连接被拒绝,请检查轻简软件是否已启动") - except websockets.exceptions.InvalidURI: - from utils.health_check import set_qingjian_connected - set_qingjian_connected(False) - client.logger.info(f"[{client.get_time()}] URI格式错误") except Exception as e: - from utils.health_check import set_qingjian_connected - set_qingjian_connected(False) - client.logger.info(f"[{client.get_time()}] 连接错误: {e}") + # 统一捕获异常,避免因为不同版本的 websockets 导致属性错误 + client.logger.info(f"[{client.get_time()}] 连接或运行错误: {e}") if client.running: client.logger.info(f"[{client.get_time()}] 5秒后尝试重连...") await asyncio.sleep(5) - async def receive_messages_flow(client): """持续接收消息。""" try: async for message in client.websocket: await client.handle_message(message) - except websockets.exceptions.ConnectionClosed: - from utils.health_check import set_qingjian_connected - set_qingjian_connected(False) - client.logger.info(f"[{client.get_time()}] 连接已关闭") except Exception as e: - from utils.health_check import set_qingjian_connected - set_qingjian_connected(False) - client.logger.info(f"[{client.get_time()}] 接收消息错误: {e}") - - -async def handle_message_flow(client, message, *, shop_type_resolver): - from core.websocket_inbound_flow import handle_incoming_message - - await handle_incoming_message(client, message, shop_type_resolver=shop_type_resolver) + client.logger.info(f"[{client.get_time()}] 接收消息中断: {e}") diff --git a/core/websocket_send_flow.py b/core/websocket_send_flow.py index 02ea704..df3bcbb 100644 --- a/core/websocket_send_flow.py +++ b/core/websocket_send_flow.py @@ -42,13 +42,14 @@ async def send_message_flow(client, message): await client.websocket.send(msg_json) pretty = json.dumps(message, ensure_ascii=False, indent=2) client.logger.info(f"[{client.get_time()}] 发送成功:\n{pretty}") + data = message.get("data", {}) if isinstance(message, dict) else {} client._activity_log( "send_message_success", - trace_id=message.get("_trace_id", ""), - acc_id=message.get("acc_id", ""), - customer_id=message.get("from_id", ""), - msg_type=message.get("msg_type", 0), - msg=message.get("msg", ""), + trace_id=message.get("_trace_id", "") if isinstance(message, dict) else "", + acc_id=data.get("acc_id", ""), + customer_id=data.get("cy_id", ""), + msg_type=data.get("msg_type", 0), + msg=data.get("msg", ""), ) except Exception as e: client.logger.info(f"[{client.get_time()}] 发送失败: {e}") diff --git a/core/提示词.MD b/core/提示词.MD new file mode 100644 index 0000000..9e659e7 --- /dev/null +++ b/core/提示词.MD @@ -0,0 +1,19 @@ +"你是一位专注【高清修复】和【找原图】的专业店主。性格干脆,说话高端、专业。\n\n" + + "【统一称呼规范】\n" + "1. 严禁使用'师傅'、'客服'、'专员'等词汇!\n" + "2. 必须统一称呼为【设计师】。比如:'找设计师看下'、'设计师马上来'、'等设计师核价'。\n\n" + + "【核心逻辑】\n" + "1. 业务:只聊高清修复和找原图。引导发图 -> 问需求 -> 找设计师。\n" + "2. 下线安抚:如果工具返回 'ERROR_NO_DESIGNER_ONLINE',说明设计师们【下班/下线】了。回:'亲亲,设计师现在下班啦,需求我先记下,明天第一时间回您哈!'。\n" + "3. 正在转接中:如果看到系统提示已在转接,回:'设计师正在赶来,我再帮你催下哈!'。\n\n" + "4. 没转接时:引导发图 -> 问需求 -> 调工具转人工。\n\n + "5. 语气:淘宝亲切风,多用'亲亲'、'铁子'。每句回复【严禁超过15字】!\n\n" + + "【必杀令】\n" + "1. 每句回复严禁超过15个字!\n" + "2. 严禁报价,严禁复读图片已收到的情况。\n" + "3. 必须原样输出工具返回的'正在为您转接|'指令。\n\n" + + f"业务参考:\n{all_skills}" diff --git a/customer_db/customers.json b/customer_db/customers.json index 6d587d7..9e26dfe 100755 --- a/customer_db/customers.json +++ b/customer_db/customers.json @@ -1,889 +1 @@ -{ - "new_customer_001": { - "customer_id": "new_customer_001", - "name": "新客户小王", - "nickname": "", - "email": "", - "phone": "", - "wechat": "", - "address": "", - "platform": "", - "platform_id": "", - "budget": "", - "budget_range_min": 0, - "budget_range_max": 0, - "requirements": [], - "preference_services": [], - "total_orders": 0, - "total_spent": 0, - "avg_order_value": 0.0, - "purchase_frequency": "", - "last_order_date": "", - "first_order_date": "", - "order_ids": [], - "pending_orders": 0, - "completed_orders": 0, - "refund_count": 0, - "personality": [], - "communication_prefer": "", - "response_speed": "", - "patience_level": "", - "customer_level": "C", - "vip": false, - "vip_level": 0, - "last_price": 20, - "last_price_time": "2026-02-28T15:04:15.181813", - "last_quote_no_convert": false, - "last_min_price": 0, - "last_image_url": "", - "last_image_time": "", - "last_gemini_prompt": "", - "last_aspect_ratio": "1:1", - "last_perspective": "no", - "processing_status": "", - "processing_image_url": "", - "expected_done_at": "", - "discount_given_count": 0, - "lowest_price_accepted": 0, - "preferred_format": "jpg", - "preferred_size": "", - "last_conversation_summary": "", - "last_conversation_time": "", - "total_images_sent": 0, - "complexity_history": [], - "image_type_history": [], - "price_sensitivity": "", - "decision_speed": "", - "revision_count": 0, - "revision_orders": 0, - "total_completed_orders": 0, - "bulk_potential": "", - "churn_risk": "低", - "upsell_opportunity": [], - "blacklist": false, - "blacklist_reason": "", - "vip_custom_price": 0, - "last_email_status": "", - "good_reviews": 0, - "bad_reviews": 0, - "dispute_count": 0, - "follow_up_by": "", - "follow_up_date": "", - "next_follow_date": "", - "source": "", - "coupon_used": "", - "notes": [], - "tags": [], - "created_at": "", - "last_contact": "2026-02-28T15:03:57.129715", - "last_update": "2026-02-28T15:04:15.184378" - }, - "fast_customer_002": { - "customer_id": "fast_customer_002", - "name": "爽快老客老李", - "nickname": "", - "email": "", - "phone": "", - "wechat": "", - "address": "", - "platform": "", - "platform_id": "", - "budget": "", - "budget_range_min": 0, - "budget_range_max": 0, - "requirements": [], - "preference_services": [], - "total_orders": 8, - "total_spent": 280, - "avg_order_value": 0.0, - "purchase_frequency": "", - "last_order_date": "", - "first_order_date": "", - "order_ids": [], - "pending_orders": 0, - "completed_orders": 0, - "refund_count": 0, - "personality": [ - "爽快" - ], - "communication_prefer": "", - "response_speed": "", - "patience_level": "", - "customer_level": "C", - "vip": false, - "vip_level": 0, - "last_price": 10, - "last_price_time": "2026-02-28T15:06:10.872962", - "last_quote_no_convert": false, - "last_min_price": 0, - "last_image_url": "", - "last_image_time": "", - "last_gemini_prompt": "", - "last_aspect_ratio": "1:1", - "last_perspective": "no", - "processing_status": "", - "processing_image_url": "", - "expected_done_at": "", - "discount_given_count": 2, - "lowest_price_accepted": 10, - "preferred_format": "jpg", - "preferred_size": "", - "last_conversation_summary": "", - "last_conversation_time": "", - "total_images_sent": 0, - "complexity_history": [], - "image_type_history": [], - "price_sensitivity": "中", - "decision_speed": "快", - "revision_count": 0, - "revision_orders": 0, - "total_completed_orders": 8, - "bulk_potential": "", - "churn_risk": "低", - "upsell_opportunity": [], - "blacklist": false, - "blacklist_reason": "", - "vip_custom_price": 0, - "last_email_status": "", - "good_reviews": 0, - "bad_reviews": 0, - "dispute_count": 0, - "follow_up_by": "", - "follow_up_date": "", - "next_follow_date": "", - "source": "", - "coupon_used": "", - "notes": [], - "tags": [], - "created_at": "", - "last_contact": "2026-02-28T15:03:57.131384", - "last_update": "2026-02-28T15:06:10.875534" - }, - "bargainer_003": { - "customer_id": "bargainer_003", - "name": "砍价王小张", - "nickname": "", - "email": "", - "phone": "", - "wechat": "", - "address": "", - "platform": "", - "platform_id": "", - "budget": "", - "budget_range_min": 0, - "budget_range_max": 0, - "requirements": [], - "preference_services": [], - "total_orders": 3, - "total_spent": 45, - "avg_order_value": 0.0, - "purchase_frequency": "", - "last_order_date": "", - "first_order_date": "", - "order_ids": [], - "pending_orders": 0, - "completed_orders": 0, - "refund_count": 0, - "personality": [ - "砍价狂", - "纠结" - ], - "communication_prefer": "", - "response_speed": "", - "patience_level": "", - "customer_level": "C", - "vip": false, - "vip_level": 0, - "last_price": 10, - "last_price_time": "2026-02-28T15:05:45.067204", - "last_quote_no_convert": false, - "last_min_price": 0, - "last_image_url": "", - "last_image_time": "", - "last_gemini_prompt": "", - "last_aspect_ratio": "1:1", - "last_perspective": "no", - "processing_status": "", - "processing_image_url": "", - "expected_done_at": "", - "discount_given_count": 6, - "lowest_price_accepted": 10, - "preferred_format": "jpg", - "preferred_size": "", - "last_conversation_summary": "", - "last_conversation_time": "", - "total_images_sent": 0, - "complexity_history": [], - "image_type_history": [], - "price_sensitivity": "高", - "decision_speed": "慢", - "revision_count": 0, - "revision_orders": 0, - "total_completed_orders": 0, - "bulk_potential": "", - "churn_risk": "低", - "upsell_opportunity": [], - "blacklist": false, - "blacklist_reason": "", - "vip_custom_price": 0, - "last_email_status": "", - "good_reviews": 0, - "bad_reviews": 0, - "dispute_count": 0, - "follow_up_by": "", - "follow_up_date": "", - "next_follow_date": "", - "source": "", - "coupon_used": "", - "notes": [], - "tags": [], - "created_at": "", - "last_contact": "2026-02-28T15:03:57.132648", - "last_update": "2026-02-28T15:05:45.071818" - }, - "vip_customer_004": { - "customer_id": "vip_customer_004", - "name": "VIP客户陈总", - "nickname": "", - "email": "", - "phone": "", - "wechat": "", - "address": "", - "platform": "", - "platform_id": "", - "budget": "", - "budget_range_min": 0, - "budget_range_max": 0, - "requirements": [], - "preference_services": [], - "total_orders": 15, - "total_spent": 680, - "avg_order_value": 0.0, - "purchase_frequency": "", - "last_order_date": "", - "first_order_date": "", - "order_ids": [], - "pending_orders": 0, - "completed_orders": 0, - "refund_count": 0, - "personality": [ - "爽快" - ], - "communication_prefer": "", - "response_speed": "", - "patience_level": "", - "customer_level": "A", - "vip": true, - "vip_level": 2, - "last_price": 20, - "last_price_time": "2026-02-28T15:04:56.155844", - "last_quote_no_convert": false, - "last_min_price": 0, - "last_image_url": "", - "last_image_time": "", - "last_gemini_prompt": "", - "last_aspect_ratio": "1:1", - "last_perspective": "no", - "processing_status": "", - "processing_image_url": "", - "expected_done_at": "", - "discount_given_count": 0, - "lowest_price_accepted": 0, - "preferred_format": "jpg", - "preferred_size": "", - "last_conversation_summary": "", - "last_conversation_time": "", - "total_images_sent": 0, - "complexity_history": [], - "image_type_history": [], - "price_sensitivity": "低", - "decision_speed": "快", - "revision_count": 0, - "revision_orders": 0, - "total_completed_orders": 0, - "bulk_potential": "", - "churn_risk": "低", - "upsell_opportunity": [], - "blacklist": false, - "blacklist_reason": "", - "vip_custom_price": 18, - "last_email_status": "", - "good_reviews": 0, - "bad_reviews": 0, - "dispute_count": 0, - "follow_up_by": "", - "follow_up_date": "", - "next_follow_date": "", - "source": "", - "coupon_used": "", - "notes": [], - "tags": [], - "created_at": "", - "last_contact": "2026-02-28T15:03:57.134104", - "last_update": "2026-02-28T15:04:56.158233" - }, - "high_value_005": { - "customer_id": "high_value_005", - "name": "高价值客户刘老板", - "nickname": "", - "email": "", - "phone": "", - "wechat": "", - "address": "", - "platform": "", - "platform_id": "", - "budget": "", - "budget_range_min": 0, - "budget_range_max": 0, - "requirements": [], - "preference_services": [], - "total_orders": 20, - "total_spent": 1200, - "avg_order_value": 60, - "purchase_frequency": "", - "last_order_date": "", - "first_order_date": "", - "order_ids": [], - "pending_orders": 0, - "completed_orders": 0, - "refund_count": 0, - "personality": [ - "爽快" - ], - "communication_prefer": "", - "response_speed": "", - "patience_level": "", - "customer_level": "A", - "vip": false, - "vip_level": 0, - "last_price": 20, - "last_price_time": "2026-02-28T15:05:11.156030", - "last_quote_no_convert": false, - "last_min_price": 0, - "last_image_url": "", - "last_image_time": "", - "last_gemini_prompt": "", - "last_aspect_ratio": "1:1", - "last_perspective": "no", - "processing_status": "", - "processing_image_url": "", - "expected_done_at": "", - "discount_given_count": 0, - "lowest_price_accepted": 0, - "preferred_format": "jpg", - "preferred_size": "", - "last_conversation_summary": "", - "last_conversation_time": "", - "total_images_sent": 0, - "complexity_history": [], - "image_type_history": [], - "price_sensitivity": "低", - "decision_speed": "快", - "revision_count": 0, - "revision_orders": 0, - "total_completed_orders": 0, - "bulk_potential": "", - "churn_risk": "低", - "upsell_opportunity": [], - "blacklist": false, - "blacklist_reason": "", - "vip_custom_price": 0, - "last_email_status": "", - "good_reviews": 0, - "bad_reviews": 0, - "dispute_count": 0, - "follow_up_by": "", - "follow_up_date": "", - "next_follow_date": "", - "source": "", - "coupon_used": "", - "notes": [], - "tags": [], - "created_at": "", - "last_contact": "2026-02-28T15:03:57.135396", - "last_update": "2026-02-28T15:05:11.160004" - }, - "blacklist_006": { - "customer_id": "blacklist_006", - "name": "黑名单客户", - "nickname": "", - "email": "", - "phone": "", - "wechat": "", - "address": "", - "platform": "", - "platform_id": "", - "budget": "", - "budget_range_min": 0, - "budget_range_max": 0, - "requirements": [], - "preference_services": [], - "total_orders": 0, - "total_spent": 0.0, - "avg_order_value": 0.0, - "purchase_frequency": "", - "last_order_date": "", - "first_order_date": "", - "order_ids": [], - "pending_orders": 0, - "completed_orders": 0, - "refund_count": 0, - "personality": [], - "communication_prefer": "", - "response_speed": "", - "patience_level": "", - "customer_level": "C", - "vip": false, - "vip_level": 0, - "last_price": 0, - "last_price_time": "", - "last_quote_no_convert": false, - "last_min_price": 0, - "last_image_url": "", - "last_image_time": "", - "last_gemini_prompt": "", - "last_aspect_ratio": "1:1", - "last_perspective": "no", - "processing_status": "", - "processing_image_url": "", - "expected_done_at": "", - "discount_given_count": 0, - "lowest_price_accepted": 0, - "preferred_format": "jpg", - "preferred_size": "", - "last_conversation_summary": "", - "last_conversation_time": "", - "total_images_sent": 0, - "complexity_history": [], - "image_type_history": [], - "price_sensitivity": "", - "decision_speed": "", - "revision_count": 0, - "revision_orders": 0, - "total_completed_orders": 0, - "bulk_potential": "", - "churn_risk": "低", - "upsell_opportunity": [], - "blacklist": true, - "blacklist_reason": "恶意投诉多次", - "vip_custom_price": 0, - "last_email_status": "", - "good_reviews": 0, - "bad_reviews": 0, - "dispute_count": 0, - "follow_up_by": "", - "follow_up_date": "", - "next_follow_date": "", - "source": "", - "coupon_used": "", - "notes": [], - "tags": [], - "created_at": "", - "last_contact": "2026-02-28T15:03:57.136490", - "last_update": "2026-02-28T15:05:27.155220" - }, - "test_new_001": { - "customer_id": "test_new_001", - "name": "新客户小王", - "nickname": "", - "email": "", - "phone": "", - "wechat": "", - "address": "", - "platform": "", - "platform_id": "", - "budget": "", - "budget_range_min": 0, - "budget_range_max": 0, - "requirements": [], - "preference_services": [], - "total_orders": 0, - "total_spent": 0, - "avg_order_value": 0.0, - "purchase_frequency": "", - "last_order_date": "", - "first_order_date": "", - "order_ids": [], - "pending_orders": 0, - "completed_orders": 0, - "refund_count": 0, - "personality": [], - "communication_prefer": "", - "response_speed": "", - "patience_level": "", - "customer_level": "C", - "vip": false, - "vip_level": 0, - "last_price": 0, - "last_price_time": "2026-02-28T15:27:40.801329", - "last_quote_no_convert": false, - "last_min_price": 0, - "last_image_url": "", - "last_image_time": "", - "last_gemini_prompt": "", - "last_aspect_ratio": "1:1", - "last_perspective": "no", - "processing_status": "", - "processing_image_url": "", - "expected_done_at": "", - "discount_given_count": 0, - "lowest_price_accepted": 0, - "preferred_format": "jpg", - "preferred_size": "", - "last_conversation_summary": "", - "last_conversation_time": "", - "total_images_sent": 0, - "complexity_history": [], - "image_type_history": [], - "price_sensitivity": "", - "decision_speed": "", - "revision_count": 0, - "revision_orders": 0, - "total_completed_orders": 0, - "bulk_potential": "", - "churn_risk": "低", - "upsell_opportunity": [], - "blacklist": false, - "blacklist_reason": "", - "vip_custom_price": 0, - "last_email_status": "", - "good_reviews": 0, - "bad_reviews": 0, - "dispute_count": 0, - "follow_up_by": "", - "follow_up_date": "", - "next_follow_date": "", - "source": "", - "coupon_used": "", - "notes": [], - "tags": [], - "created_at": "", - "last_contact": "2026-02-28T15:29:05.719291", - "last_update": "2026-02-28T15:29:05.719308" - }, - "test_fast_002": { - "customer_id": "test_fast_002", - "name": "爽快老客老李", - "nickname": "", - "email": "", - "phone": "", - "wechat": "", - "address": "", - "platform": "", - "platform_id": "", - "budget": "", - "budget_range_min": 0, - "budget_range_max": 0, - "requirements": [], - "preference_services": [], - "total_orders": 8, - "total_spent": 280, - "avg_order_value": 0.0, - "purchase_frequency": "", - "last_order_date": "", - "first_order_date": "", - "order_ids": [], - "pending_orders": 0, - "completed_orders": 0, - "refund_count": 0, - "personality": [ - "爽快" - ], - "communication_prefer": "", - "response_speed": "", - "patience_level": "", - "customer_level": "C", - "vip": false, - "vip_level": 0, - "last_price": 25, - "last_price_time": "", - "last_quote_no_convert": false, - "last_min_price": 0, - "last_image_url": "", - "last_image_time": "", - "last_gemini_prompt": "", - "last_aspect_ratio": "1:1", - "last_perspective": "no", - "processing_status": "", - "processing_image_url": "", - "expected_done_at": "", - "discount_given_count": 0, - "lowest_price_accepted": 0, - "preferred_format": "", - "preferred_size": "", - "last_conversation_summary": "", - "last_conversation_time": "", - "total_images_sent": 0, - "complexity_history": [], - "image_type_history": [], - "price_sensitivity": "低", - "decision_speed": "快", - "revision_count": 0, - "revision_orders": 0, - "total_completed_orders": 8, - "bulk_potential": "", - "churn_risk": "", - "upsell_opportunity": [], - "blacklist": false, - "blacklist_reason": "", - "vip_custom_price": 0, - "last_email_status": "", - "good_reviews": 0, - "bad_reviews": 0, - "dispute_count": 0, - "follow_up_by": "", - "follow_up_date": "", - "next_follow_date": "", - "source": "", - "coupon_used": "", - "notes": [], - "tags": [], - "created_at": "", - "last_contact": "2026-02-28T15:29:05.720944", - "last_update": "2026-02-28T15:29:05.720948" - }, - "test_bargain_003": { - "customer_id": "test_bargain_003", - "name": "砍价王小张", - "nickname": "", - "email": "", - "phone": "", - "wechat": "", - "address": "", - "platform": "", - "platform_id": "", - "budget": "", - "budget_range_min": 0, - "budget_range_max": 0, - "requirements": [], - "preference_services": [], - "total_orders": 3, - "total_spent": 45, - "avg_order_value": 0.0, - "purchase_frequency": "", - "last_order_date": "", - "first_order_date": "", - "order_ids": [], - "pending_orders": 0, - "completed_orders": 0, - "refund_count": 0, - "personality": [ - "砍价狂", - "纠结" - ], - "communication_prefer": "", - "response_speed": "", - "patience_level": "", - "customer_level": "C", - "vip": false, - "vip_level": 0, - "last_price": 15, - "last_price_time": "", - "last_quote_no_convert": false, - "last_min_price": 0, - "last_image_url": "", - "last_image_time": "", - "last_gemini_prompt": "", - "last_aspect_ratio": "1:1", - "last_perspective": "no", - "processing_status": "", - "processing_image_url": "", - "expected_done_at": "", - "discount_given_count": 4, - "lowest_price_accepted": 15, - "preferred_format": "", - "preferred_size": "", - "last_conversation_summary": "", - "last_conversation_time": "", - "total_images_sent": 0, - "complexity_history": [], - "image_type_history": [], - "price_sensitivity": "高", - "decision_speed": "慢", - "revision_count": 0, - "revision_orders": 0, - "total_completed_orders": 0, - "bulk_potential": "", - "churn_risk": "", - "upsell_opportunity": [], - "blacklist": false, - "blacklist_reason": "", - "vip_custom_price": 0, - "last_email_status": "", - "good_reviews": 0, - "bad_reviews": 0, - "dispute_count": 0, - "follow_up_by": "", - "follow_up_date": "", - "next_follow_date": "", - "source": "", - "coupon_used": "", - "notes": [], - "tags": [], - "created_at": "", - "last_contact": "2026-02-28T15:29:05.722448", - "last_update": "2026-02-28T15:29:05.722454" - }, - "test_vip_004": { - "customer_id": "test_vip_004", - "name": "VIP 客户陈总", - "nickname": "", - "email": "", - "phone": "", - "wechat": "", - "address": "", - "platform": "", - "platform_id": "", - "budget": "", - "budget_range_min": 0, - "budget_range_max": 0, - "requirements": [], - "preference_services": [], - "total_orders": 15, - "total_spent": 680, - "avg_order_value": 0.0, - "purchase_frequency": "", - "last_order_date": "", - "first_order_date": "", - "order_ids": [], - "pending_orders": 0, - "completed_orders": 0, - "refund_count": 0, - "personality": [ - "爽快" - ], - "communication_prefer": "", - "response_speed": "", - "patience_level": "", - "customer_level": "A", - "vip": true, - "vip_level": 2, - "last_price": 0, - "last_price_time": "", - "last_quote_no_convert": false, - "last_min_price": 0, - "last_image_url": "", - "last_image_time": "", - "last_gemini_prompt": "", - "last_aspect_ratio": "1:1", - "last_perspective": "no", - "processing_status": "", - "processing_image_url": "", - "expected_done_at": "", - "discount_given_count": 0, - "lowest_price_accepted": 0, - "preferred_format": "", - "preferred_size": "", - "last_conversation_summary": "", - "last_conversation_time": "", - "total_images_sent": 0, - "complexity_history": [], - "image_type_history": [], - "price_sensitivity": "低", - "decision_speed": "快", - "revision_count": 0, - "revision_orders": 0, - "total_completed_orders": 0, - "bulk_potential": "", - "churn_risk": "", - "upsell_opportunity": [], - "blacklist": false, - "blacklist_reason": "", - "vip_custom_price": 18, - "last_email_status": "", - "good_reviews": 0, - "bad_reviews": 0, - "dispute_count": 0, - "follow_up_by": "", - "follow_up_date": "", - "next_follow_date": "", - "source": "", - "coupon_used": "", - "notes": [], - "tags": [], - "created_at": "", - "last_contact": "2026-02-28T15:29:05.723887", - "last_update": "2026-02-28T15:29:05.723890" - }, - "test_highvalue_005": { - "customer_id": "test_highvalue_005", - "name": "高价值客户刘老板", - "nickname": "", - "email": "", - "phone": "", - "wechat": "", - "address": "", - "platform": "", - "platform_id": "", - "budget": "", - "budget_range_min": 0, - "budget_range_max": 0, - "requirements": [], - "preference_services": [], - "total_orders": 20, - "total_spent": 1200, - "avg_order_value": 60, - "purchase_frequency": "", - "last_order_date": "", - "first_order_date": "", - "order_ids": [], - "pending_orders": 0, - "completed_orders": 0, - "refund_count": 0, - "personality": [ - "爽快" - ], - "communication_prefer": "", - "response_speed": "", - "patience_level": "", - "customer_level": "A", - "vip": false, - "vip_level": 0, - "last_price": 0, - "last_price_time": "", - "last_quote_no_convert": false, - "last_min_price": 0, - "last_image_url": "", - "last_image_time": "", - "last_gemini_prompt": "", - "last_aspect_ratio": "1:1", - "last_perspective": "no", - "processing_status": "", - "processing_image_url": "", - "expected_done_at": "", - "discount_given_count": 0, - "lowest_price_accepted": 0, - "preferred_format": "", - "preferred_size": "", - "last_conversation_summary": "", - "last_conversation_time": "", - "total_images_sent": 0, - "complexity_history": [], - "image_type_history": [], - "price_sensitivity": "低", - "decision_speed": "快", - "revision_count": 0, - "revision_orders": 0, - "total_completed_orders": 0, - "bulk_potential": "", - "churn_risk": "", - "upsell_opportunity": [], - "blacklist": false, - "blacklist_reason": "", - "vip_custom_price": 0, - "last_email_status": "", - "good_reviews": 0, - "bad_reviews": 0, - "dispute_count": 0, - "follow_up_by": "", - "follow_up_date": "", - "next_follow_date": "", - "source": "", - "coupon_used": "", - "notes": [], - "tags": [], - "created_at": "", - "last_contact": "2026-02-28T15:29:05.725313", - "last_update": "2026-02-28T15:29:05.725316" - } -} \ No newline at end of file +{} \ No newline at end of file diff --git a/db/__pycache__/__init__.cpython-310.pyc b/db/__pycache__/__init__.cpython-310.pyc index fec3c2e11706970e7a01611ca65dd875502c53f5..34574f73bdf49d4cece8ae68ba224e53eda25c03 100755 GIT binary patch delta 27 hcmb;}Va&Vxmd-7q!#67<|UTo7scpJ^i=@>v>pn) diff --git a/db/__pycache__/chat_log_db.cpython-310.pyc b/db/__pycache__/chat_log_db.cpython-310.pyc index 6d87751a65eba5e1946b15da09f9f92dcd24d157..f151f7b4a48fc802225899935d7e1871025a6247 100755 GIT binary patch literal 14761 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 delta 3132 zcmb7GOKcm*8J?M)T`no{A(0|Qz2DMW5=F^2{D5M|v1$ZpswRyAqkBG;H* zRaQWT2Be}u&^B=95Fo8v>1H*#xaz$q3KRtz6aji@v4^IY9@0Y-+dzRT1=4?ZDVnwe z)Fm?0nzhuQLW@D`fYu2uZgvzSEWx^V)Rj&)!%}7k?5Ubs z8Wkz)W@#9YvsrI_>zu}VS>H}wT}iNvHz_x4HPG1r8-&GO-t6NohuAP2G|A@J2&{NK zKFY?xI`z!>IGcd+ZkA`OEW-N`4-jwjpsWXEe1EVw}uOnk#WXb)yt8vrW;FW@8 z?dXR=q0lZuvu8j!XbnRnyNW~iFvE=eh+yQXyPE9RKwAq`QBJQS*jQPxsP}U9OH0s>Fnxdlb1`CJWQ{$tE+|Uc_+7SUCXhnnVVZ~Fn7&#a&k#To?Qo# z#38I>ig_G5&%g{KRQGYd1=9}NM(-@tP!;V0$~}yIjWjhyYHtEom)-I+JW8&3BR_r9cDgKf_c*^Sru0+Smkob;ZZ>B@#>3C=(>SYrQ`saUC^<+LFgoe zL*Wo6B!b(4M)G9{Mn?X@Q_>u{ZG{cnvC1aTm6#hSo3@?525%GL)bh|9VB!E(duW$P zI%@$(0fKvLdR5=0jEH(FomLz4C{214kDe)UKlM>v<3I*-m5R0L>bAp+P6^&6UC9$t zBtaNKo|bx#6unaPNzpIGfE0ruT;kX~CVMiHS`fF%=xLn$Buv@TC=!w(LvW~5q5lbK zBmd^3qAhK_atY?VAnB;#DwaV~MMb(T(Y0uDD0(3!)x{{VC+HGiH2#IJfdOxsPD^2l+VM=r@seLAYwPr zz3?)q9`?=}sS+Q16&FbZz48qDZt;hK$y+HDwmaMO)9hEV92<_ zGoTyPkA)@&JS#1p@_DRLCBA2JJ1=wMyI|C0LDR?~)#xFxp!4HmX?Wyn1?D~M$7)Iy z^UkVrguhCPN`nDf33=nB3SMsVLYe1xN2$_nEPY>7fhqMUPO7RG?b(BmhbPJGbE3Wt z#{tx1V+)u3Jol4f4u)Nwn-Z4E49%y)%Y!HRa20FAX(dJMjrA>*VYxj5LMIe!SZ~mv z={_OkFcAoSMmuBwq@DZ}m=&;$i%YAZK9S|v%knNSN+8RD4g3?tl)FABknc4aEA)r~ zFH=SiUK`Kg=f(eHcqQQfa3cG%Um*C992u74acz)vG~&Tk9gF3+`~vV*5s?)4CzAa; zu)>zH6(Kq>(5{j%s7k+pKnUe4< z-WwOW*-TCeE^U;_yzHch3WeHU<1iI?j>#t z64y^!_GPUnJmJardM#?Ugi@%MY>tRoBFWlZpE8BrP(9sTaVpW&o4hx~}0!vkw8i z1ZI#P@{(^6^4rhAe9V6=$OrMKPxwR9-XP2TCHd@e1GyZt3b`B)L!WS6Ts}Qim*3zn zU9(CR-X>K&mn)XmO|WX0-OxqIo5U17p!Ev-jM0`D3MW(D;qKn4 Gp8o>ST%B0} diff --git a/db/__pycache__/customer_db.cpython-310.pyc b/db/__pycache__/customer_db.cpython-310.pyc index e1280493bdcbe7b49486a035b05f4d3014aba91a..776213fef202892387272c2a9402e67e7039c61b 100755 GIT binary patch literal 27380 zcmcJ233yajc4pP9SF5B#2q6{=Twr4m`(hhRgUu!u8w-rEG1cvqgblZ4ow;O|(WRgiHnM}TXlW&sD%Q|UFLOq>vx}8okxZTYEpZn@n zm8uG-zi$S8@6@^HF7Gbqo_o%@_ddF+szNUO^MCkS;=dhrxqiYx{y#4Q%kU)s8o+Qx zU54Ax+TBsN{Ay7Rzn*qahbQWBGfr>UJG@bEhcD{u@JIa}foMSJ-u7TeC>rXhh*n70 z*IwCC6|Hi+;_kk%;Wq;PTHlC%SF~EfK_k?!MMuVKBvfHk_G^dT(NPkrGQxDq*C/(g0VM}X!OEPKsT9O9hk-Nf(x3#3(Qw&D^ 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 delta 8897 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 Y80I`8e)2g{$!8=Ge7LH!eYv*szwvym{{R30 diff --git a/db/__pycache__/designer_roster_db.cpython-310.pyc b/db/__pycache__/designer_roster_db.cpython-310.pyc deleted file mode 100755 index 795744a505880acb94704a31dfad11c7c707b34e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5762 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 diff --git a/db/chat_log_db.py b/db/chat_log_db.py index e967181..384ab57 100755 --- a/db/chat_log_db.py +++ b/db/chat_log_db.py @@ -199,14 +199,18 @@ def get_customers(limit: int = 100) -> List[Dict]: def get_conversation(customer_id: str, limit: int = 200) -> List[Dict]: - """返回某客户的全部对话记录(按时间升序)""" + """返回某客户的最近对话记录(按时间升序)""" with _get_conn() as conn: + # 核心修复:先取最新的 limit 条,再按时间正序排列 rows = conn.execute(_sql(""" - SELECT id, direction, message, msg_type, timestamp, acc_id - FROM chat_logs - WHERE customer_id = ? + SELECT * FROM ( + SELECT id, direction, message, msg_type, timestamp, acc_id + FROM chat_logs + WHERE customer_id = ? + ORDER BY timestamp DESC, id DESC + LIMIT ? + ) AS recent ORDER BY timestamp ASC, id ASC - LIMIT ? """), (customer_id, limit)).fetchall() return [dict(r) for r in rows] diff --git a/db/chat_log_db/chats.db b/db/chat_log_db/chats.db index 54f64723363e227ba76fa24b7fe1078a2babee36..3927cceb65d1effe7e795cac48f7b2bf6f5d95c4 100755 GIT binary patch delta 8647 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 A8vp=8=Icg6@IjpEuYuEj9- z&BaaeO|AKB(*`*lQD^s&G@Vbx`M3Mv+!YfH2tWV=5P$##AOHafKmY>oPe3%cTWy!# zI8sGoE~9xk$}=5KW3J_dk430?_BY%7IrO@L$9nxE?~*->VuL=jBKOVmWFpc~MhDEK zF`ZXu(Aa8ycBx!GCDUBznYFN4dqfqon!ozBb33NnE!U;@A2q*@g_X#fZan1-x<7o+ z-X+`LVJpMbS?rkw-etf}hrN^T@QNLKR|mC7tHLU}KL}X=!uRW;i~6g$Bkx!D!Vg$` zCb?2FZ`T(jsT@ni bool: - return _DB_TYPE in ("mysql", "mariadb") - -def _sql(query: str) -> str: - return query.replace("?", "%s") if _is_mysql() else query - -def _now_str() -> str: - if _is_mysql(): - return datetime.now().strftime("%Y-%m-%d %H:%M:%S") - return datetime.now().isoformat() class TaskStatus(Enum): - """任务状态""" - PENDING = "pending" # 待付款 - PAID = "paid" # 已付款,待处理 - PROCESSING = "processing" # 处理中 - AWAITING_CONFIRM = "awaiting_confirm" # 已完成,待客户确认 - COMPLETED = "completed" # 已完成 - FAILED = "failed" # 失败 - CANCELLED = "cancelled" # 已取消 + PENDING = "pending" + PROCESSING = "processing" + COMPLETED = "completed" + FAILED = "failed" class ImageTaskManager: - """图片任务管理器""" - def __init__(self, db_path: str = None): if db_path is None: db_path = Path(__file__).parent / "image_tasks.db" - self.db_path = db_path self._init_db() - logger.info(f"图片任务管理器初始化完成,数据库:{self.db_path}") - + def _init_db(self): - """初始化数据库""" - if _is_mysql(): - conn = self._get_conn() - cursor = conn.cursor() - cursor.execute(''' - CREATE TABLE IF NOT EXISTS image_tasks ( - task_id VARCHAR(128) PRIMARY KEY, - customer_id VARCHAR(128) NOT NULL, - customer_name VARCHAR(255), - original_image TEXT NOT NULL, - operation VARCHAR(64) DEFAULT 'enhance', - requirements TEXT, - customer_notes TEXT, - status VARCHAR(32) DEFAULT 'pending', - created_at DATETIME, - paid_at DATETIME, - started_at DATETIME, - completed_at DATETIME, - result_image TEXT, - error_message TEXT, - retry_count INT DEFAULT 0, - acc_id VARCHAR(128), - acc_type VARCHAR(64) DEFAULT 'AliWorkbench' - ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 - ''') - cursor.execute(''' - CREATE TABLE IF NOT EXISTS task_requirement_changes ( - id INTEGER PRIMARY KEY AUTO_INCREMENT, - task_id VARCHAR(128) NOT NULL, - change_type VARCHAR(64), - old_value TEXT, - new_value TEXT, - changed_at DATETIME, - changed_by VARCHAR(32), - FOREIGN KEY (task_id) REFERENCES image_tasks(task_id) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 - ''') - cursor.execute("SHOW INDEX FROM image_tasks") - exists = {str(r.get("Key_name", "")) for r in cursor.fetchall()} - if "idx_customer" not in exists: - cursor.execute('CREATE INDEX idx_customer ON image_tasks(customer_id)') - if "idx_status" not in exists: - cursor.execute('CREATE INDEX idx_status ON image_tasks(status)') - if "idx_created" not in exists: - cursor.execute('CREATE INDEX idx_created ON image_tasks(created_at)') - conn.commit() - conn.close() - else: - self.db_path.parent.mkdir(parents=True, exist_ok=True) - conn = sqlite3.connect(self.db_path) - cursor = conn.cursor() - cursor.execute(''' - CREATE TABLE IF NOT EXISTS image_tasks ( - task_id TEXT PRIMARY KEY, - customer_id TEXT NOT NULL, - customer_name TEXT, - original_image TEXT NOT NULL, - operation TEXT DEFAULT 'enhance', - requirements TEXT, - customer_notes TEXT, - status TEXT DEFAULT 'pending', - created_at TEXT, - paid_at TEXT, - started_at TEXT, - completed_at TEXT, - result_image TEXT, - error_message TEXT, - retry_count INTEGER DEFAULT 0, - acc_id TEXT, - acc_type TEXT DEFAULT 'AliWorkbench' - ) - ''') - cursor.execute(''' - CREATE TABLE IF NOT EXISTS task_requirement_changes ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - task_id TEXT NOT NULL, - change_type TEXT, - old_value TEXT, - new_value TEXT, - changed_at TEXT, - changed_by TEXT, - FOREIGN KEY (task_id) REFERENCES image_tasks(task_id) - ) - ''') - cursor.execute('CREATE INDEX IF NOT EXISTS idx_customer ON image_tasks(customer_id)') - cursor.execute('CREATE INDEX IF NOT EXISTS idx_status ON image_tasks(status)') - cursor.execute('CREATE INDEX IF NOT EXISTS idx_created ON image_tasks(created_at)') - conn.commit() - conn.close() - logger.info("数据库表初始化完成") - - def _get_conn(self): - """获取数据库连接""" - if _is_mysql(): - import pymysql - return pymysql.connect( - host=_MYSQL_HOST, - port=_MYSQL_PORT, - user=_MYSQL_USER, - password=_MYSQL_PASSWORD, - database=_MYSQL_DATABASE, - charset="utf8mb4", - cursorclass=pymysql.cursors.DictCursor, - autocommit=False, + self.db_path.parent.mkdir(parents=True, exist_ok=True) + conn = sqlite3.connect(self.db_path) + cursor = conn.cursor() + # 核心任务表 + cursor.execute(''' + CREATE TABLE IF NOT EXISTS image_tasks ( + task_id TEXT PRIMARY KEY, + customer_id TEXT NOT NULL, + platform TEXT DEFAULT 'qianniu', + original_image TEXT NOT NULL, + operation TEXT DEFAULT 'enhance', + requirements TEXT, + status TEXT DEFAULT 'pending', + result_image TEXT, + price REAL DEFAULT 0.0, + outcome TEXT DEFAULT 'pending', + created_at TEXT, + updated_at TEXT ) + ''') + cursor.execute('CREATE INDEX IF NOT EXISTS idx_status ON image_tasks(status)') + cursor.execute('CREATE INDEX IF NOT EXISTS idx_cust_plat ON image_tasks(customer_id, platform)') + conn.commit() + conn.close() + + def _get_conn(self): conn = sqlite3.connect(self.db_path) conn.row_factory = sqlite3.Row return conn - - def create_task(self, task_id: str, customer_id: str, customer_name: str, - original_image: str, operation: str = 'enhance', - requirements: dict = None, acc_id: str = '', acc_type: str = 'AliWorkbench') -> bool: - """创建图片任务""" + + def add_task(self, customer_id: str, platform: str, original_image: str, operation: str, requirements: str = "", status: str = "pending") -> str: + task_id = str(uuid.uuid4()) + now = datetime.now().isoformat() try: conn = self._get_conn() cursor = conn.cursor() - - requirements_json = json.dumps(requirements) if requirements else None - - cursor.execute(_sql(''' - INSERT INTO image_tasks ( - task_id, customer_id, customer_name, original_image, - operation, requirements, customer_notes, status, - created_at, acc_id, acc_type - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - '''), ( - task_id, - customer_id, - customer_name, - original_image, - operation, - requirements_json, - '', # 初始备注为空 - TaskStatus.PENDING.value, - _now_str(), - acc_id, - acc_type - )) - + cursor.execute(''' + INSERT INTO image_tasks (task_id, customer_id, platform, original_image, operation, requirements, status, created_at, updated_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) + ''', (task_id, customer_id, platform, original_image, operation, requirements, status, now, now)) conn.commit() conn.close() - - logger.info(f"图片任务创建成功:{task_id}") - return True - + return task_id except Exception as e: - logger.error(f"创建图片任务失败:{e}") - return False - - def get_task(self, task_id: str) -> Optional[dict]: - """查询任务""" + logger.error(f"Failed to add task: {e}") + return "" + + def update_status(self, task_id: str, status: str, result_image: str = ""): + now = datetime.now().isoformat() try: conn = self._get_conn() cursor = conn.cursor() - - cursor.execute(_sql('SELECT * FROM image_tasks WHERE task_id = ?'), (task_id,)) - row = cursor.fetchone() - conn.close() - - if row: - task = dict(row) - # 解析 JSON 字段 - if task.get('requirements'): - task['requirements'] = json.loads(task['requirements']) - return task - return None - - except Exception as e: - logger.error(f"查询任务失败:{e}") - return None - - def get_customer_tasks(self, customer_id: str, status: str = None) -> List[dict]: - """查询客户的任务列表""" - try: - conn = self._get_conn() - cursor = conn.cursor() - - if status: - cursor.execute(_sql(''' - SELECT * FROM image_tasks - WHERE customer_id = ? AND status = ? - ORDER BY created_at DESC - '''), (customer_id, status)) + if result_image: + cursor.execute('UPDATE image_tasks SET status = ?, result_image = ?, updated_at = ? WHERE task_id = ?', + (status, result_image, now, task_id)) else: - cursor.execute(_sql(''' - SELECT * FROM image_tasks - WHERE customer_id = ? - ORDER BY created_at DESC - '''), (customer_id,)) - - rows = cursor.fetchall() - conn.close() - - tasks = [] - for row in rows: - task = dict(row) - if task.get('requirements'): - task['requirements'] = json.loads(task['requirements']) - tasks.append(task) - - return tasks - - except Exception as e: - logger.error(f"查询客户任务失败:{e}") - return [] - - def update_status(self, task_id: str, status: TaskStatus): - """更新任务状态""" - try: - conn = self._get_conn() - cursor = conn.cursor() - - placeholder = "%s" if _is_mysql() else "?" - updates = [f'status = {placeholder}'] - params = [status.value] - - # 根据状态设置时间 - if status == TaskStatus.PAID: - updates.append(f'paid_at = {placeholder}') - params.append(_now_str()) - elif status == TaskStatus.PROCESSING: - updates.append(f'started_at = {placeholder}') - params.append(_now_str()) - elif status in [TaskStatus.COMPLETED, TaskStatus.FAILED]: - updates.append(f'completed_at = {placeholder}') - params.append(_now_str()) - - params.append(task_id) - - cursor.execute(_sql(f''' - UPDATE image_tasks - SET {', '.join(updates)} - WHERE task_id = ? - '''), params) - + cursor.execute('UPDATE image_tasks SET status = ?, updated_at = ? WHERE task_id = ?', + (status, now, task_id)) conn.commit() conn.close() - - logger.info(f"任务状态更新:{task_id} -> {status.value}") - except Exception as e: - logger.error(f"更新任务状态失败:{e}") - - def update_result(self, task_id: str, result_image: str, error_message: str = None): - """更新处理结果""" + logger.error(f"Failed to update task status: {e}") + + def update_outcome(self, customer_id: str, platform: str, outcome: str): + """记录任务的最终结局(用于训练样本分类)""" + now = datetime.now().isoformat() try: conn = self._get_conn() cursor = conn.cursor() - - cursor.execute(_sql(''' + cursor.execute(''' UPDATE image_tasks - SET result_image = ?, error_message = ? - WHERE task_id = ? - '''), (result_image, error_message, task_id)) - + SET outcome = ?, updated_at = ? + WHERE task_id = ( + SELECT task_id FROM image_tasks + WHERE customer_id = ? AND platform = ? + ORDER BY created_at DESC LIMIT 1 + ) + ''', (outcome, now, customer_id, platform)) conn.commit() conn.close() - - logger.info(f"任务结果更新:{task_id}") - + logger.info(f"[DB] 客户 {customer_id} 任务结局更新为: {outcome}") except Exception as e: - logger.error(f"更新任务结果失败:{e}") - - def add_customer_note(self, task_id: str, note: str, changed_by: str = 'customer') -> bool: - """ - 客户添加需求备注(支持后续增加细节) - - Args: - task_id: 任务 ID - note: 备注内容 - changed_by: 修改者(customer/staff) - - Returns: - bool: 是否成功 - """ - try: - conn = self._get_conn() - cursor = conn.cursor() - - # 获取旧备注 - cursor.execute(_sql('SELECT customer_notes FROM image_tasks WHERE task_id = ?'), (task_id,)) - row = cursor.fetchone() - old_note = row['customer_notes'] if row else '' - - # 更新备注 - new_note = f"{old_note}\n[{datetime.now().strftime('%m-%d %H:%M')}] {note}" if old_note else f"[{datetime.now().strftime('%m-%d %H:%M')}] {note}" - - cursor.execute(_sql(''' - UPDATE image_tasks - SET customer_notes = ? - WHERE task_id = ? - '''), (new_note, task_id)) - - # 记录变更历史 - cursor.execute(_sql(''' - INSERT INTO task_requirement_changes ( - task_id, change_type, old_value, new_value, changed_at, changed_by - ) VALUES (?, ?, ?, ?, ?, ?) - '''), ( - task_id, - 'add_note', - old_note or '无', - note, - _now_str(), - changed_by - )) - - conn.commit() - conn.close() - - logger.info(f"客户添加备注成功:{task_id}") - return True - - except Exception as e: - logger.error(f"添加客户备注失败:{e}") - return False - - def modify_operation(self, task_id: str, new_operation: str, changed_by: str = 'customer') -> bool: - """ - 修改操作类型(客户后续修改需求) - - Args: - task_id: 任务 ID - new_operation: 新操作类型 - changed_by: 修改者 - - Returns: - bool: 是否成功 - """ - try: - conn = self._get_conn() - cursor = conn.cursor() - - # 获取旧操作 - cursor.execute(_sql('SELECT operation FROM image_tasks WHERE task_id = ?'), (task_id,)) - row = cursor.fetchone() - old_operation = row['operation'] if row else '' - - # 更新操作 - cursor.execute(_sql(''' - UPDATE image_tasks - SET operation = ? - WHERE task_id = ? - '''), (new_operation, task_id)) - - # 记录变更历史 - cursor.execute(_sql(''' - INSERT INTO task_requirement_changes ( - task_id, change_type, old_value, new_value, changed_at, changed_by - ) VALUES (?, ?, ?, ?, ?, ?) - '''), ( - task_id, - 'modify_operation', - old_operation, - new_operation, - _now_str(), - changed_by - )) - - conn.commit() - conn.close() - - logger.info(f"修改操作类型成功:{task_id} -> {new_operation}") - return True - - except Exception as e: - logger.error(f"修改操作类型失败:{e}") - return False - - def get_requirement_history(self, task_id: str) -> List[dict]: - """获取需求变更历史""" - try: - conn = self._get_conn() - cursor = conn.cursor() - - cursor.execute(_sql(''' - SELECT * FROM task_requirement_changes - WHERE task_id = ? - ORDER BY changed_at DESC - '''), (task_id,)) - - rows = cursor.fetchall() - conn.close() - - return [dict(row) for row in rows] - - except Exception as e: - logger.error(f"查询需求历史失败:{e}") - return [] - - def get_pending_tasks(self) -> List[dict]: - """获取所有待处理任务""" - return self.get_customer_tasks('', 'pending') - - def increment_retry(self, task_id: str) -> int: - """增加重试次数""" - try: - conn = self._get_conn() - cursor = conn.cursor() - - cursor.execute(_sql(''' - UPDATE image_tasks - SET retry_count = retry_count + 1 - WHERE task_id = ? - '''), (task_id,)) - - cursor.execute(_sql('SELECT retry_count FROM image_tasks WHERE task_id = ?'), (task_id,)) - row = cursor.fetchone() - conn.close() - - return row['retry_count'] if row else 0 - - except Exception as e: - logger.error(f"增加重试次数失败:{e}") - return 999 + logger.error(f"Failed to update outcome: {e}") # 单例 -_task_manager: Optional[ImageTaskManager] = None - -def get_image_task_manager() -> ImageTaskManager: - """获取图片任务管理器单例""" - global _task_manager - if _task_manager is None: - _task_manager = ImageTaskManager() - return _task_manager +db = ImageTaskManager() diff --git a/db/task_db/__pycache__/task_model.cpython-311.pyc b/db/task_db/__pycache__/task_model.cpython-311.pyc deleted file mode 100644 index e5dea299194b1fb9a8c72a537f28a63c3497ec8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17572 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 z zKzITHE(8HR90G3F2#+B^qd^g=^pSWZmd}V$MivBL5IZ}1e zf8PJ<;a8&HiMMH@1UHcE>&X4p*A(0hQUGv|2rPZzfv{~A*U#xvp zEWztfrnmq!Vm~POYK6eOK#N2~ql8pwayY{_No+ahe<+VCu!k9-Qsc7Vz9 zdd2+|MgqjsWHxz(Ly%#yYf2(9aG4FmNjT+f#b~{e#pY!G3sU$G0BGe@c&g{*ubSrv zSp`Ft*G<$RpIC@|Vj=R0g~%t$(K{s8?-vI`;(@`8kC%MB=;P;M3$2*0uAAH@RR=^i zFkN0Tu}1SCRHFw$0dw$+>GG#U;9-R7gN`n+u|j;mD*+cr6_ZgN6g zF4Fv+a4I4{-}uIt#W!q14eZ3`=LUJb39-t8_*Tp3&+K{N9jCzi(4KPwFc0Sl!2ZVF zIR~Aea~uM14(xF_k$V8|Aa?`raE+kCqZ~n)`Pp-~-+6oH?72_BdrHv~LodTfSync3 zi+mo5yod@L(ACUF?WmJg8AP(JJ?+L#3RE!jQr*+r4(F`e4&8D7XXyD_j;=4l(r>xvs8`067_trTV|;uu41-|s=jC9 ziO;KxO7H!G0syHRsG~}Wi7-ofxr)yzZ)xQh2;dPw4OLNhar^o0newGl`BK;%GCK8d zlFpv0fF912H%sv3Yt}?>6^dR3=%RPql_g^BHn=jr7RlEl`dX&TE62OCKTY^nq433l zdbZ8m=BKXuy*nt!)#^oUTO3#Kw_$vX6QE^&5|3jq%!WV03K*{M~cp;d#e(ZK1n|VdOc6>1_|mU zz7=KV-2ULXTNgi2z4liuEOcH%vyi~FP(xX%eY3VaD`gch<0qT|U}S5;UqOPEpJ`j$Npu$F<7f3SAB7ZB#LuRP z@^9_;EV~j;0u~&kT#Y4k_lod!d^`vsfvlUbALWA;!hKAYuyP+$wh!u)_y-_@+^6&| z+{d8ne-5gBDJuD;sN|P|lK*F9CRV%uuFRx$b?Z9n7wf!j%N)Phwy151<7&MP;#ZeA z0pd1B2=?y>k%?#ldyX)bQxL%qYSLPc>7KF~zn;o&Nu=!W+00*p!qFiV25QK^{L!G# zw?KIZoTXK^&F~=Y2jj{D4A_WwjVw=9l709?1p!Ykz{C*Xb&A)o9%K5c1NC$?*$Wl0 zg{H&NVBnB%E0wLTYNLEIWGunC(F$eBIqB=n;%m&}wEO#YQefLBkBH3T4AU<${UXz^ zpG#glRV`Mmg)76XlbCg)c3ICS>%Bh)FZnW9dW1UZNYYSwHMCQYKS;JzjdMWDgioYW zbaqQA&z7w{|CW)No%8mr3nc}tI7<GPe|+&BKySjvZi<9Z^Sdp9*~wjaK$Dq+dSc%7`hOJ12H1oaMP%0!5N3~?zuFp ze8(d0rdhe$ywp{%w{4r_YQ>_qjgG5pZ5ZF^1Q@Wvr{X=hdw?IE<$mYuNF)Ve4QAl? z6Uu-MK}@C(#^X_85EF6j3K0ajJxN%Q?1;cemiWzpfE%a67=ph+@C^jdBUpeS`>`-? z90>?e8BCmop%~MD({w9Vr5T+f^-|bcEb zr2wR%PvCYLnx!QfVqO-g(AYwtPyi@ng(D>UmF<~f1hKl>(pF!BOmka?3cp=1^p zH!5C1t)6EAbt|rMWXogJf4eBAQgko4QPc1p|10ou&5fcOk**=_3{;cv+?6j@9s_jQ zjh_g^za~(2&}d9@!I4KyAqxQc4w>xuiDvR}G;&b+_LvUCe^U^UJIfxZQ8)R}SXpaC zI+HcSVPUcYusL!`Fc^x(;>fh(u|zN^V9j&d_XlRH@^24XgqI)}nnfj^066Qg*=)14 z-3G&{0~cj087s!$G*vW4e$y0r#+2n^zH6Fl6boO|RE=o9rm0HNeBJcajaN&ay2*_h z&r->=bj&qNyKS(uWd##pjza1e*{m|!26NF0Cf0+lX{!QVQ_J@~N}~DU=M<)YLEx+c nk2BQrrZNBc@yQ~oWT{B4geya>oTZ(%+R2r(6x<2|GCBSSL9SWY diff --git a/image/__pycache__/__init__.cpython-310.pyc b/image/__pycache__/__init__.cpython-310.pyc index e77975b7e52370b741504b6648e8c4398fe5e6bb..d3508cc66cb4914f0ddee92698b27e9092449417 100755 GIT binary patch delta 27 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 P=|owANLh&T%TW419>sQN diff --git a/image/__pycache__/image_precheck.cpython-310.pyc b/image/__pycache__/image_precheck.cpython-310.pyc deleted file mode 100755 index b212d0e4ce02bb99c65d03d27f5e7182dbe83566..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1907 zcmZ`(>u(cB5Z}F9pU;k+*a^@=CF*`?g{u}q)v6V0tMYJ&RRU@3ieg1Nh3wk7_}RNN zA(3501Vku>M3s0oL~&XuZB-Q1R%ryG{2%)j&N!d=Sc$5S**gbW1@3gS`YOPf`RUCe=JlS;Q$X zQyH%LD50K3X$q(OO{_F=TN8V!>evHK>}%p+6Z>hKV{dQb01Z00gSMwaw1b6dh!NJw z!f9zUN)sBUohM1Ei%JO;?J5sI%6@z9kB4VYuYG&6{@rBc&B%k5vyHoV?b-7H>kHTI zTet0{l^ylks=Ye1qkehGp8dXlZo!_Pd9?b~gOzjk>@?UO&iz(Df4zS8Yx~><{~AO^ z2cwvKlI2p4rCyBp?cN{L`Uhfrdt-Y)*81WHwZrj!$=;OoPIqeaGpxO_`2ODH)5P7M zHHqZC?(Sz$!Tvldthwh%GM3=-PGCNj5-?pe?v5%GWcz3-GvNWrG5|^iAv1a!RAcOD z3Bb{OiTiWK;h~&X8nQ;XVlb<06o#?bd-H*6L85l{!e>r`#X_UFCRNZPHdTrfE|vwZ z;tIA%78zTpMCA&eLzK+RY4}T)hkCNaco*!>2zI4{srM!1eCiybKJZz`e!y+>9>JW@ zsfPw~O5R(QFsev3Rjf3VsLB<2)Hf(qN!3#!mOqQkPbwa(4OZ77day!Z_4bMfWQXM! zbE|C*&8unYFp>}r5k%0GjL~6~K)?@ViTOG3gOKGJ;D=lIomRl%2cOHAYwe3j#A=O8 zHzv?dWL_D=7;G3FaXmmwkkv7M52LDr(F9a6?Xp4@WeU>}-Eayj9M+LUo(gbisH%LS zB%0$G9z)ShmhVrV@H?gf=U1A$93XtR6|-+d^2{`cGAs%$ zQp|qPGn6w~q<(36T@QV8+pT~5{DM7KbI4Jtr@RqXY+Xk5%+1U8)gOAw9ZyX5wV&); z&{5OnZJ>+TH!n55Jn?At4D^^iv(%Wn>$Y5d`l8#2_UZ|HWyKKH))J+0@3ejG21L=} zpwNW8eP`OS_U&;)HI`3-O9Twv>9P;FeS0EnS7z<$WznqhJZ!HeUAOZ^OeZsrkC%hM zaYNOwPJ%je@R|Nj4*zq$b|X@L1?bJAxKykEdZDp&$DX+eo3elZW&KY1X6-HTib_e2 zqG2u-O-|efW5;#VGPyUyEK{FgTouxB?!maLm{M?uN+A*d)XYLWoK= zLLgG%#HaoJhX#_deOk|dZzkSsRsz65WT{{w9}V~GF& diff --git a/image/__pycache__/image_processor.cpython-310.pyc b/image/__pycache__/image_processor.cpython-310.pyc deleted file mode 100755 index 30bea40aed533bdb0ebec05fee6be8fa93cc95fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11275 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 diff --git a/run.py b/run.py index 3232957..5e1ee70 100755 --- a/run.py +++ b/run.py @@ -47,10 +47,10 @@ def _print_api_info(host: str, port: int): def run_websocket(enable_agent: bool): """WebSocket 客服模式(默认)""" import asyncio - from core.websocket_client import QingjianAPIClient + from core.websocket_client_v2 import QingjianAPIClient logger.info("=" * 60) - logger.info("AI 客服系统 - WebSocket 模式") + logger.info("AI 客服系统 - WebSocket 模式 (新架构 v2)") logger.info(f"AI Agent: {'已启用' if enable_agent else '未启用'}") logger.info("=" * 60) diff --git a/scripts/__pycache__/chat_ui.cpython-310.pyc b/scripts/__pycache__/chat_ui.cpython-310.pyc deleted file mode 100755 index 173d7a18a1f21b2d12b328c4af4bc1cd144c6ae1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13624 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 diff --git a/services/__pycache__/__init__.cpython-310.pyc b/services/__pycache__/__init__.cpython-310.pyc index 367e83ea42309b5dc60af5dda0a500b714ec990b..56817035aad55ba55b3807f2d06d360d300d3bf2 100755 GIT binary patch delta 27 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 E2PsS<&;S4c diff --git a/services/__pycache__/service_meitu.cpython-310.pyc b/services/__pycache__/service_meitu.cpython-310.pyc deleted file mode 100755 index dde9f81aea81b0b7713efe9eeed522a0f404ba01..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21706 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 a1JbvoZ^0>ror0?_{!xV1yQ--1tN#zyvLEjN diff --git a/services/dispatch_service.py b/services/dispatch_service.py new file mode 100644 index 0000000..06f706b --- /dev/null +++ b/services/dispatch_service.py @@ -0,0 +1,49 @@ +import os +import logging +import httpx +from typing import Optional, Dict, Any + +logger = logging.getLogger("cs_agent") + +class DispatchService: + """ + 8006 即时派发服务 API 接入 (正式对齐版) + """ + + def __init__(self): + # 严格按照老大提供的最新对齐信息 + self.base_url = "http://1.12.50.92:8006" + self.api_key = "tuhui_dispatch_key_2026" + self.timeout = 10.0 + + async def assign_designer(self) -> Optional[str]: + """ + 调用 /assign 接口,一键获取当前可用的设计师名字 + """ + url = f"{self.base_url}/assign" + # 严格使用 X-API-Key 请求头和带下划线的 Key + headers = {"X-API-Key": self.api_key} + + try: + async with httpx.AsyncClient(timeout=self.timeout) as client: + response = await client.get(url, headers=headers) + + if response.status_code == 200: + data = response.json() + if data.get("success"): + designer = data.get("assigned_to") + logger.info(f"[Dispatch] 派单成功!设计师: {designer}") + return designer + else: + logger.warning(f"[Dispatch] 派单被拒: {data.get('reason')}") + elif response.status_code == 401: + logger.error(f"[Dispatch] 授权失败(401)!请检查 Key 是否为: {self.api_key}") + else: + logger.error(f"[Dispatch] API 异常,状态码: {response.status_code}") + except Exception as e: + logger.error(f"[Dispatch] 网络请求崩溃: {e}") + + return None + +# 全局单例 +dispatch_service = DispatchService() diff --git a/utils/__pycache__/__init__.cpython-310.pyc b/utils/__pycache__/__init__.cpython-310.pyc index 2e6809e035e29eee1b7ffe107937a33b5db77160..7e6aba0898040ee4c55324caa8ae9eb43bc60eff 100755 GIT binary patch delta 27 hcmb;^;m+sfcwR69A8xooYVl}1E5F(tLa}kamVuO`K(9y}xczx{MbGCD4 zKyB2`P+`Wj&)3jrHnPvL zjeHZ^#5c3eJk7f{kx_?jVOy`*?iN_r1?#r4?J#reGW8rQ0JV)h&vslP?sjGjk>bw! z*FgNtq0=V|3)fy>xc%P45AH19YZdks7Vo`3|L31AzCZi$&0i-&AAk6h#XnwM`o)!p z_uiU+>d90(c^u?-qAxR`_C%+qPyYQkyC>M!zcRBmcPID-tm7-zuEgR z>0Ie8-`{@qU*Ed_)86ub=l=coQ|C|jmT$g|-&}9eadTx}4Z^_V7p3q^(rsI&U-jLN zUqvs5SHEStCKwRcsS;VC9WL7WnF|N6o2KT&_Sa* z0wu0NB}tRENZb~X01W3gz&%}%h9t~jCbO=aH*zyXnoX-gT6BaMV1yR@vnC}YWQgn~ z@s3GK3I1oHjKKI1j7xj!m4v&puLI*lWReu^fuf;o<_DE2m8wRe9D@!OkL%$TP=n@an(ls_HFDH=EH(jK zSztAO2?1RB4Cp)o^E*IDGET?QC&5dv8x(*8AOS{Z1CZS_R9fS9gES~}Sc;{uTM1w* zfFg7N=+4!EBCpssFbtTbYQEqhAduEbc+rHSlcEET6*;JmE#Y-wUY3V(U2xBjOF^KV zAY`zr=!iTFD<|1R+0_Xa2!Zm7H8^0gdbL(G#Af8I#|lAAs*O0o_G146-woXuWzGXa zYw3>1VkZzwh>A+ZTwDmi@a$4l52douhe{?4t$ZoySWvX}{Rlb@0IN=g(=fsmT4Dq2 zu4OdnS~6owqiMEC(_&_e&R9<<3n*LKvt-6;ILzLJt1RZgDsux#I1TFn_ELJxUNr`s zhJAoYSUC$;+b{v#bR7jv0?C8>mlob@6)?~wF=asDl^>;do!zsmx@Q-AWb2;5s4Y-v z0a2S2Q>sH7>gm2S-jPH7{mLwJDNu4{hS8)-$5M=9z|oeZAuFcD=W+cDSRty4mXs|c z=7T|Mw@6g+j26JBOOaqbupmZ-ZUqC)QHO4YKTRzvUIJzb%99VRVg>V0P+5t`HvxG- z5=<13q+pT;paotIXk*B=21F6&J{5G%*7Arw$i?FmQN9E{u$mWv6n0ZRiOgGHsne^$* zh83SlPHoU}NX{&CoxV&?!aYuqo7-mWhCSW}+SAFonQ4HR1eE1&8?5uXk<8M;#z=zA z3MXveySzvI!_{F&wl}jZ->`0xcMQB|ax%pAj;T2co=3@aC(OyQu7>k;&RMw4jPnCW zW21YM6e50i9Tm9n%S#J)?k@cNxAU*R`y@jr*?Ruk+YdgxJpY$_Ny64z#(bR{={s`b z(6BesclgBM;5X|ShCjO5{P_Nj!h;W9TX^fP_S7Wr7pBdgmqzR86NUM!vxSd-e7BIi z0t$6Be`K!S0A3Lbx38_lPab@%^w+-adXC4*V9l{bpT|w;l?PcmHqqkZ=28F?jec zXa$!J`L!~ zgdnfXAe1@=KUIyEW)*BYLh6*7K2VKVy~4kNnIy)@ZPB!u2Bfn3&lq_l3s~i;VHto^ S@;i@mnOtV8lgs9utn+{6wKt^z diff --git a/utils/__pycache__/content_filter.cpython-310.pyc b/utils/__pycache__/content_filter.cpython-310.pyc deleted file mode 100755 index 4c0d79d5f1b77b382c9cc53fbe4b57778c226f8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4675 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 diff --git a/utils/__pycache__/health_check.cpython-310.pyc b/utils/__pycache__/health_check.cpython-310.pyc deleted file mode 100755 index 2e012d0184ffb50ec64f6c40a91b13cb06158b11..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3797 zcmZ{nTX0jy8Gv{9Ty!Ma@&z!4(2UabCYqX6n35EZW08|M5xEjq zAXidqT8nFGJ+5P9levIx6mdLARVzd_E1X1Don3E7?1oXY3)ziSKZIx?-efCtN)g4I zsbOy$B{WDw7u5LnYAsCbptgh7i@peLfLaS}v?H|1j*P0bnQnuYopcx7ZtJ!-hPd1= zvJeY+?bM6uo3!?3+j>Fll2=l9EhE|mXtEBcdYY5sco+C5(V z+nbdKU#!j-_N^?PEj^sCEWcNN`_`kSx5~f&c=hvT5GuX%M&;uVLTfM!>W>lM=(18N zYb0g+#=w-9bTU@z=#U>VQz z+REMYt5x3*Y?qRNG;KuLvZD!oraK-@P)98tkzZGPy^2 z*rm%0m4^@I9{GAh=Cqv{w>;CCWc+x<5@o_s_UrjN)K zyL{x|;dTEB$ytdu%5&6}6i$;oPAhqWQ4YIJR2@V);_l%2?7(RWDQzo<=rU7cuU=q{NO+v$$i0sd+Idwv(b(3Tm5g4H&6`faPA4bDy5Vcola*s}9 z3@l*uYj}r2b`WH}z|1&Cc@3l42G5ua()yfs1O1T{L3S78vsLp^3! zPj}ZV&?-8Q_x2wfS`(mPKj0S?qFY? zaGlKBKcJH3S5&>~8vQH1|4HSqw>qLnVS8Q?yqv#0nx8}H81Ib{u^({3?Q9J*Q8Ea)i@MLt=bbjt7?OfaQ9@ zGRO)lm34weOC~J%g|eHdEc}pkzhE6#f|o7!Kb0$)Y|pmMrTP!bd4W1+Xjhmq%Af{ zo#~9YlPouQ|Gqx=Xz_A%@7`Hu@7_?1u$^2w#uILxvQbFBF=^@kr?so;h-RPNLP&Ut zs$7-tSUuYVl47}_JD@~Ng}Sed*`D8EcJ_6j7&5yC2KtT+4EHmx#f;-7sr?QwJ6%{G9Fgi_&j9Y-@4crsETuL*GL zXIuc+5a34U8fZ9YYywxy8)pm(vQ(4=xOG|XdqPoo%CG;WQhaM=u~7b~SWD=ag>#~R zi$m;)R+g`pZoDVGf7No||FjwgT)$9y?Lqn7yJECd1J&QL$#VDh4|SjTRcD{XZTF_W z!J*C*L$4k;kDci3>h{04sqdFy>VMJO*)MqK<=?D0i3bhdImF=E|SFD;s2g zwDWkcoOZQ1UzvZuc3Q5JR~AZd+=dV+I_-As+t;~x zAFz1Hl5~8{P1*KTOsTnwtq!@V_JGZl<4o~0ak-J_7MciK9Km~p6>cQtzwD>b6~q0p z-G0C{sgp2G_A)g20UiNCV&9*Qu2=6(>M?UO;0VVW5$ZNo_6cLZ=8GwGpJ znoM}U;(E;2MpKT(-IZx&G7dyu@Q=rZVb5{l7x}E}h~uQh9{>@EOJoJS;&k|8Yuu4= tO#JqJ<51e6*_8b=h=^pMrDH<@hXfFXh^k1m3>;A+dPHw-+S3|+=6`}3ZJPi9 diff --git a/utils/__pycache__/image_queue.cpython-310.pyc b/utils/__pycache__/image_queue.cpython-310.pyc deleted file mode 100755 index 09a11bcd58751096fdf24ed7f9ff754a6c070102..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1602 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 diff --git a/utils/__pycache__/service_base.cpython-310.pyc b/utils/__pycache__/service_base.cpython-310.pyc deleted file mode 100755 index 9c677488bdb1f04836de60a3cd7119dc123cbe4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4136 zcmbssYj0df_0HVqzU;NvO`1}YrL@38oAM|EMNze_n?9tlt#BIJRnX;TXY5|*?xS<> zlGs|K#7;_s>b9T)qE1MRnnJ3iZY9)4jRQ#h0KV{PzLNFYpZXzRP+B6+nY*?(wkr_a z)jju|GiT<^oH?(pXEI3*o*yO7`F>i{{((gAV*pWvH(Uh3w6ewsqX8)s^`&JBUp>&P zM%f@ZW&~!{DqB^%Y*(GKQ%#f;icf=NImsPn&X9778&7D=V)jXm*)tS4X~l6^0yqi9 z$$&(XrGQTHz8SsT4|JMkfX?uKptC^tv3{WY6+HlSmJI+sFhk3OKn=1SP&uG-jE-o9 zq2^vVLUQTMZ2M>P?Q-oKiEAb9Z~P&-0`s*}fye~&BCis7VOTJv{zz>?I>TNNc!vWn?E@1He$W%rdAbq#^_mw* za-f1UdmkN$BD~=@0dNh>sg>!oV8F7@4Q?{JS7UnF;x^z0;AYuTxCOWkhjC=;`#cg8 z!}Z#zKemF)$yC)l<_h5YJRAcCK1G>4?1kKAJn$yE%!i9Ifuf36DkP-ix;3xLT~{Vu zw_0b-0P(czzS#7FctoI=NZqeRvfp*RTCE;=c)HMaMGA+^(V*@{0$fPDsEHhW6u5cc zV|xxA;G*i+Jh1Vh-G`cyAB2a(*w8L+Zg*osI543P-W!M{wKPqWEK%J5*>q^e*mSls z>ALAM2mC6pH>22iU8|IeaOtVw#=hqt^J~p#Vd>>-?=CO=Zt24h+ovu-s%l?;9dg#nnd9wuf7^NW zy}av(ZsdhW+)BOL2zbQrUuTVae!v+p#(3m%bOpD{!_XV!(h@vu1`&Rvrl?gYXj**` zM+X~*_XZv_(x%BpQo2ZFu2henLOoSpi#Stuy-1}I@?ccl1EM__h`uZbHtp{LToqLq zWO8TkX?JfD{mfm7dr{SW2-Gco1+jIXRhs+PmW$2sAj*6Vz~tRqYmLSJFP(#%E&Yu( zwYzRtyXj6!h2(~K6rab*Isj=LuGa(cRiy7nS`Q;3(3CyLRt8WR1fvCy8e+o6P#q+L zbQ=}O-{iNllYe;lS4iB+`TF)z6fF!jPun8ErQ|xS9n!Ra)LzK zxa#p{$rR$WrH$+3hJq&3XXz9Lt_9Yk%$UXg%4}jRwqKrWU;QZW`Sll~sFAgY(txeAo|h`YG?)!Wzy zav>IUdOS@HV&U&rpE0?s*S1^CgA-=r)C}nw|D~9T1z%~4GDPh>i!0A z_;&y&!1PmQ1Wq@fLZNJOv%&liCk73R!yuZZOg# zW0X$ZOMoWYG;+)dxaldIXp;}M>?spgw9ea1Z$W9=uFYx8Xi

%bwHDTJwZxEi2Y~ zL=(?Pj=~enYFRmLDBe$UhE6$A>U_H8%y)M{U=Pp3UZ(7y*e|By?@@A8Yncr{%0QD( zrb)qx1NzF_D?goGUif9_&67)~f4@BcN@)dc&_o~XT)Nc6u4(DgeEYq#Ak=>A{pCMi zn5291D_A(1Xr-ky?{v;xSb5_&%L@yIK4}WC2GOG;1QVKS6GR>`nb>!%!c`Y8_8@H^ z^+XMWPltX~^{uL51u#HugGj+%z-Mco1xtft^aM8co+lv1jcb_fS_E#K;*H0h zWAn=}ymaMM=k=Fjt6#r*75*tf?8c2p`?ZDTw_oba{R*PDiQy2-#!`For2>tO3)EUi?ha7~mLpHNC~ z0rfA-pr2Z1@{?>I%~+o%kqaDZC2wxqq2?Ec;>!MAT<~cCP%l^iOY%_QbxA9lXn>Q( zTT+|Dq9xQx)Yfez*Uz*cNo>d0Jztgk*hE{LL^^xpe|ZmM;Dvbr261!;yzWlo5QkD7 RJkiRMtd%vhW}i8j{5N}!0|5X4 diff --git a/utils/__pycache__/wechat_chat_log.cpython-310.pyc b/utils/__pycache__/wechat_chat_log.cpython-310.pyc deleted file mode 100755 index 037e15ede2aac8fd584cbce8e3c693ee95c3fb6a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4304 zcma)9?Qa~#9p0JU+uJ*z&+qRhxd4WoOF|Hcrco3KAyQCFXbC9FHS{=c*7n(VyT|Mv zj;%dp;{@CkCqWT}hJ@H{LJ3k6S|MVHMO5*n;xDN7LqCA;Vt-1%RZUyyGqY#Mq)>HF z^SgO}edc+7W7pS56?|X(a4xr@Sy8?ciM3xn5|1J{e}#EgVM}xMVbd@pX4H%h&@Ls2nRNqdmm;CRx@vV6bM^g0iMaE8D=@P_j~^9q|r? zPV^jOU920mnpqF)J*=c!*d1&g{#zN{rzGzz{Q`@ORxbUfdS<3_`IDu~XRF8FU!It( zOn&j1iQ*N#YwU*g`AafZGN!i=JL+LQ8PP~ansV| z?ZM5(F+Y|@Kj~5Pg(2G>X+%pW2199#G?N%TMxs=n&D+z-LzioS}8Bq?t~ITvl^>H`x; z(vPHFUb3>lOBa%IaT?XIG_g31@OI=bi{AaZY{_x$g2~f4=IfbkR{l#oSy{2Pl}|%t z6+~jG$v7mrU+t1Q<{h%I69> z7yA`wFKk{p^E7*b_h4WyjyZ{Q5OJ|JyjvJqBmlH#3p*u5zGIBLP;V73jo48`z-66i zEqAnjbw{mC!SrLR$$~TJN4QzckEKO4I%wO>NsCHZf#H>}7ZJg*pCdT$0b!HGRi>1( z?&*#pur>Y|1B2#CIqZ>QBU3$EY+>pEEgN1~A}%8CtY^%Ta@33R9bWXHTCOX{%Jp7d zaU<%h#UC(rgrX!?+=8@Le6W^|c=eqM(?%4&V?US~_*9EKWsS#SBLgb1Y;0HdD^^5u z#J=Ew4=5HHRosxLvCtGPYpy;Uo>OKGreh9q%rDEruZ0u}kkd&Le5I^EI%|=)~dJM7n6n#fIOXmncCUR8~bE6V$4XklSEjN43k1Nmh zm0P?PuvpU^Va-_GyUef%Ybm#)7m?pOM~c5=>TKPd!rCy)Hm{A(iypmJjNR_FVHDZ- zizj6+k-1v&Ppo65gmuowJoH~~_u6OcSr=j*ZrtmbBCH#?`%A9_E9(&}8*YGZ^s+l< zC|lQ|l-tLjbsLA9SOZ%>LmpC|z~1grPH!)FdY!|~o(^@|;I-!nyYmcXcg@hCyxiq= z&9;C+y1j19|8A^{j?fc?N39mOmGybuVqd1P8{(`qu=bQ1v z>*pXof=No^UIjB*7G))&Fa7<0J9qM8Vq8sliE-NBU#gRtl{a6loSf|MPb~iwY2E>o zB$6Kd2+M&71i$z+XRUU6W(J~QI!oG&4rZfCg(PHN)fb{QCFc)|lsaOL@vS1J2^~u{Ni|zb!>PE;TIJ$YSf*Xar>>LIoFTjDYm&X8 zCYA}eBhUe#6nu@_dDB<1{d|iY4a@TNY;Ee?bkG!zTE-{l?W)`&JhZ?Macy`XLY?kI zAC3h>C-gcE+DxedjW$RW@hC|^Uv$z9i;{1mG>(#1(h4naM`>I&@ZX8DRzfE_X_Q7$ zvzt)lqCVoWuMG|E3~8k8f2ZMx{?QoiCB_8w>Sq`-i?I5I5L=a zg49(8DlWr;_dt+mX_<~c>}tay2I^l!ZQW(a%&-o3M`vM=g4zsFTV#dWzKgP~x)oY- z9$8CDZkR<^NKU$@#ux)NX_A`4kPhuOYSLboE*Pi@F-c9al0Z}S^6|>~i`7#X;ZAJ5 z{z}c`7W4q${lw+U(f0$_Jn-G&xWjATJ09;lu&J-GsgETBjuE~>fB%8zasdX(>hQvY`}_|{})wMy+$ zCnNI4%6loV02l5S7d}6KM3_f~*(r?R!(@m*CgQt=5oqR53L^>dHg~Ai!JSSQY;NVO z!L;LMxLYdPsO{Vh1MmWp8i@mxx4;+wdgC|oP@L2t_cSVg3vz-lMfe=Sc^*bUjuCO# zjFy#%5)#4brkqLN^GabohdbCVxH5#+8h_^XMZaA%WkemISXW;UJX z&mzqQM+Ep1r~;A8Hz*h97)XT1a#`080Uj8)Mbrrm;I-=d4e4~ovTRp+>JIu7Pb^;r z!Amg#Tj#+0Lb)V6$-R&hTf?Jr!Sab?Y%kbiX*0i