This commit is contained in:
renzhiyuan 2026-09-27 02:35:05 +08:00
parent 4280442a76
commit f9b78eefea
16 changed files with 406 additions and 695 deletions

View File

@ -3,50 +3,6 @@ server:
port: 8090
host: "0.0.0.0"
ollama:
base_url: "http://172.17.0.1:11434"
# model: "qwen3:8b"
# generate_model: "qwen3:8b"
# mapping_model: "qwen3:8b"
model: "qwen3-coder:480b-cloud"
generate_model: "qwen3-coder:480b-cloud"
mapping_model: "deepseek-v3.2:cloud"
vl_model: "qwen2.5vl:3b"
timeout: "120s"
level: "info"
format: "json"
vllm:
base_url: "http://172.17.0.1:8001/v1"
vl_model: "qwen2.5-vl-3b-awq"
timeout: "120s"
level: "info"
coze:
base_url: "https://api.coze.cn"
lsxd:
# 统一登录
login_url: "https://api.user.1688sup.com/v1/login/phone"
phone: "ORlviZN7N06W2+WKLe76xg=="
password: "V5Uh8C4bamEM6UQZh4TCeQ=="
code: "456789"
check_token_url: "https://api.user.1688sup.com/v1/user/welcome"
sys:
session_len: 6
channel_pool_len: 100
channel_pool_size: 32
llm_pool_len: 5
heartbeat_interval: 300
key: report-api
pollSize: 5 #连接池大小,不配置,或配置为0表示不启用连接池
minIdleConns: 2 #最小空闲连接数
maxIdleTime: 30 #每个连接最大空闲时间,如果超过了这个时间会被关闭
tls: 30
db:
# 数字销售(AI 客户自动运营)
advicer:
# 上游个人微信协议服务 Token(后端主动发送消息/查询联系人时使用;可留空)
@ -64,19 +20,21 @@ advicer:
auto_reply: false
# 每日客户等级评估执行小时(0=凌晨0点)
daily_evaluate_hour: 0
redis:
host: 47.97.27.195:6379
type: node
pass: lansexiongdi@666
key: ai_scheduler_prov
pollSize: 5 #连接池大小,不配置,或配置为0表示不启用连接池
minIdleConns: 2 #最小空闲连接数
maxIdleTime: 30 #每个连接最大空闲时间,如果超过了这个时间会被关闭
poolSize: 5
maxIdle: 2
maxIdleTime: 30
tls: 30
db:
db: 0
db:
driver: mysql
source: root:SD###sdf323r343@tcp(121.199.38.107:3306)/sys_ai?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai
mongo:
source: mongodb://root:lsxd2026123@192.168.6.115:27017
dataBase: ai_scheduler
@ -85,6 +43,7 @@ mongo:
maxConnIdleTime: 30
connectTimeout: 10
socketTimeout: 30
oss:
access_key: "LTAI5tGGZzjf3tvqWk8SQj2G"
secret_key: "S0NKOAUaYWoK4EGSxrMFmYDzllhvpq"
@ -92,126 +51,4 @@ oss:
domain: "https://attachment-public.oss-cn-hangzhou.aliyuncs.com"
endpoint: "https://oss-cn-hangzhou.aliyuncs.com"
tools:
zltxOrderDetail:
enabled: true
base_url: "https://revcl.1688sup.com/api/admin/direct/ai/%s"
add_url: "https://revcl.1688sup.com/api/admin/direct/log/%s/%s"
api_key: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ1c2VyQ2VudGVyIiwiZXhwIjoxNzU4MDkxOTU4LCJuYmYiOjE3NTgwOTAxNTgsImp0aSI6IjEiLCJQaG9uZSI6IjE4MDAwMDAwMDAwIiwiVXNlck5hbWUiOiJsc3hkIiwiUmVhbE5hbWUiOiLotoXnuqfnrqHnkIblkZgiLCJBY2NvdW50VHlwZSI6MSwiR3JvdXBDb2RlcyI6IlZDTF9DQVNISUVSLFZDTF9PUEVSQVRFLFZDTF9BRE1JTixWQ0xfQUFBLFZDTF9WQ0xfT1BFUkFULFZDTF9JTlZPSUNFLENSTV9BRE1JTixMSUFOTElBTl9BRE1JTixNQVJLRVRNQUcyX0FETUlOLFBIT05FQklMTF9BRE1JTixRSUFOWkhVX1NVUFBFUl9BRE0sTUFSS0VUSU5HU0FBU19TVVBFUkFETUlOLENBUkRfQ09ERSxDQVJEX1BST0NVUkVNRU5ULE1BUktFVElOR1NZU1RFTV9TVVBFUixTVEFUSVNUSUNBTFNZU1RFTV9BRE1JTixaTFRYX0FETUlOLFpMVFhfT1BFUkFURSIsIkRpbmdVc2VySWQiOiIxNjIwMjYxMjMwMjg5MzM4MzQifQ.Bjsx9f8yfcrV9EWxb0n6POwnXVOq9XPRD78JFZnnf1_VAVMN78W4W570SZL27PWuDnkD7E4oUg6RzeZwZgl7BZrNpNr-a-QpNC5qCptqrqXeNfVStmX7pxWA8GqnzI8ybkZgbhQ58Gje7DzdJtBq_8zte_LDaYhTYXdIc5EAG0AbCzAk22nPTl47nkMeHtmisXQVLEsdibl1hW3ViFJlXwfXvUrOENItmL1_mRYkggUB0MaTu2nHJOYM6PaOVGLHx-74eepnmK2rm6konFEb6ed-Ukc6gVR-nM9yWZaYLYNGNKJLwZoCX3tRuerq74n4kzQgWmUEJeaVI1yIGSw1zw"
zltxProduct:
enabled: true
base_url: "https://revcl.1688sup.com/api/admin/oursProduct"
add_url: "https://revcl.1688sup.com/api/admin/platformProduct/getProductsByOfficialProductId"
api_key: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ1c2VyQ2VudGVyIiwiZXhwIjoxNzU2MTgyNTM1LCJuYmYiOjE3NTYxODA3MzUsImp0aSI6IjEiLCJQaG9uZSI6IjE4MDAwMDAwMDAwIiwiVXNlck5hbWUiOiJsc3hkIiwiUmVhbE5hbWUiOiLotoXnuqfnrqHnkIblkZgiLCJBY2NvdW50VHlwZSI6MSwiR3JvdXBDb2RlcyI6IlZDTF9DQVNISUVSLFZDTF9PUEVSQVRFLFZDTF9BRE1JTixWQ0xfQUFBLFZDTF9WQ0xfT1BFUkFULFZDTF9JTlZPSUNFLENSTV9BRE1JTixMSUFOTElBTl9BRE1JTixNQVJLRVRNQUcyX0FETUlOLFBIT05FQklMTF9BRE1JTixRSUFOWkhVX1NVUFBFUl9BRE0sTUFSS0VUSU5HU0FBU19TVVBFUkFETUlOLENBUkRfQ09ERSxDQVJEX1BST0NVUkVNRU5ULE1BUktFVElOR1NZU1RFTV9TVVBFUixTVEFUSVNUSUNBTFNZU1RFTV9BRE1JTixaTFRYX0FETUlOLFpMVFhfT1BFUkFURSIsIkRpbmdVc2VySWQiOiIxNjIwMjYxMjMwMjg5MzM4MzQifQ.N1xv1PYbcO8_jR5adaczc16YzGsr4z101gwEZdulkRaREBJNYTOnFrvRxTFx3RJTooXsqTqroE1MR84v_1WPX6BS6kKonA-kC1Jgot6yrt5rFWhGNGb2Cpr9rKIFCCQYmiGd3AUgDazEeaQ0_sodv3E-EXg9VfE1SX8nMcck9Yjnc8NCy7RTWaBIaSeOdZcEl-JfCD0S6GSx3oErp_hk-U9FKGwf60wAuDGTY1R0BP4BYpcEqS-C2LSnsSGyURi54Cuk5xH8r1WuF0Dm5bwAj5d7Hvs77-N_sUF-C5ONqyZJRAEhYLgcmN9RX_WQZfizdQJxizlTczdpzYfy-v-1eQ"
zltxOrderStatistics:
base_url: "https://revcl.1688sup.com/api/admin/direct/ai/search/"
enabled: true
api_key: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ1c2VyQ2VudGVyIiwiZXhwIjoxNzU2MTgyNTM1LCJuYmYiOjE3NTYxODA3MzUsImp0aSI6IjEiLCJQaG9uZSI6IjE4MDAwMDAwMDAwIiwiVXNlck5hbWUiOiJsc3hkIiwiUmVhbE5hbWUiOiLotoXnuqfnrqHnkIblkZgiLCJBY2NvdW50VHlwZSI6MSwiR3JvdXBDb2RlcyI6IlZDTF9DQVNISUVSLFZDTF9PUEVSQVRFLFZDTF9BRE1JTixWQ0xfQUFBLFZDTF9WQ0xfT1BFUkFULFZDTF9JTlZPSUNFLENSTV9BRE1JTixMSUFOTElBTl9BRE1JTixNQVJLRVRNQUcyX0FETUlOLFBIT05FQklMTF9BRE1JTixRSUFOWkhVX1NVUFBFUl9BRE0sTUFSS0VUSU5HU0FBU19TVVBFUkFETUlOLENBUkRfQ09ERSxDQVJEX1BST0NVUkVNRU5ULE1BUktFVElOR1NZU1RFTV9TVVBFUixTVEFUSVNUSUNBTFNZU1RFTV9BRE1JTixaTFRYX0FETUlOLFpMVFhfT1BFUkFURSIsIkRpbmdVc2VySWQiOiIxNjIwMjYxMjMwMjg5MzM4MzQifQ.N1xv1PYbcO8_jR5adaczc16YzGsr4z101gwEZdulkRaREBJNYTOnFrvRxTFx3RJTooXsqTqroE1MR84v_1WPX6BS6kKonA-kC1Jgot6yrt5rFWhGNGb2Cpr9rKIFCCQYmiGd3AUgDazEeaQ0_sodv3E-EXg9VfE1SX8nMcck9Yjnc8NCy7RTWaBIaSeOdZcEl-JfCD0S6GSx3oErp_hk-U9FKGwf60wAuDGTY1R0BP4BYpcEqS-C2LSnsSGyURi54Cuk5xH8r1WuF0Dm5bwAj5d7Hvs77-N_sUF-C5ONqyZJRAEhYLgcmN9RX_WQZfizdQJxizlTczdpzYfy-v-1eQ"
knowledge:
base_url: "http://117.175.169.61:10000"
enabled: true
DingTalkBot:
enabled: true
api_key: "dingsbbntrkeiyazcfdg"
api_secret: "ObqxwyR20r9rVNhju0sCPQyQA98_FZSc32W4vgxnGFH_b02HZr1BPCJsOAF816nu"
zltxOrderAfterSaleSupplier:
enabled: true
base_url: "https://revcl.1688sup.com/api/admin/afterSales/directs"
zltxOrderAfterSaleReseller:
enabled: true
base_url: "https://revcl.1688sup.com/api/admin/afterSales/reseller_pre_ai"
zltxOrderAfterSaleResellerBatch:
enabled: true
base_url: "https://revcl.1688sup.com/api/admin/afterSales/reseller_pre_ai"
weather:
enabled: true
base_url: "https://restapi.amap.com/v3/weather/weatherInfo"
api_key: "12afbde5ab78cb7e575ff76bd0bdef2b"
cozeExpress:
enabled: true
base_url: "https://api.coze.cn"
api_key: "7582477438102552616"
api_secret: "pat_eEN0BdLNDughEtABjJJRYTW71olvDU0qUbfQUeaPc2NnYWO8HeyNoui5aR9z0sSZ"
cozeCompany:
enabled: true
base_url: "https://api.coze.cn"
api_key: "7583905168607100978"
api_secret: "pat_eEN0BdLNDughEtABjJJRYTW71olvDU0qUbfQUeaPc2NnYWO8HeyNoui5aR9z0sSZ"
zltxResellerAuthProductToManagerAndDefaultLossReason:
base_url: "https://revcl.1688sup.com/api/admin/reseller/resellerAuthProduct/getManagerAndDefaultLossReason"
# eino tool 配置
eino_tools:
# 货易通商品上传
hytProductUpload:
base_url: "https://hyt.86698.cn/admin_upload/api/v1/goods/supplier/batch/add/complete"
add_url: "https://hyt.86698.cn/#/goods/goodsManage"
# 货易通供应商查询
hytSupplierSearch:
base_url: "https://hyt.86698.cn/admin_upload/api/v1/supplier/list"
# 货易通仓库查询
hytWarehouseSearch:
base_url: "https://hyt.86698.cn/admin_upload/api/v1/warehouse/list"
# 货易通商品添加
hytGoodsAdd:
base_url: "https://hyt.86698.cn/admin_upload/api/v1/goods/add"
add_url: "https://hyt.86698.cn/#/goods/goodsManage"
# 货易通商品图片添加
hytGoodsMediaAdd:
base_url: "https://hyt.86698.cn/admin_upload/api/v1/media/add/batch"
# 货易通商品分类添加
hytGoodsCategoryAdd:
base_url: "https://hyt.86698.cn/admin_upload/api/v1/good/category/relation/add"
# 货易通商品分类查询
hytGoodsCategorySearch:
base_url: "https://hyt.86698.cn/admin_upload/api/v1/goods/category/list"
# 货易通商品品牌查询
hytGoodsBrandSearch:
base_url: "https://hyt.86698.cn/admin_upload/api/v1/goods/brand/list"
# == 电商充值系统 ==
# 我们的商品统计
rechargeStatisticsOursProduct:
base_url: "http://admin.lanseds.cn/admin/statistics/oursProduct"
# == 通用工具 ==
# 表格转图片
excel2pic:
base_url: "http://excel2pic:8000/api/v1/convert"
dingtalk:
api_key: "dingsbbntrkeiyazcfdg"
api_secret: "ObqxwyR20r9rVNhju0sCPQyQA98_FZSc32W4vgxnGFH_b02HZr1BPCJsOAF816nu"
table_demand:
url: "https://alidocs.dingtalk.com/i/nodes/2Amq4vjg89RnYx9DTp66m2orW3kdP0wQ"
base_id: "2Amq4vjg89RnYx9DTp66m2orW3kdP0wQ"
sheet_id_or_name: "数据表"
# 机器人群组
bot_group_id:
bbxt: 29
qywx:
corp_id: "ww48151f694fb8ec67"
app_secret: "uYqtdwdtdH4Uv_P4is2AChuGzBCoB6cQDyRvpbW0Vmk"
token: "zJdukry6"
aes_key: "4VLH47qRGUogc2d3QLWuUhvJlk8Y0YuRjXzeBquBq8B"
init_account: "les.,FuZhongYun"
chat_id_len: 16
default_config_id: 1
bot_group_id:
bbxt: 37
default_prompt:
img_recognize:
system_prompt:
'你是一个具备图像理解与用户意图分析能力的智能助手。当用户提供一张图片时,请完成以下任务:
1. 关键信息提取:
提取出图片中对用户可能有用的关键信息(例如金额、日期、标题、编号、联系信息、商品名称等)。
若图片为文档类(如合同、发票、收据),请结构化输出关键字段(如客户名称、金额、开票日期等)。
'
user_prompt: '识别图片内容'
# 权限配置
permissionConfig:
permission_url: "https://api.user.1688sup.com/v1/menu/myCodes?systemId="
jwt_secret: "lsxd20260918"
jwt_secret: "lsxd20260918"

