This commit is contained in:
parent
4280442a76
commit
f9b78eefea
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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*
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 非空时拼入系统提示)
|
||||
|
|
|
|||
|
|
@ -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"`
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,可为空)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
BIN
server.exe
BIN
server.exe
Binary file not shown.
|
|
@ -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`;
|
||||
|
|
@ -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>";
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Reference in New Issue