View File

@ -3,44 +3,6 @@ server:
port: 8090
host: "0.0.0.0"
ollama:
base_url: "http://192.168.6.115:11434"
model: "qwen3:8b"
generate_model: "qwen3:8b"
mapping_model: "qwen3:8b"
# model: "qwen3-coder:480b-cloud"
# generate_model: "qwen3-coder:480b-cloud"
# mapping_model: "deepseek-v3.2:cloud"
vl_model: "qwen2.5vl:7b"
timeout: "120s"
level: "info"
format: "json"
vllm:
base_url: "http://117.175.169.61:16001/v1"
vl_model: "qwen2.5-vl-3b-awq"
timeout: "120s"
level: "info"
coze:
base_url: "https://api.coze.cn"
api_secret: "sat_AqvFcdNgesP8megy1ItTscWFXRcsHRzmM4NJ1KNavfcdT0EPwYuCPkDqGhItpx13"
lsxd:
# 统一登录
login_url: "https://api.user.1688sup.com/v1/login/phone"
phone: "ORlviZN7N06W2+WKLe76xg=="
password: "V5Uh8C4bamEM6UQZh4TCeQ=="
check_token_url: "https://api.user.1688sup.com/v1/user/welcome"
code: "456789"
sys:
session_len: 6
channel_pool_len: 100
channel_pool_size: 32
llm_pool_len: 5
heartbeat_interval: 30
# 数字销售(AI 客户自动运营)
advicer:
# 上游个人微信协议服务 Token(后端主动发送消息/查询联系人时使用;可留空)
@ -58,19 +20,21 @@ advicer:
auto_reply: false
# 每日客户等级评估执行小时(0=凌晨0点)
daily_evaluate_hour: 0
redis:
host: 47.97.27.195:6379
type: node
pass: lansexiongdi@666
key: report-api-test
pollSize: 5 #连接池大小,不配置,或配置为0表示不启用连接池
minIdleConns: 2 #最小空闲连接数
maxIdleTime: 30 #每个连接最大空闲时间,如果超过了这个时间会被关闭
poolSize: 5
maxIdle: 2
maxIdleTime: 30
tls: 30
db:
db: 0
db:
driver: mysql
source: root:SD###sdf323r343@tcp(121.199.38.107:3306)/sys_ai_test?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai
mongo:
source: mongodb://root:lsxd2026123@192.168.6.115:27017
dataBase: ai_scheduler_test
@ -79,6 +43,7 @@ mongo:
maxConnIdleTime: 30
connectTimeout: 10
socketTimeout: 30
oss:
access_key: "LTAI5tGGZzjf3tvqWk8SQj2G"
secret_key: "S0NKOAUaYWoK4EGSxrMFmYDzllhvpq"
@ -86,163 +51,4 @@ oss:
domain: "https://attachment-public.oss-cn-hangzhou.aliyuncs.com"
endpoint: "https://oss-cn-hangzhou.aliyuncs.com"
tools:
zltxOrderDetail:
enabled: true
base_url: "https://gateway.dev.cdlsxd.cn/zltx_api/admin/direct/ai/%s"
add_url: "https://gateway.dev.cdlsxd.cn/zltx_api/admin/direct/log/%s/%s"
api_key: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ1c2VyQ2VudGVyIiwiZXhwIjoxNzU4MDkxOTU4LCJuYmYiOjE3NTgwOTAxNTgsImp0aSI6IjEiLCJQaG9uZSI6IjE4MDAwMDAwMDAwIiwiVXNlck5hbWUiOiJsc3hkIiwiUmVhbE5hbWUiOiLotoXnuqfnrqHnkIblkZgiLCJBY2NvdW50VHlwZSI6MSwiR3JvdXBDb2RlcyI6IlZDTF9DQVNISUVSLFZDTF9PUEVSQVRFLFZDTF9BRE1JTixWQ0xfQUFBLFZDTF9WQ0xfT1BFUkFULFZDTF9JTlZPSUNFLENSTV9BRE1JTixMSUFOTElBTl9BRE1JTixNQVJLRVRNQUcyX0FETUlOLFBIT05FQklMTF9BRE1JTixRSUFOWkhVX1NVUFBFUl9BRE0sTUFSS0VUSU5HU0FBU19TVVBFUkFETUlOLENBUkRfQ09ERSxDQVJEX1BST0NVUkVNRU5ULE1BUktFVElOR1NZU1RFTV9TVVBFUixTVEFUSVNUSUNBTFNZU1RFTV9BRE1JTixaTFRYX0FETUlOLFpMVFhfT1BFUkFURSIsIkRpbmdVc2VySWQiOiIxNjIwMjYxMjMwMjg5MzM4MzQifQ.Bjsx9f8yfcrV9EWxb0n6POwnXVOq9XPRD78JFZnnf1_VAVMN78W4W570SZL27PWuDnkD7E4oUg6RzeZwZgl7BZrNpNr-a-QpNC5qCptqrqXeNfVStmX7pxWA8GqnzI8ybkZgbhQ58Gje7DzdJtBq_8zte_LDaYhTYXdIc5EAG0AbCzAk22nPTl47nkMeHtmisXQVLEsdibl1hW3ViFJlXwfXvUrOENItmL1_mRYkggUB0MaTu2nHJOYM6PaOVGLHx-74eepnmK2rm6konFEb6ed-Ukc6gVR-nM9yWZaYLYNGNKJLwZoCX3tRuerq74n4kzQgWmUEJeaVI1yIGSw1zw"
zltxProduct:
enabled: true
base_url: "https://gateway.dev.cdlsxd.cn/zltx_api/admin/oursProduct"
add_url: "https://gateway.dev.cdlsxd.cn/zltx_api/admin/platformProduct/getProductsByOfficialProductId"
api_key: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ1c2VyQ2VudGVyIiwiZXhwIjoxNzU2MTgyNTM1LCJuYmYiOjE3NTYxODA3MzUsImp0aSI6IjEiLCJQaG9uZSI6IjE4MDAwMDAwMDAwIiwiVXNlck5hbWUiOiJsc3hkIiwiUmVhbE5hbWUiOiLotoXnuqfnrqHnkIblkZgiLCJBY2NvdW50VHlwZSI6MSwiR3JvdXBDb2RlcyI6IlZDTF9DQVNISUVSLFZDTF9PUEVSQVRFLFZDTF9BRE1JTixWQ0xfQUFBLFZDTF9WQ0xfT1BFUkFULFZDTF9JTlZPSUNFLENSTV9BRE1JTixMSUFOTElBTl9BRE1JTixNQVJLRVRNQUcyX0FETUlOLFBIT05FQklMTF9BRE1JTixRSUFOWkhVX1NVUFBFUl9BRE0sTUFSS0VUSU5HU0FBU19TVVBFUkFETUlOLENBUkRfQ09ERSxDQVJEX1BST0NVUkVNRU5ULE1BUktFVElOR1NZU1RFTV9TVVBFUixTVEFUSVNUSUNBTFNZU1RFTV9BRE1JTixaTFRYX0FETUlOLFpMVFhfT1BFUkFURSIsIkRpbmdVc2VySWQiOiIxNjIwMjYxMjMwMjg5MzM4MzQifQ.N1xv1PYbcO8_jR5adaczc16YzGsr4z101gwEZdulkRaREBJNYTOnFrvRxTFx3RJTooXsqTqroE1MR84v_1WPX6BS6kKonA-kC1Jgot6yrt5rFWhGNGb2Cpr9rKIFCCQYmiGd3AUgDazEeaQ0_sodv3E-EXg9VfE1SX8nMcck9Yjnc8NCy7RTWaBIaSeOdZcEl-JfCD0S6GSx3oErp_hk-U9FKGwf60wAuDGTY1R0BP4BYpcEqS-C2LSnsSGyURi54Cuk5xH8r1WuF0Dm5bwAj5d7Hvs77-N_sUF-C5ONqyZJRAEhYLgcmN9RX_WQZfizdQJxizlTczdpzYfy-v-1eQ"
zltxOrderStatistics:
base_url: "https://gateway.dev.cdlsxd.cn/zltx_api/admin/direct/ai/search/"
enabled: true
api_key: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ1c2VyQ2VudGVyIiwiZXhwIjoxNzU2MTgyNTM1LCJuYmYiOjE3NTYxODA3MzUsImp0aSI6IjEiLCJQaG9uZSI6IjE4MDAwMDAwMDAwIiwiVXNlck5hbWUiOiJsc3hkIiwiUmVhbE5hbWUiOiLotoXnuqfnrqHnkIblkZgiLCJBY2NvdW50VHlwZSI6MSwiR3JvdXBDb2RlcyI6IlZDTF9DQVNISUVSLFZDTF9PUEVSQVRFLFZDTF9BRE1JTixWQ0xfQUFBLFZDTF9WQ0xfT1BFUkFULFZDTF9JTlZPSUNFLENSTV9BRE1JTixMSUFOTElBTl9BRE1JTixNQVJLRVRNQUcyX0FETUlOLFBIT05FQklMTF9BRE1JTixRSUFOWkhVX1NVUFBFUl9BRE0sTUFSS0VUSU5HU0FBU19TVVBFUkFETUlOLENBUkRfQ09ERSxDQVJEX1BST0NVUkVNRU5ULE1BUktFVElOR1NZU1RFTV9TVVBFUixTVEFUSVNUSUNBTFNZU1RFTV9BRE1JTixaTFRYX0FETUlOLFpMVFhfT1BFUkFURSIsIkRpbmdVc2VySWQiOiIxNjIwMjYxMjMwMjg5MzM4MzQifQ.N1xv1PYbcO8_jR5adaczc16YzGsr4z101gwEZdulkRaREBJNYTOnFrvRxTFx3RJTooXsqTqroE1MR84v_1WPX6BS6kKonA-kC1Jgot6yrt5rFWhGNGb2Cpr9rKIFCCQYmiGd3AUgDazEeaQ0_sodv3E-EXg9VfE1SX8nMcck9Yjnc8NCy7RTWaBIaSeOdZcEl-JfCD0S6GSx3oErp_hk-U9FKGwf60wAuDGTY1R0BP4BYpcEqS-C2LSnsSGyURi54Cuk5xH8r1WuF0Dm5bwAj5d7Hvs77-N_sUF-C5ONqyZJRAEhYLgcmN9RX_WQZfizdQJxizlTczdpzYfy-v-1eQ"
knowledge:
base_url: "http://117.175.169.61:10000"
enabled: true
DingTalkBot:
enabled: true
api_key: "dingsbbntrkeiyazcfdg"
api_secret: "ObqxwyR20r9rVNhju0sCPQyQA98_FZSc32W4vgxnGFH_b02HZr1BPCJsOAF816nu"
zltxOrderAfterSaleSupplier:
enabled: true
base_url: "https://gateway.dev.cdlsxd.cn/zltx_api/admin/afterSales/directs"
zltxOrderAfterSaleReseller:
enabled: true
base_url: "https://gateway.dev.cdlsxd.cn/zltx_api/admin/afterSales/reseller_pre_ai"
zltxOrderAfterSaleResellerBatch:
enabled: true
base_url: "https://gateway.dev.cdlsxd.cn/zltx_api/admin/afterSales/reseller_pre_ai"
weather:
enabled: true
base_url: "https://restapi.amap.com/v3/weather/weatherInfo"
api_key: "12afbde5ab78cb7e575ff76bd0bdef2b"
cozeExpress:
enabled: true
base_url: "https://api.coze.cn"
api_key: "7582477438102552616"
api_secret: "pat_eEN0BdLNDughEtABjJJRYTW71olvDU0qUbfQUeaPc2NnYWO8HeyNoui5aR9z0sSZ"
cozeCompany:
enabled: true
base_url: "https://api.coze.cn"
api_key: "7583905168607100978"
api_secret: "pat_eEN0BdLNDughEtABjJJRYTW71olvDU0qUbfQUeaPc2NnYWO8HeyNoui5aR9z0sSZ"
zltxResellerAuthProductToManagerAndDefaultLossReason:
base_url: "https://revcl.1688sup.com/api/admin/reseller/resellerAuthProduct/getManagerAndDefaultLossReason"
# eino tool 配置
eino_tools:
# == 货易通 hyt ==
# 货易通商品上传
hytProductUpload:
base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/goods/supplier/batch/add/complete"
add_url: "https://gateway.dev.cdlsxd.cn/sw//#/goods/goodsManage"
# 货易通供应商查询
hytSupplierSearch:
base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/supplier/list"
# 货易通仓库查询
hytWarehouseSearch:
base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/warehouse/list"
# 货易通商品添加
hytGoodsAdd:
base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/goods/add"
add_url: "https://gateway.dev.cdlsxd.cn/sw//#/goods/goodsManage"
# 货易通商品图片添加
hytGoodsMediaAdd:
base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/media/add/batch"
# 货易通商品分类添加
hytGoodsCategoryAdd:
base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/good/category/relation/add"
# 货易通商品分类查询
hytGoodsCategorySearch:
base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/goods/category/list"
# 货易通商品品牌查询
hytGoodsBrandSearch:
base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/goods/brand/list"
# == 报表分析 data analytics ==
# 负利润分析列表
daOursProductLoss:
base_url: "https://reportapi.1688sup.com/api/dataanalytics/statisOursProductLossSum"
# 利润同比排行榜
daProfitRanking:
base_url: "https://reportapi.1688sup.com/api/dataanalytics/profitRankingSum"
# 销售同比分析列表
daOfficialProduct:
base_url: "https://reportapi.1688sup.com/api/dataanalytics/statisOfficialProduct"
# == 电商充值系统 ==
# 我们的商品统计
rechargeStatisticsOursProduct:
base_url: "http://admin.lanseds.cn/admin/statistics/oursProduct"
# == 通用工具 ==
# 表格转图片
excel2pic:
base_url: "http://192.168.6.109:8010/api/v1/convert"
dingtalk:
api_key: "dingsbbntrkeiyazcfdg"
api_secret: "ObqxwyR20r9rVNhju0sCPQyQA98_FZSc32W4vgxnGFH_b02HZr1BPCJsOAF816nu"
table_demand:
url: "https://alidocs.dingtalk.com/i/nodes/YQBnd5ExVE6qAbnOiANQg2KKJyeZqMmz"
base_id: "YQBnd5ExVE6qAbnOiANQg2KKJyeZqMmz"
sheet_id_or_name: "数据表"
# 机器人群组
bot_group_id:
bbxt: 23
# 互动卡片
card:
# 卡片回调路由key - https://gateway.dev.cdlsxd.cn/zltx_api/aitest/api/v1//callback/dingtalk-card
callback_route_key: "gateway.dev.cdlsxd.cn-dingtalk-card"
# 卡片调试工具 [show:展示 hide:隐藏]
debug_tool_entry_show: "hide"
# 卡片模板
template:
# 基础消息卡片(title + content)
base_msg: "291468f8-a048-4132-a37e-a14365e855e9.schema"
# 内容收集卡片(title + textarea + button)
content_collect: "3a447814-6a3e-4a02-b48a-92c57b349d77.schema"
# 创建群聊申请(title + content + button)
create_group_approve: "faad6d5d-726d-467f-a6ba-28c1930aa5f3.schema"
# 场景群
scene_group:
# 问题处理群模板ID
group_template_id_issue_handling: "aa3aa4fe-e709-4491-b24b-c3d5b27e86d0"
# 问题处理群模板机器人ID
group_template_robot_id_issue_handling: "VqgJYpB91j3RnB217690607273471011"
qywx:
corp_id: "ww48151f694fb8ec67"
app_secret: "uYqtdwdtdH4Uv_P4is2AChuGzBCoB6cQDyRvpbW0Vmk"
token: "zJdukry6"
aes_key: "4VLH47qRGUogc2d3QLWuUhvJlk8Y0YuRjXzeBquBq8B"
init_account: "les.,FuZhongYun"
chat_id_len: 16
default_config_id: 1
bot_group_id:
bbxt: 36
default_prompt:
img_recognize:
system_prompt:
'你是一个具备图像理解与用户意图分析能力的智能助手。当用户提供一张图片时,请完成以下任务:
1. 关键信息提取:
提取出图片中对用户可能有用的关键信息(例如金额、日期、标题、编号、联系信息、商品名称等)。
若图片为文档类(如合同、发票、收据),请结构化输出关键字段(如客户名称、金额、开票日期等)。
'
user_prompt: '识别图片内容'
# 权限配置
permissionConfig:
permission_url: "http://api.test.user.1688sup.cn:8001/v1/menu/myCodes?systemId="
# 知识库配置
knowledge_config:
base_url: "http://192.168.6.115:9600"
tenant_id: "default"
mode: "naive"
stream: true
think: false
only_rag: true
jwt_secret: "lsxd20260918"

View File

@ -3,43 +3,6 @@ server:
port: 8090
host: "0.0.0.0"
ollama:
base_url: "http://host.docker.internal:11434"
model: "qwen3-coder:480b-cloud"
generate_model: "qwen3-coder:480b-cloud"
mapping_model: "deepseek-v3.2:cloud"
vl_model: "gemini-3-pro-preview"
timeout: "120s"
level: "info"
format: "json"
vllm:
base_url: "http://host.docker.internal:8001/v1"
vl_model: "qwen2.5-vl-3b-awq"
timeout: "120s"
level: "info"
coze:
base_url: "https://api.coze.cn"
api_secret: "sat_AqvFcdNgesP8megy1ItTscWFXRcsHRzmM4NJ1KNavfcdT0EPwYuCPkDqGhItpx13"
lsxd:
# 统一登录
login_url: "http://api.test.user.1688sup.com/v1/login/phone"
phone: "OFJ8UpqOlI7+w3Qklf36ZA=="
password: "tEbFegH/DRRh6LutFb7o3g=="
code: "123456"
check_token_url: "http://api.test.user.1688sup.com/v1/user/welcome"
sys:
session_len: 6
channel_pool_len: 100
channel_pool_size: 32
llm_pool_len: 5
heartbeat_interval: 30
# 数字销售(AI 客户自动运营)
advicer:
# 上游个人微信协议服务 Token(后端主动发送消息/查询联系人时使用;可留空)
@ -57,21 +20,23 @@ advicer:
auto_reply: false
# 每日客户等级评估执行小时(0=凌晨0点)
daily_evaluate_hour: 0
redis:
host: 47.97.27.195:6379
type: node
pass: lansexiongdi@666
key: ai_scheduler_test
pollSize: 5 #连接池大小,不配置,或配置为0表示不启用连接池
minIdleConns: 2 #最小空闲连接数
maxIdleTime: 30 #每个连接最大空闲时间,如果超过了这个时间会被关闭
poolSize: 5
maxIdle: 2
maxIdleTime: 30
tls: 30
db:
db: 0
db:
driver: mysql
source: root:SD###sdf323r343@tcp(121.199.38.107:3306)/sys_ai_test?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai
mongo:
source: mongodb://root:lsxd2026123@8.147.107.207:27017 #mongodb://root:lsxd2026123@127.0.0.1:27017
source: mongodb://root:lsxd2026123@8.147.107.207:27017
dataBase: ai_scheduler_test
maxPoolSize: 100
minPoolSize: 10
@ -86,205 +51,4 @@ oss:
domain: "https://attachment-public.oss-cn-hangzhou.aliyuncs.com"
endpoint: "https://oss-cn-hangzhou.aliyuncs.com"
tools:
zltxOrderDetail:
enabled: true
base_url: "https://gateway.dev.cdlsxd.cn/zltx_api/admin/direct/ai/%s"
add_url: "https://gateway.dev.cdlsxd.cn/zltx_api/admin/direct/log/%s/%s"
api_key: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ1c2VyQ2VudGVyIiwiZXhwIjoxNzU4MDkxOTU4LCJuYmYiOjE3NTgwOTAxNTgsImp0aSI6IjEiLCJQaG9uZSI6IjE4MDAwMDAwMDAwIiwiVXNlck5hbWUiOiJsc3hkIiwiUmVhbE5hbWUiOiLotoXnuqfnrqHnkIblkZgiLCJBY2NvdW50VHlwZSI6MSwiR3JvdXBDb2RlcyI6IlZDTF9DQVNISUVSLFZDTF9PUEVSQVRFLFZDTF9BRE1JTixWQ0xfQUFBLFZDTF9WQ0xfT1BFUkFULFZDTF9JTlZPSUNFLENSTV9BRE1JTixMSUFOTElBTl9BRE1JTixNQVJLRVRNQUcyX0FETUlOLFBIT05FQklMTF9BRE1JTixRSUFOWkhVX1NVUFBFUl9BRE0sTUFSS0VUSU5HU0FBU19TVVBFUkFETUlOLENBUkRfQ09ERSxDQVJEX1BST0NVUkVNRU5ULE1BUktFVElOR1NZU1RFTV9TVVBFUixTVEFUSVNUSUNBTFNZU1RFTV9BRE1JTixaTFRYX0FETUlOLFpMVFhfT1BFUkFURSIsIkRpbmdVc2VySWQiOiIxNjIwMjYxMjMwMjg5MzM4MzQifQ.Bjsx9f8yfcrV9EWxb0n6POwnXVOq9XPRD78JFZnnf1_VAVMN78W4W570SZL27PWuDnkD7E4oUg6RzeZwZgl7BZrNpNr-a-QpNC5qCptqrqXeNfVStmX7pxWA8GqnzI8ybkZgbhQ58Gje7DzdJtBq_8zte_LDaYhTYXdIc5EAG0AbCzAk22nPTl47nkMeHtmisXQVLEsdibl1hW3ViFJlXwfXvUrOENItmL1_mRYkggUB0MaTu2nHJOYM6PaOVGLHx-74eepnmK2rm6konFEb6ed-Ukc6gVR-nM9yWZaYLYNGNKJLwZoCX3tRuerq74n4kzQgWmUEJeaVI1yIGSw1zw"
zltxProduct:
enabled: true
base_url: "https://gateway.dev.cdlsxd.cn/zltx_api/admin/oursProduct"
add_url: "https://gateway.dev.cdlsxd.cn/zltx_api/admin/platformProduct/getProductsByOfficialProductId"
api_key: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ1c2VyQ2VudGVyIiwiZXhwIjoxNzU2MTgyNTM1LCJuYmYiOjE3NTYxODA3MzUsImp0aSI6IjEiLCJQaG9uZSI6IjE4MDAwMDAwMDAwIiwiVXNlck5hbWUiOiJsc3hkIiwiUmVhbE5hbWUiOiLotoXnuqfnrqHnkIblkZgiLCJBY2NvdW50VHlwZSI6MSwiR3JvdXBDb2RlcyI6IlZDTF9DQVNISUVSLFZDTF9PUEVSQVRFLFZDTF9BRE1JTixWQ0xfQUFBLFZDTF9WQ0xfT1BFUkFULFZDTF9JTlZPSUNFLENSTV9BRE1JTixMSUFOTElBTl9BRE1JTixNQVJLRVRNQUcyX0FETUlOLFBIT05FQklMTF9BRE1JTixRSUFOWkhVX1NVUFBFUl9BRE0sTUFSS0VUSU5HU0FBU19TVVBFUkFETUlOLENBUkRfQ09ERSxDQVJEX1BST0NVUkVNRU5ULE1BUktFVElOR1NZU1RFTV9TVVBFUixTVEFUSVNUSUNBTFNZU1RFTV9BRE1JTixaTFRYX0FETUlOLFpMVFhfT1BFUkFURSIsIkRpbmdVc2VySWQiOiIxNjIwMjYxMjMwMjg5MzM4MzQifQ.N1xv1PYbcO8_jR5adaczc16YzGsr4z101gwEZdulkRaREBJNYTOnFrvRxTFx3RJTooXsqTqroE1MR84v_1WPX6BS6kKonA-kC1Jgot6yrt5rFWhGNGb2Cpr9rKIFCCQYmiGd3AUgDazEeaQ0_sodv3E-EXg9VfE1SX8nMcck9Yjnc8NCy7RTWaBIaSeOdZcEl-JfCD0S6GSx3oErp_hk-U9FKGwf60wAuDGTY1R0BP4BYpcEqS-C2LSnsSGyURi54Cuk5xH8r1WuF0Dm5bwAj5d7Hvs77-N_sUF-C5ONqyZJRAEhYLgcmN9RX_WQZfizdQJxizlTczdpzYfy-v-1eQ"
zltxOrderStatistics:
base_url: "https://gateway.dev.cdlsxd.cn/zltx_api/admin/direct/ai/search/"
enabled: true
api_key: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ1c2VyQ2VudGVyIiwiZXhwIjoxNzU2MTgyNTM1LCJuYmYiOjE3NTYxODA3MzUsImp0aSI6IjEiLCJQaG9uZSI6IjE4MDAwMDAwMDAwIiwiVXNlck5hbWUiOiJsc3hkIiwiUmVhbE5hbWUiOiLotoXnuqfnrqHnkIblkZgiLCJBY2NvdW50VHlwZSI6MSwiR3JvdXBDb2RlcyI6IlZDTF9DQVNISUVSLFZDTF9PUEVSQVRFLFZDTF9BRE1JTixWQ0xfQUFBLFZDTF9WQ0xfT1BFUkFULFZDTF9JTlZPSUNFLENSTV9BRE1JTixMSUFOTElBTl9BRE1JTixNQVJLRVRNQUcyX0FETUlOLFBIT05FQklMTF9BRE1JTixRSUFOWkhVX1NVUFBFUl9BRE0sTUFSS0VUSU5HU0FBU19TVVBFUkFETUlOLENBUkRfQ09ERSxDQVJEX1BST0NVUkVNRU5ULE1BUktFVElOR1NZU1RFTV9TVVBFUixTVEFUSVNUSUNBTFNZU1RFTV9BRE1JTixaTFRYX0FETUlOLFpMVFhfT1BFUkFURSIsIkRpbmdVc2VySWQiOiIxNjIwMjYxMjMwMjg5MzM4MzQifQ.N1xv1PYbcO8_jR5adaczc16YzGsr4z101gwEZdulkRaREBJNYTOnFrvRxTFx3RJTooXsqTqroE1MR84v_1WPX6BS6kKonA-kC1Jgot6yrt5rFWhGNGb2Cpr9rKIFCCQYmiGd3AUgDazEeaQ0_sodv3E-EXg9VfE1SX8nMcck9Yjnc8NCy7RTWaBIaSeOdZcEl-JfCD0S6GSx3oErp_hk-U9FKGwf60wAuDGTY1R0BP4BYpcEqS-C2LSnsSGyURi54Cuk5xH8r1WuF0Dm5bwAj5d7Hvs77-N_sUF-C5ONqyZJRAEhYLgcmN9RX_WQZfizdQJxizlTczdpzYfy-v-1eQ"
knowledge:
base_url: "http://117.175.169.61:10000"
enabled: true
DingTalkBot:
enabled: true
api_key: "dingsbbntrkeiyazcfdg"
api_secret: "ObqxwyR20r9rVNhju0sCPQyQA98_FZSc32W4vgxnGFH_b02HZr1BPCJsOAF816nu"
zltxOrderAfterSaleSupplier:
enabled: true
base_url: "https://gateway.dev.cdlsxd.cn/zltx_api/admin/afterSales/directs"
zltxOrderAfterSaleReseller:
enabled: true
base_url: "https://gateway.dev.cdlsxd.cn/zltx_api/admin/afterSales/reseller_pre_ai"
zltxOrderAfterSaleResellerBatch:
enabled: true
base_url: "https://gateway.dev.cdlsxd.cn/zltx_api/admin/afterSales/reseller_pre_ai"
weather:
enabled: true
base_url: "https://restapi.amap.com/v3/weather/weatherInfo"
api_key: "12afbde5ab78cb7e575ff76bd0bdef2b"
cozeExpress:
enabled: true
base_url: "https://api.coze.cn"
api_key: "7582477438102552616"
api_secret: "pat_eEN0BdLNDughEtABjJJRYTW71olvDU0qUbfQUeaPc2NnYWO8HeyNoui5aR9z0sSZ"
cozeCompany:
enabled: true
base_url: "https://api.coze.cn"
api_key: "7583905168607100978"
api_secret: "pat_eEN0BdLNDughEtABjJJRYTW71olvDU0qUbfQUeaPc2NnYWO8HeyNoui5aR9z0sSZ"
zltxResellerAuthProductToManagerAndDefaultLossReason:
base_url: "https://revcl.1688sup.com/api/admin/reseller/resellerAuthProduct/getManagerAndDefaultLossReason"
# eino tool 配置
eino_tools:
# 货易通商品上传
hytProductUpload:
base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/goods/supplier/batch/add/complete"
add_url: "https://gateway.dev.cdlsxd.cn/sw//#/goods/goodsManage"
# 货易通供应商查询
hytSupplierSearch:
base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/supplier/list"
# 货易通仓库查询
hytWarehouseSearch:
base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/warehouse/list"
# 货易通商品添加
hytGoodsAdd:
base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/goods/add"
add_url: "https://gateway.dev.cdlsxd.cn/sw//#/goods/goodsManage"
# 货易通商品图片添加
hytGoodsMediaAdd:
base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/media/add/batch"
# 货易通商品分类添加
hytGoodsCategoryAdd:
base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/good/category/relation/add"
# 货易通商品分类查询
hytGoodsCategorySearch:
base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/goods/category/list"
# 货易通商品品牌查询
hytGoodsBrandSearch:
base_url: "https://gateway.dev.cdlsxd.cn/goods-admin/api/v1/goods/brand/list"
# == 电商充值系统 ==
# 我们的商品统计
rechargeStatisticsOursProduct:
base_url: "http://admin.lanseds.cn/admin/statistics/oursProduct"
# == 通用工具 ==
# 表格转图片
excel2pic:
base_url: "http://192.168.6.109:8010/api/v1/convert"
dingtalk:
api_key: "dingsbbntrkeiyazcfdg"
api_secret: "ObqxwyR20r9rVNhju0sCPQyQA98_FZSc32W4vgxnGFH_b02HZr1BPCJsOAF816nu"
table_demand:
url: "https://alidocs.dingtalk.com/i/nodes/YQBnd5ExVE6qAbnOiANQg2KKJyeZqMmz"
base_id: "YQBnd5ExVE6qAbnOiANQg2KKJyeZqMmz"
sheet_id_or_name: "数据表"
# 机器人群组
bot_group_id:
bbxt: 23
# 互动卡片
card:
# 卡片回调路由key
callback_route_key: "gateway.dev.cdlsxd.cn-dingtalk-card"
# 卡片调试工具 [show:展示 hide:隐藏]
debug_tool_entry_show: "show"
# 卡片模板
template:
# 基础消息卡片(title + content)
base_msg: "291468f8-a048-4132-a37e-a14365e855e9.schema"
# 内容收集卡片(title + textarea + button)
content_collect: "3a447814-6a3e-4a02-b48a-92c57b349d77.schema"
# 创建群聊申请(title + content + button)
create_group_approve: "faad6d5d-726d-467f-a6ba-28c1930aa5f3.schema"
# 场景群
scene_group:
# 问题处理群模板ID
group_template_id_issue_handling: "aa3aa4fe-e709-4491-b24b-c3d5b27e86d0"
# 问题处理群模板机器人ID
group_template_robot_id_issue_handling: "VqgJYpB91j3RnB217690607273471011"
qywx:
corp_id: "ww48151f694fb8ec67"
app_secret: "uYqtdwdtdH4Uv_P4is2AChuGzBCoB6cQDyRvpbW0Vmk"
token: "zJdukry6"
aes_key: "4VLH47qRGUogc2d3QLWuUhvJlk8Y0YuRjXzeBquBq8B"
init_account: "les.,FuZhongYun"
chat_id_len: 16
default_config_id: 1
bot_group_id:
bbxt: 36
default_prompt:
img_recognize:
system_prompt:
'你是一个具备图像理解与用户意图分析能力的智能助手。当用户提供一张图片时,请完成以下任务:
1. 关键信息提取:
提取出图片中对用户可能有用的关键信息(例如金额、日期、标题、编号、联系信息、商品名称等)。
若图片为文档类(如合同、发票、收据),请结构化输出关键字段(如客户名称、金额、开票日期等)。
'
user_prompt: '识别图片内容'
# 权限配置
permissionConfig:
permission_url: "http://api.test.user.1688sup.cn:8001/v1/menu/myCodes?systemId="
# 知识库配置
knowledge_config:
base_url: "http://192.168.6.115:9600"
tenant_id: "default"
mode: "naive"
stream: true
think: false
only_rag: true
# llm 服务配置
llm:
providers:
ollama:
endpoint: http://host.docker.internal:11434
timeout: 60s
models:
- id: qwen3-coder:480b-cloud
name: qwen3-coder:480b-cloud
streaming: true
modalities: [text]
max_tokens: 4096
vllm:
endpoint: http://117.175.169.61:16001
timeout: 60s
models:
- id: models/Qwen2.5-VL-3B-Instruct-AWQ
name: qwen2.5-vl-3b
streaming: true
modalities: [text, image]
max_tokens: 4096
# 每个能力只绑定一个 provider+model,不做自动回退
capabilities:
intent:
provider: vllm
model: qwen2.5-vl-3b
parameters:
temperature: 0.2
max_tokens: 4096
stream: false
vision:
provider: vllm
model: qwen2.5-vl-3b
parameters:
temperature: 0.5
max_tokens: 4096
stream: true
chat:
provider: ollama
model: qwen3-coder:480b-cloud
parameters:
temperature: 0.7
max_tokens: 4096
stream: true
jwt_secret: "lsxd20260918"
jwt_secret: "lsxd20260918"

View File

@ -44,13 +44,13 @@ ai_scheduler/
├── config/config.yaml # MySQL/Mongo/Redis/JWT/微信协议地址
├── internal/
│ ├── biz/ # ★ 业务逻辑层
│ │ ├── advice_wx.go # 微信回调处理 + 消息流水 + 会话聚合
│ │ ├── advice_wx_send.go # 微信消息发送
│ │ ├── advice_wx.go # 微信回调处理 + 消息流水 + 会话聚合 + ★ 托管自动注册
│ │ ├── advice_wx_send.go # 微信消息发送(含模拟真人打字延迟)
│ │ ├── advice_strategy.go # 智能策略(四级回复/主动对话)
│ │ ├── advice_client.go # 客户管理 + 等级评估
│ │ ├── advice_customer_new.go # ★ 微信好友 CRUD + 差集同步(ai_advice_customer)
│ │ ├── advice_label.go # ★ 标签同步(与 DB 比对增删改)
│ │ ├── advice_chat.go # AI 对话(LLM 调用)
│ │ ├── advice_chat.go # AI 对话(LLM 调用 + ChatWithSession 复用优化)
│ │ ├── advice_evaluate.go # 客户等级评估
│ │ ├── advice_proactive.go # 主动触达
│ │ ├── advice_iterate.go # 画像自迭代
@ -102,12 +102,12 @@ ai_scheduler/
| 表名 | 说明 | 关键字段 |
|---|---|---|
| `ai_advice_customer` | ★ 微信好友(`self_wxid` + `user_name` 唯一键) | label_list(逗号分隔的标签ID) |
| `ai_advice_customer` | ★ 微信好友(`self_wxid` + `user_name` 唯一键) | label_list, session_id(当前活跃会话) |
| `ai_advice_label` | ★ 微信标签(`self_wxid` + `label_id` 唯一键) | label_id, label_name |
| `ai_advice_advicer` | 销售基本信息 | wx_device_id(即 appId) |
| `ai_advice_project` | 项目信息 | wx_token |
| `ai_advice_admin` | 管理员账号 | |
| `ai_advice_session` | AI 对话会话 | |
| `ai_advice_session` | AI 对话会话 | advicer_id(托管场景动态取最新版本) |
### MongoDB 核心集合
@ -207,8 +207,37 @@ loadLabels()(并行)
→ 去重(AppId + NewMsgId)→ 入库 MongoDB advicer_wx_msg
→ WebSocket 广播 new_message(按 appId 匹配推送)
→ 触发智能策略(客户文本消息异步 AI 决策)
→ 触发托管自动注册(文本私聊消息异步检查)
```
### 托管自动注册流程
```
消息回调 → 文本私聊 → goroutine tryHostingAutoRegis
→ (1) 查 advicer(FindByWxDeviceId)→ hosting_enabled=1?
→ (2) 查 projectInfo → 取项目级 wxToken
→ (3) 若 peerWxid == "filehelper" 且 advicer.reply_filehelper=1 → 跳过标签检查,直接进入回复流程
否则调微信 contacts/getDetailInfo 取好友 labelList("1,2,3" 形式)
labelList 为空 → 直接 return,不做回复
→ (4) 取 ai_advice_label 中该销售 hosting=1 的标签 ID 列表
→ (5) 判断好友 labelList 与托管标签是否有交集,无交集 → return
→ (6) 查 ai_advice_customer 取 session_id(无则自动注册;filehelper 不在 customer 表,每次都自动注册)
→ (7) hostingChatAndSend(Chat 生成 AI 回复 → 拆段 → 模拟打字延迟 → 分段发送)
```
**关键设计**:
- 标签判断改用微信实时返回的 labelList,不再依赖 customer 表缓存的标签
- projectInfo 提前到步骤 2 查询(后续 getDetailInfo 和 Chat 都需要 wxToken)
- 客户昵称优先使用微信备注名(Remark),回退到 NickName,最后才用 customer 表中的昵称
- customer 表仅用于存取 session_id,不再承担标签判断职责
- 文件传输助手(filehelper)特殊路径:销售开启 `reply_filehelper` 后,跳过标签检查,直接作为客户进行 AI 回复;由于 filehelper 是微信系统账号,不在 customer 表,因此不写回 session_id,每条消息都新建一个会话
**模拟真人发送算法**:
- AI 回复拆分为多条短消息(每条 ≤80 字,按换行/句末标点拆分)
- 初始延迟 3~8 秒(模拟阅读 + 思考)
- 每条消息间延迟 = 思考时间(2~5s) + 打字时间(每字 300~500ms)
- 提示词约束:每条消息 10~30 字,用 `\n` 分隔
### WebSocket 实时通信
```
@ -222,7 +251,7 @@ loadLabels()(并行)
---
## 当前开发状态(截至 2026-09-24)
## 当前开发状态(截至 2026-09-25)
### 已完成
@ -235,10 +264,34 @@ loadLabels()(并行)
- [x] 联系人详情悬浮气泡(hover popup,含视口边界检测)
- [x] WebSocket 实时推送新消息 + 在线状态
- [x] 去掉 localStorage 缓存(brief/labels 全部内存 state)
- [x] 托管标签自动会话注册:检查标签交集 → 自动注册 AI 会话 → 回写 session_id
- [x] 托管自动回复:注册会话 → Chat → 拆段 → 模拟真人打字延迟 → 分段发送
- [x] 项目级 wx_token 支持:SendTextWithToken 方法,托管场景使用项目级 token
- [x] 查询优化:消除重复查询(projectInfo/advicer/session),新注册路径从 ~16 次降至 ~10 次 DB
- [x] 文件传输助手自动回复:销售级开关 `reply_filehelper`,开启后 peerWxid=filehelper 跳过标签检查直接作为客户进行 AI 回复
### 待开发(下一步)
#### 1. 标签标记为客户标签 → 客户管理联动
#### 1. 聊天算法深度优化
**目标**:进一步提升 AI 回复的真实感,让对话更自然、更像真人销售。
**优化方向**:
- **回复节奏优化**:根据消息内容复杂度动态调整延迟(简单问候快一些,复杂问题慢一些)
- **上下文感知回复**:结合客户画像、历史对话、当前时间段等因素调整回复风格
- **多轮对话连贯性**:确保多轮对话中话题过渡自然,不重复、不突兀
- **情绪感知**:识别客户情绪(犹豫/急迫/不满),动态调整回复语气和节奏
- **回复长度自适应**:根据客户消息长度调整回复长度(客户发短句,AI 也回短句)
- **提示词迭代**:根据实际对话效果持续优化 BasePrompt,减少 AI 味、增强人味
**涉及文件**:
- `internal/data/constants/prompt.go`(提示词模板)
- `internal/biz/advice_wx.go`(splitReplyToChunks / hostingChatAndSend)
- `internal/biz/advice_wx_send.go`(typingDelay 算法)
- `internal/biz/advice_chat.go`(Chat / ChatWithSession)
- `internal/biz/advice_strategy.go`(智能策略回复)
#### 2. 标签标记为客户标签 → 客户管理联动
**目标**:给标签打上"客户标记",被标记标签下的好友自动识别为客户,在客户管理模块体现,并在销售托管(自动回复)开启时仅对这些客户生效。
@ -258,7 +311,7 @@ loadLabels()(并行)
- 前端:`wx.js`(标签 tab 渲染标记按钮)、`theme.css`(标记样式)
- SQL:`06_ai_advice_label_customer_tag.sql`(ALTER TABLE 或迁移脚本)
#### 2. 好友/会话列表 → 给好友打标签
#### 3. 好友/会话列表 → 给好友打标签
**目标**:在好友列表和会话列表中,可以对好友(非 chatroom)添加到指定标签,类似微信原生标签管理。
@ -326,4 +379,4 @@ docker-compose up -d
---
*最后更新:2026-09-24*
*最后更新:2026-09-25*

View File

@ -109,6 +109,10 @@ func (a *AdviceAdvicerBiz) HostingUpdate(ctx context.Context, req *entitys.Advic
"hosting_version_id": req.HostingVersionId,
"hosting_skill_id": req.HostingSkillId,
}
// reply_filehelper 为可选字段,仅当显式传入时才更新
if req.ReplyFilehelper != nil {
updates["reply_filehelper"] = *req.ReplyFilehelper
}
cond := builder.NewCond()
cond = cond.And(builder.Eq{"advicer_id": req.AdvicerId})
return a.advicerImpl.UpdateByCond(&cond, updates)

View File

@ -15,6 +15,7 @@ import (
"errors"
"fmt"
"github.com/gofiber/fiber/v2/log"
"github.com/google/uuid"
"github.com/sashabaranov/go-openai"
"go.mongodb.org/mongo-driver/bson"
@ -95,10 +96,20 @@ func (a *AdviceChatBiz) Regis(ctx context.Context, chatData *entitys.ChatData, r
return "", err
}
err = a.rdb.Rdb.SetEx(ctx, sessionId, promptJson, 3600*time.Second).Err()
// 存储 ChatData 供后续 Chat 全量注入提示词
if chatDataJson, e := json.Marshal(chatData); e == nil {
_ = a.rdb.Rdb.SetEx(ctx, "chatdata:"+sessionId, string(chatDataJson), 3600*time.Second).Err()
}
return sessionId, err
}
// UpdateSessionMission 仅更新 session 的 mission 字段(用于复用已有会话时刷新人格/项目信息)
func (a *AdviceChatBiz) UpdateSessionMission(ctx context.Context, sessionId, mission string) error {
cond := builder.NewCond()
cond = cond.And(builder.Eq{"session_id": sessionId})
return a.aiAdviceSessionImpl.UpdateByCond(&cond, map[string]interface{}{"mission": mission})
}
func (a *AdviceChatBiz) Chat(ctx context.Context, chat *entitys.AdvicerChatReq) (assistant mongo_model.Assistant, err error) {
var session dbmodel.AiAdviceSession
cond := builder.NewCond()
@ -127,16 +138,22 @@ func (a *AdviceChatBiz) Chat(ctx context.Context, chat *entitys.AdvicerChatReq)
if err != nil {
return assistant, err
}
prompt, err := a.buildChatPromptResponse(ctx, chat, &session, chatHis)
var chatData entitys.ChatData
if cdStr, e := a.rdb.Rdb.Get(ctx, "chatdata:"+session.SessionID).Result(); e == nil {
_ = json.Unmarshal([]byte(cdStr), &chatData)
}
prompt, err := a.buildChatPromptResponse(ctx, chat, &session, chatHis, &chatData)
if err != nil {
return assistant, err
}
log.Infof("[提示词] sessionId=%s prompt=%s", session.SessionID, pkg.JsonStringIgonErr(prompt))
resContent, err := a.callLlmResponse(ctx, prompt, modelInfo.Key, modelInfo.URL, modelInfo.ChatModel, session.ContextCache)
if err != nil {
return assistant, err
}
result := resContent.GetOutputText()
log.Infof("[AI回复] sessionId=%s content=%s", session.SessionID, result)
if err = json.Unmarshal([]byte(result), &assistant); err != nil {
return assistant, err
}
@ -183,16 +200,22 @@ func (a *AdviceChatBiz) ChatWithSession(ctx context.Context, chat *entitys.Advic
if err != nil {
return assistant, err
}
prompt, err := a.buildChatPromptResponse(ctx, chat, session, chatHis)
var chatData entitys.ChatData
if cdStr, e := a.rdb.Rdb.Get(ctx, "chatdata:"+session.SessionID).Result(); e == nil {
_ = json.Unmarshal([]byte(cdStr), &chatData)
}
prompt, err := a.buildChatPromptResponse(ctx, chat, session, chatHis, &chatData)
if err != nil {
return assistant, err
}
log.Infof("[提示词] sessionId=%s prompt=%s", session.SessionID, pkg.JsonStringIgonErr(prompt))
resContent, err := a.callLlmResponse(ctx, prompt, modelInfo.Key, modelInfo.URL, modelInfo.ChatModel, session.ContextCache)
if err != nil {
return assistant, err
}
result := resContent.GetOutputText()
log.Infof("[AI回复] sessionId=%s content=%s", session.SessionID, result)
if err = json.Unmarshal([]byte(result), &assistant); err != nil {
return assistant, err
}
@ -223,11 +246,53 @@ func (a *AdviceChatBiz) ChatWithSession(ctx context.Context, chat *entitys.Advic
return
}
func (a *AdviceChatBiz) buildChatPromptResponse(ctx context.Context, chat *entitys.AdvicerChatReq, session *dbmodel.AiAdviceSession, chatList []mongo_model.AdvicerChatHisMongoEntity) ([]openai.ResponseInputMessage, error) {
func (a *AdviceChatBiz) buildChatPromptResponse(ctx context.Context, chat *entitys.AdvicerChatReq, session *dbmodel.AiAdviceSession, chatList []mongo_model.AdvicerChatHisMongoEntity, chatData *entitys.ChatData) ([]openai.ResponseInputMessage, error) {
const outputFormatHint = "\n[输出格式]请用 json 格式返回你的回复,结构为 {\"result\":\"回复内容\",\"mission_status\":\"in_progress|completed|fail\",\"mission_complete_desc\":\"本轮进展小结\"}。"
var sys strings.Builder
// 基础规则 + 任务 + 风控红线
sys.WriteString(constants.BasePrompt)
if session.Mission != "" {
sys.WriteString(session.Mission)
sys.WriteString("\n")
}
if chatData != nil && chatData.RuleDimension != "" {
sys.WriteString(constants.RulePromptPrefix)
sys.WriteString(chatData.RuleDimension)
sys.WriteString("\n")
}
sys.WriteString(constants.BasePrompt2)
// 全量结构化数据注入
if chatData != nil {
if chatData.ProjectInfo != nil {
sys.WriteString("\n[项目信息]\n")
sys.WriteString(pkg.JsonStringIgonErr(chatData.ProjectInfo))
}
if chatData.ProjectData != nil && len(chatData.ProjectData) > 0 {
sys.WriteString("\n[项目资料]\n")
sys.WriteString(pkg.JsonStringIgonErr(chatData.ProjectData))
}
if chatData.AdvicerInfo != nil {
sys.WriteString("\n[销售信息]\n")
sys.WriteString(pkg.JsonStringIgonErr(chatData.AdvicerInfo))
}
if chatData.AdvicerVersion != nil && len(chatData.AdvicerVersion) > 0 {
sys.WriteString("\n[销售人设风格]\n")
sys.WriteString(pkg.JsonStringIgonErr(chatData.AdvicerVersion))
}
if chatData.ClientInfo != nil {
sys.WriteString("\n[客户信息]\n")
sys.WriteString(pkg.JsonStringIgonErr(chatData.ClientInfo))
}
if chatData.TalkSkill != nil {
sys.WriteString("\n[销售技巧]\n")
sys.WriteString(pkg.JsonStringIgonErr(chatData.TalkSkill))
}
}
sys.WriteString(outputFormatHint)
message := []openai.ResponseInputMessage{
{
Role: openai.ChatMessageRoleSystem,
Content: a.taskPrompt(session),
Content: sys.String(),
},
{
Role: openai.ChatMessageRoleSystem,
@ -468,6 +533,8 @@ func formatPersonaPrompt(v map[string]interface{}) string {
}
// asMap 将 interface{} 安全转为 map[string]interface{}
// 使用 JSON 中转,兼容 bson.M / primitive.M / map[string]interface{} 等各种 map 类型,
// 解决 mongo-driver 返回 primitive.M 时类型断言 v.(bson.M) 匹配不上的问题。
func asMap(v interface{}) map[string]interface{} {
if v == nil {
return nil
@ -475,13 +542,24 @@ func asMap(v interface{}) map[string]interface{} {
if m, ok := v.(map[string]interface{}); ok {
return m
}
if m, ok := v.(bson.M); ok {
return map[string]interface{}(m)
// bson.D(有序文档):mongo-driver 解码嵌套文档时可能返回 bson.D 而非 bson.M
if d, ok := v.(bson.D); ok {
return d.Map()
}
return nil
// JSON 中转,兼容 primitive.M 等其他 bson 类型
data, err := json.Marshal(v)
if err != nil {
return nil
}
var m map[string]interface{}
if err = json.Unmarshal(data, &m); err != nil {
return nil
}
return m
}
// asStringSlice 将 interface{} 安全转为 []string
// 使用 JSON 中转,兼容 bson.A / primitive.A / []interface{} 等各种 slice 类型。
func asStringSlice(v interface{}) []string {
if v == nil {
return nil
@ -498,7 +576,22 @@ func asStringSlice(v interface{}) []string {
}
return out
}
return nil
// JSON 中转,兼容 primitive.A 等 bson 切片类型
data, err := json.Marshal(v)
if err != nil {
return nil
}
var arr []interface{}
if err = json.Unmarshal(data, &arr); err != nil {
return nil
}
out := make([]string, 0, len(arr))
for _, item := range arr {
if s, ok := item.(string); ok {
out = append(out, s)
}
}
return out
}
// asFloat64 将 interface{} 安全转为 float64

View File

@ -128,13 +128,15 @@ func (a *AdviceWxBiz) handleOneEvent(ctx context.Context, body []byte) error {
// 判定消息方向与对话方 wxid
direction := mongo_model.WxMsgDirectionCustomer
peerWxid := event.PeerWxid()
to := event.Data.ToUserName.Val()
if event.IsSelfMsg() {
// 销售自己发的消息通常标记为 Self,但发给 filehelper 的除外:
// 给文件传输助手发消息时,保持 Customer 方向,让托管流程能作为客户消息触发 AI 回复
if event.IsSelfMsg() && to != "filehelper" {
direction = mongo_model.WxMsgDirectionSelf
} else if len(event.Wxid) == 0 && a.clientBiz != nil {
// 报文未提供登录微信标识:借助客户绑定库判定
from := event.Data.FromUserName.Val()
to := event.Data.ToUserName.Val()
if _, found, _ := a.clientBiz.FindByWxid(ctx, from); !found {
if _, foundTo, _ := a.clientBiz.FindByWxid(ctx, to); foundTo {
direction = mongo_model.WxMsgDirectionSelf
@ -222,7 +224,6 @@ func (a *AdviceWxBiz) handleOneEvent(ctx context.Context, body []byte) error {
// WebSocket 实时广播:向对应 appId 的已连接前端推送新消息事件
if a.wsBroadcaster != nil {
log.Infof("[WS] broadcasting new_message appId=%s wxid=%s", event.AppId, peerWxid)
a.wsBroadcaster.Broadcast(event.AppId, "new_message", map[string]interface{}{
"appId": event.AppId,
"wxid": peerWxid,
@ -242,74 +243,97 @@ func (a *AdviceWxBiz) handleOneEvent(ctx context.Context, body []byte) error {
}
// 智能策略:客户文本消息异步触发 AI 回复决策
if direction == mongo_model.WxMsgDirectionCustomer && len(peerWxid) != 0 && wx.IsTextMsg(msgType) && a.strategyBiz != nil {
wxid, msgContent := peerWxid, content
go func() {
sctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()
a.strategyBiz.OnCustomerMessage(sctx, wxid, msgContent)
}()
}
// 托管自动注册 + AI 回复:双向触发(不限 direction),文本私聊消息检查
if wx.IsTextMsg(msgType) && !event.IsGroupMsg() {
appId, selfWxid, msgContent := event.AppId, event.Wxid, content
go a.tryHostingAutoRegis(context.Background(), appId, selfWxid, peerWxid, msgContent, direction)
go a.tryHostingAutoRegis(context.Background(), appId, selfWxid, peerWxid, to, msgContent, direction)
}
return nil
}
// ==================== 托管自动注册 ====================
// tryHostingAutoRegis 托管自动注册 + AI 回复:检查消息是否触发托管会话,
// 若客户无 session 则自动注册,然后用触发消息调用 Chat 生成 AI 回复并发送。
func (a *AdviceWxBiz) tryHostingAutoRegis(ctx context.Context, appId, selfWxid, peerWxid, content string, direction string) {
// tryHostingAutoRegis 托管自动回复流程:
// 1. 查 advicer,确认处于托管状态(hosting_enabled=1)
// 2. 查 projectInfo 取项目级 wxToken
// 3. 若回调数据 ToUserName.string == "filehelper" 且 advicer.reply_filehelper=1 → 跳过标签检查,直接进入回复流程
// 否则调微信 contacts/getDetailInfo 取好友的 labelList("1,2,3" 形式)
// labelList 为空 → 直接 return,不做回复
// 4. 取 ai_advice_label 中该销售 hosting=1 的标签 ID 列表
// 5. 判断好友 labelList 与托管标签是否有交集,无交集 → return
// 6. 查 ai_advice_customer 取 session_id(无则自动注册;filehelper 不在 customer 表,每次都自动注册)
// 7. 调 Chat 生成 AI 回复 → hostingChatAndSend 发送
func (a *AdviceWxBiz) tryHostingAutoRegis(ctx context.Context, appId, selfWxid, peerWxid, toUserName, content string, direction string) {
if appId == "" || selfWxid == "" || peerWxid == "" {
return
}
// 1. 通过 appId(即 wx_device_id)查 advicer
// 1. 通过 appId(即 wx_device_id)查 advicer,确认托管状态
advicer, err := a.adviceAdvicerBiz.FindByWxDeviceId(ctx, appId)
if err != nil {
log.Infof("[托管] 查 advicer 失败 appId=%s err=%v", appId, err)
return
}
if advicer.AdvicerID == 0 || advicer.HostingEnabled != 1 {
return
}
// 2. 查 customer(selfWxid + peerWxid)
customer, err := a.adviceCustomerBiz.FindBySelfWxidAndUserName(ctx, selfWxid, peerWxid)
// 2. 查项目信息(含项目级 wxToken),后续 getDetailInfo 与 Chat 都要用
projectInfo, err := a.adviceProjectBiz.Info(ctx, &entitys.AdvicerProjectInfoReq{ProjectId: advicer.ProjectID})
if err != nil {
log.Infof("[托管] 查 customer 失败 selfWxid=%s peerWxid=%s err=%v", selfWxid, peerWxid, err)
return
}
if customer.CustomerID == 0 {
wxToken := projectInfo.Base.WxToken
if wxToken == "" {
return
}
sessionId := customer.SessionId
// 3. 文件传输助手特殊路径:仅看回调 ToUserName.string 是否为 "filehelper"
// 是 → 跳过标签检查,直接检查 advicer.reply_filehelper 开关
// 否 → 走正常标签交集检查流程
isFilehelper := toUserName == "filehelper"
var sessionId string
var cachedSession *dbmodel.AiAdviceSession
var cachedModelInfo *dbmodel.AiAdviceModelSup
var customerNickName string
if !isFilehelper {
// 3a. 调微信 contacts/getDetailInfo 取好友的 labelList
var detailRes []wx.GetDetailInfoResData
if err := wx.Request(ctx, wxToken, wx.GetDetailInfo, wx.GetDetailInfoReq{
AppId: appId,
Wxids: []string{peerWxid},
}, &detailRes); err != nil {
return
}
if len(detailRes) == 0 {
return
}
detail := detailRes[0]
friendLabelList := strings.TrimSpace(detail.LabelList)
if friendLabelList == "" {
// 好友没有任何标签,不进入托管回复
return
}
// 3. 无会话 → 检查标签交集 → 自动注册(projectInfo 延迟到需要时才查)
if sessionId == "" {
// 4. 取该销售下 hosting=1 的托管标签 ID 列表
hostingLabelIds, _ := a.adviceLabelBiz.GetHostingLabelIds(ctx, selfWxid)
if len(hostingLabelIds) == 0 {
return
}
customerLabelSet := make(map[int]bool)
if customer.LabelList != "" {
for _, s := range strings.Split(customer.LabelList, ",") {
var id int
if _, e := fmt.Sscanf(strings.TrimSpace(s), "%d", &id); e == nil {
customerLabelSet[id] = true
}
// 5. 判断好友标签与托管标签是否有交集
friendLabelSet := make(map[int]bool)
for _, s := range strings.Split(friendLabelList, ",") {
var id int
if _, e := fmt.Sscanf(strings.TrimSpace(s), "%d", &id); e == nil && id > 0 {
friendLabelSet[id] = true
}
}
hasIntersection := false
for _, id := range hostingLabelIds {
if customerLabelSet[id] {
if friendLabelSet[id] {
hasIntersection = true
break
}
@ -317,39 +341,88 @@ func (a *AdviceWxBiz) tryHostingAutoRegis(ctx context.Context, appId, selfWxid,
if !hasIntersection {
return
}
// 标签有交集,才查项目信息(用于注册 + 后续发送)
projectInfo, err := a.adviceProjectBiz.Info(ctx, &entitys.AdvicerProjectInfoReq{ProjectId: advicer.ProjectID})
// 6. 查 ai_advice_customer 取 session_id
customer, err := a.adviceCustomerBiz.FindBySelfWxidAndUserName(ctx, selfWxid, peerWxid)
if err != nil {
log.Infof("[托管] 查项目信息失败 projectId=%d err=%v", advicer.ProjectID, err)
return
}
sessionId, cachedSession, cachedModelInfo, err = a.autoRegisSession(ctx, advicer, projectInfo, customer.CustomerID, customer.NickName)
if err != nil {
log.Infof("[托管] 自动注册会话失败 err=%v", err)
if customer.CustomerID == 0 {
return
}
sessionId = customer.SessionId
// 优先使用微信备注/昵称(更像真人),回退到 customer 表中的昵称
customerNickName = detail.Remark
if customerNickName == "" {
customerNickName = detail.NickName
}
if customerNickName == "" {
customerNickName = customer.NickName
}
// 无会话 → 自动注册
if sessionId == "" {
sessionId, cachedSession, cachedModelInfo, err = a.autoRegisSession(ctx, advicer, projectInfo, customer.CustomerID, customerNickName, peerWxid)
if err != nil {
// autoRegisSession error
return
}
} else {
// 复用已有会话时,刷新 mission 确保人格和项目信息是最新的
}
} else {
// filehelper 路径:跳过标签检查,直接检查 advicer.reply_filehelper 开关
if advicer.ReplyFilehelper != 1 {
// 开关未开启,不回复 filehelper
return
}
// filehelper 与普通客户同等对待:查 ai_advice_customer 表,复用 session_id
customerNickName = "文件传输助手"
customer, err := a.adviceCustomerBiz.FindBySelfWxidAndUserName(ctx, selfWxid, peerWxid)
if err != nil {
return
}
if customer.CustomerID == 0 {
if err = a.adviceCustomerBiz.Add(ctx, &entitys.AdvicerCustomerAddReq{
SelfWxid: selfWxid,
UserName: peerWxid,
NickName: customerNickName,
}); err != nil {
return
}
customer, err = a.adviceCustomerBiz.FindBySelfWxidAndUserName(ctx, selfWxid, peerWxid)
if err != nil || customer.CustomerID == 0 {
return
}
}
sessionId = customer.SessionId
if sessionId == "" {
sessionId, cachedSession, cachedModelInfo, err = a.autoRegisSession(ctx, advicer, projectInfo, customer.CustomerID, customerNickName, peerWxid)
if err != nil {
// filehelper autoRegis error
return
}
} else {
// 复用已有会话时,刷新 mission 确保人格和项目信息是最新的
}
}
// 4. 有会话 + 客户发的消息 → 调用 Chat 生成 AI 回复并发送
// 7. 有会话 + 客户发的消息 → 调 Chat 生成 AI 回复并发送
if sessionId != "" && direction == mongo_model.WxMsgDirectionCustomer && content != "" {
// 延迟获取 wxToken(已有会话路径才需要查项目信息)
wxToken := ""
if p, err := a.adviceProjectBiz.Info(ctx, &entitys.AdvicerProjectInfoReq{ProjectId: advicer.ProjectID}); err == nil {
wxToken = p.Base.WxToken
} else {
log.Infof("[托管] 查项目信息失败 projectId=%d err=%v", advicer.ProjectID, err)
return
}
a.hostingChatAndSend(ctx, sessionId, content, appId, peerWxid, wxToken, cachedSession, cachedModelInfo)
}
}
// 确保旧 session 也能拿到最新的人格和项目数据,而不是沿用老的空 mission。
// autoRegisSession 自动注册托管会话,返回 sessionId + session对象 + modelInfo(供后续 Chat 复用)。
// advicer 和 projectInfo 由调用方传入,避免重复查询。
func (a *AdviceWxBiz) autoRegisSession(ctx context.Context,
advicer dbmodel.AiAdviceAdvicer,
projectInfo *entitys.AdvicerProjectInfoRes,
customerId int32, customerNickName string,
peerWxid string,
) (string, *dbmodel.AiAdviceSession, *dbmodel.AiAdviceModelSup, error) {
// 解析版本
versionId := advicer.HostingVersionId
@ -377,12 +450,49 @@ func (a *AdviceWxBiz) autoRegisSession(ctx context.Context,
return "", nil, nil, fmt.Errorf("查版本数据失败: %w", err)
}
// 构建 ChatData(直接使用传入的 advicer,不再重复查询)
// 加载销售技巧
var talkSkillEntity *mongo_model.AdvicerTalkSkillMongoEntity
if advicer.HostingSkillId != "" {
// 指定了技巧ID,直接加载
if skillInfo, e := a.adviceSkillBiz.Info(ctx, &entitys.AdvicerTalkSkillInfoReq{Id: advicer.HostingSkillId}); e == nil {
talkSkillEntity = skillInfo.Entity()
}
} else {
// 未指定技巧ID,取该项目最新的技巧
if list, e := a.adviceSkillBiz.VersionList(ctx, &entitys.AdvicerTalkSkillListReq{ProjectId: projectInfo.Base.ProjectID}); e == nil && len(list) > 0 {
talkSkillEntity = list[0].AdvicerTalkSkillMongo.Entity()
}
}
// 加载客户信息(MongoDB advicer_client)
var clientEntity *mongo_model.AdvicerClientMongoEntity
if peerWxid != "" {
var clientDoc mongo_model.AdvicerClientMongo
filter := bson.M{"projectId": projectInfo.Base.ProjectID, "advicerId": advicer.AdvicerID, "wxid": peerWxid}
if e := a.mongo.Co(mongo_model.NewAdvicerClientMongo()).FindOne(ctx, filter).Decode(&clientDoc); e == nil {
clientEntity = clientDoc.Entity()
}
}
// 构建完整 ProjectInfo(确保 MySQL 项目名不丢)
projEntity := projectInfo.ConfigInfo.Entity()
if projEntity.ProjectInfo.Name == "" && projectInfo.Base.Name != "" {
projEntity.ProjectInfo.Name = projectInfo.Base.Name
}
// 加载项目资料(advicer_project_data 集合,扁平栏目数据)
var projectData map[string]interface{}
if projData, e := a.adviceProjectBiz.ProjectDataLoad(ctx, projectInfo.Base.ProjectID); e == nil && len(projData.Data) > 0 {
projectData = projData.Data
}
// 构建 ChatData(全量数据注入)
chatData := &entitys.ChatData{
AdvicerInfo: advicer.Entity(),
AdvicerVersion: versionInfo.Data,
ProjectInfo: projectInfo.ConfigInfo.Entity(),
ProjectInfo: projEntity,
ProjectData: projectData,
RuleDimension: projectInfo.Base.RuleDimension,
TalkSkill: talkSkillEntity,
ClientInfo: clientEntity,
}
// 构建注册请求(托管场景额外强调短消息格式)
@ -390,6 +500,27 @@ func (a *AdviceWxBiz) autoRegisSession(ctx context.Context,
if customerNickName == "" {
mission = "自动托管会话。注意:每条回复必须简短(10~30字),像真人微信聊天一样拆成多条短消息,用\\n分隔。"
}
// 将项目基本信息拼接到 mission,让后续每次 Chat 的 taskPrompt 都能带上项目名称和地址。
// 原因:Chat 时只传 taskPrompt + 聊天历史 + 用户消息,PreviousResponseID 续写不会让模型可靠获取项目信息,
// 因此必须把项目信息直接写入 mission 字段,随 session 持久化,每次 Chat 都能看到。
// 项目信息:优先用 MySQL 的 Base.Name(一定有),MongoDB 的 ProjectInfo 作为补充
projectDesc := "\n[项目信息]"
hasProjectInfo := false
if projectInfo.Base.Name != "" {
projectDesc += "\n项目名称:" + projectInfo.Base.Name
hasProjectInfo = true
}
if pi := projectInfo.ConfigInfo.ProjectInfo; pi.Address != "" {
projectDesc += "\n项目地址:" + pi.Address
hasProjectInfo = true
}
if hasProjectInfo {
mission = mission + projectDesc
}
// 将销售人格拼接到 mission
if persona := formatPersonaPrompt(chatData.AdvicerVersion); persona != "" {
mission = mission + "\n\n" + persona
}
regisReq := &entitys.AdvicerChatRegistReq{
AdvicerVersionId: versionId,
TalkSkillId: advicer.HostingSkillId,
@ -419,9 +550,8 @@ func (a *AdviceWxBiz) autoRegisSession(ctx context.Context,
// 回写 customer.session_id
if err = a.adviceCustomerBiz.UpdateSessionId(ctx, customerId, sessionId); err != nil {
log.Infof("[托管] 回写 session_id 失败 customerId=%d sessionId=%s err=%v", customerId, sessionId, err)
// ignore
}
log.Infof("[托管] 自动注册会话成功 customerId=%d sessionId=%s advicerId=%d", customerId, sessionId, advicer.AdvicerID)
return sessionId, session, &modelInfo, nil
}
@ -442,12 +572,10 @@ func (a *AdviceWxBiz) hostingChatAndSend(ctx context.Context, sessionId, content
assistant, err = a.adviceChatBiz.Chat(ctx, chatReq)
}
if err != nil {
log.Infof("[托管] Chat 失败 sessionId=%s err=%v", sessionId, err)
return
}
reply := strings.TrimSpace(assistant.Result)
if reply == "" {
log.Infof("[托管] Chat 返回空回复 sessionId=%s", sessionId)
return
}
// 拆分回复为多段消息,模拟真人分段发送
@ -458,9 +586,9 @@ func (a *AdviceWxBiz) hostingChatAndSend(ctx context.Context, sessionId, content
// 通过微信分段发送 AI 回复(使用项目级 wx_token)
if a.wxSendBiz != nil {
if _, err = a.wxSendBiz.SendMultiWithToken(ctx, wxToken, appId, peerWxid, chunks, mongo_model.WxMsgSourceCallback); err != nil {
log.Infof("[托管] 发送回复失败 appId=%s peerWxid=%s err=%v", appId, peerWxid, err)
// ignore
} else {
log.Infof("[托管] 发送回复成功 sessionId=%s chunks=%d reply=%s", sessionId, len(chunks), reply)
log.Infof("[微信回复] sessionId=%s reply=%s", sessionId, reply)
}
}
}

View File

@ -8,6 +8,7 @@ const BasePrompt = `**[场景]**现在你是专业的顾问,我们在聊天软
2.像真人发微信一样说话:一条消息只表达一个意思,每条尽量控制在10~30个字;要说的内容较多时,必须拆成2~4条短消息,在result里用\n分隔。禁止把超过40个字的内容塞进同一条消息!记住:真人微信聊天不会发长段落,每条消息就像一口气打出来的那么短。
3.结合[任务内容]信息,若任务状态为"in_progress",则在对话中尽量完成任务;如果任务状态为"completed"或"fail",则主动结束对话,且该轮对话中不再更新任务状态,mission_complete_desc记录最终结果且不再更改。不要每一句对话都包含任务内容,不要目的性太强!
4.不能有任何画外音的文字格式出现!比如(等待对方回复)
5.严禁编造任何你不确定或不了解的信息!如果客户问到的事情不在提供的json数据范围内(比如你的宠物、个人经历、家庭情况等),请自然地回避或说「这个记不太清了」,绝对不能瞎编!只有json数据中明确提供的信息才能作为你的回答依据。
**[任务内容]**`
// RulePromptPrefix 风控红线前缀(项目级 rule_dimension 非空时拼入系统提示)

View File

@ -23,6 +23,7 @@ type AiAdviceAdvicer struct {
HostingEnabled int32 `gorm:"column:hosting_enabled;not null;default:0;comment:托管开关 0关 1开" json:"hosting_enabled"`
HostingVersionId string `gorm:"column:hosting_version_id;not null;default:'';comment:指定版本ID,空=最新" json:"hosting_version_id"`
HostingSkillId string `gorm:"column:hosting_skill_id;not null;default:'';comment:指定技巧ID,空=最新" json:"hosting_skill_id"`
ReplyFilehelper int32 `gorm:"column:reply_filehelper;not null;default:0;comment:是否回复文件传输助手 0关 1开" json:"reply_filehelper"`
CreateAt time.Time `gorm:"column:create_at;default:CURRENT_TIMESTAMP" json:"create_at"`
}

View File

@ -24,6 +24,7 @@ func (a *AdvicerProjectMongo) MongoTableName() string {
}
type AdvicerProjectMongoEntity struct {
ProjectInfo ProjectInfo `json:"projectInfo" bson:"projectInfo"`
RegionValue RegionValue `json:"regionValue" bson:"regionValue"`
CompetitionComparison CompetitionComparison `json:"competitionComparison" bson:"competitionComparison"`
CoreSellingPoints CoreSellingPoints `json:"coreSellingPoints" bson:"coreSellingPoints"`
@ -33,6 +34,7 @@ type AdvicerProjectMongoEntity struct {
func (a *AdvicerProjectMongo) Entity() *AdvicerProjectMongoEntity {
return &AdvicerProjectMongoEntity{
ProjectInfo: a.ProjectInfo,
RegionValue: a.RegionValue,
CompetitionComparison: a.CompetitionComparison,
CoreSellingPoints: a.CoreSellingPoints,

View File

@ -9,6 +9,7 @@ type ChatData struct {
ClientInfo *mongo_model.AdvicerClientMongoEntity `json:"clientInfo"`
TalkSkill *mongo_model.AdvicerTalkSkillMongoEntity `json:"talkSkill"`
ProjectInfo *mongo_model.AdvicerProjectMongoEntity `json:"projectInfo"`
ProjectData map[string]interface{} `json:"projectData"` // advicer_project_data 扁平栏目数据
AdvicerInfo *model.AiAdviceAdvicerEntity `json:"advicerInfo"`
AdvicerVersion map[string]interface{} `json:"advicerVersion"` // 扁平维度数据
// RuleDimension 项目风控红线(来自项目模板 rule_dimension,可为空)

View File

@ -40,6 +40,7 @@ type AdvicerHostingUpdateReq struct {
HostingEnabled int32 `json:"hostingEnabled"` // 0=关闭 1=开启
HostingVersionId string `json:"hostingVersionId"` // 指定数字人版本ID,空=动态取最新
HostingSkillId string `json:"hostingSkillId"` // 指定聊天技巧ID,空=动态取最新
ReplyFilehelper *int32 `json:"replyFilehelper"` // 是否回复文件传输助手(nil=不更新;0=关闭;1=开启)
}
// ProjectWxTokenUpdateReq 更新项目的微信协议 Token

Binary file not shown.

View File

@ -0,0 +1,4 @@
-- 销售级开关:是否回复文件传输助手(filehelper)
-- 0=关闭(默认),1=开启;开启后 peerWxid=filehelper 的文本消息跳过标签检查直接作为客户进行 AI 回复
ALTER TABLE `ai_advice_advicer`
ADD COLUMN `reply_filehelper` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否回复文件传输助手 0关 1开' AFTER `hosting_skill_id`;

View File

@ -62,7 +62,7 @@ function renderTabAdvicers(body) {
html += '<div class="empty"><div class="big">◉</div>暂无销售人员,点击右上角新增</div>';
} else {
html += '<div class="table-wrap"><table class="table"><thead><tr>' +
"<th>ID</th><th>姓名</th><th>生日</th><th>入职时间</th><th>性别</th><th>行业经验</th><th>微信设备ID</th><th>托管</th><th>创建时间</th><th>操作</th></tr></thead><tbody>" +
"<th>ID</th><th>姓名</th><th>生日</th><th>入职时间</th><th>性别</th><th>行业经验</th><th>微信设备ID</th><th>托管</th><th>文件助手</th><th>创建时间</th><th>操作</th></tr></thead><tbody>" +
list.map(function (a) {
var gender = a.gender === 1 ? "男" : a.gender === 2 ? "女" : "-";
var hOn = a.hosting_enabled === 1 || a.hosting_enabled === true;
@ -75,6 +75,7 @@ function renderTabAdvicers(body) {
"<td>" + (a.working_years || "-") + " 年</td>" +
'<td class="mono fs-12">' + Core.esc(a.wx_device_id || '-') + "</td>" +
'<td><label class="switch"><input type="checkbox" class="adv-hosting" data-id="' + a.advicer_id + '" data-name="' + Core.esc(a.name || "") + '" data-enabled="' + (hOn ? 1 : 0) + '" data-ver="' + Core.esc(a.hosting_version_id || "") + '" data-skill="' + Core.esc(a.hosting_skill_id || "") + '"' + (hOn ? ' checked' : '') + '><span class="slider"></span></label></td>' +
'<td><label class="switch"><input type="checkbox" class="adv-filehelper" data-id="' + a.advicer_id + '"' + ((a.reply_filehelper === 1 || a.reply_filehelper === true) ? ' checked' : '') + '><span class="slider"></span></label></td>' +
'<td class="fs-12">' + Core.fmtTime(a.create_at) + "</td>" +
'<td class="ops"><button class="btn ghost sm adv-edit" data-id="' + a.advicer_id + '">编辑</button>' +
'<button class="btn ghost sm adv-avatar" data-id="' + a.advicer_id + '" data-name="' + Core.esc(a.name || "") + '">数字人管理</button>' +
@ -131,6 +132,21 @@ function renderTabAdvicers(body) {
);
};
});
// 文件助手开关:独立切换,立即生效
$$(".adv-filehelper").forEach(function (b) {
b.onchange = function () {
var advicerId = Number(b.dataset.id);
Core.api("advicer/hosting/update", {
advicerId: advicerId,
replyFilehelper: b.checked ? 1 : 0
}).then(function () {
Core.toast(b.checked ? "文件助手回复已开启" : "文件助手回复已关闭", "ok");
}).catch(function (e) {
Core.toast(e.message, "err");
b.checked = !b.checked;
});
};
});
}).catch(function (e) {
body.innerHTML = '<div class="empty"><div class="big">⚠</div>' + Core.esc(e.message) + "</div>";
});

View File

@ -99,7 +99,7 @@
<script src="assets/js/project_list.js?v=18"></script>
<script src="assets/js/project_detail.js?v=27"></script>
<script src="assets/js/project_analysis.js?v=21"></script>
<script src="assets/js/project_data.js?v=36"></script>
<script src="assets/js/project_data.js?v=37"></script>
<script src="assets/js/project_activity.js?v=18"></script>
<script src="assets/js/project_drill.js?v=19"></script>
<script src="assets/js/project_smart.js?v=18"></script>