266 lines
14 KiB
Go
266 lines
14 KiB
Go
package public
|
||
|
||
import (
|
||
"ai_scheduler/internal/config"
|
||
"ai_scheduler/internal/entitys"
|
||
"ai_scheduler/internal/pkg/utils_ollama"
|
||
"context"
|
||
"encoding/json"
|
||
"fmt"
|
||
"net/http"
|
||
"time"
|
||
|
||
"github.com/ollama/ollama/api"
|
||
|
||
"github.com/coze-dev/coze-go"
|
||
)
|
||
|
||
type CozeCompany struct {
|
||
cozeApi coze.CozeAPI
|
||
config config.ToolConfig
|
||
llm *utils_ollama.Client
|
||
}
|
||
|
||
// NewCoze 创建 Coze 实例
|
||
func NewCozeCompany(config config.ToolConfig, llm *utils_ollama.Client) *CozeCompany {
|
||
return &CozeCompany{
|
||
cozeApi: newCozeApi(config),
|
||
config: config,
|
||
llm: llm,
|
||
}
|
||
}
|
||
|
||
// newCozeClient 创建 Coze 客户端
|
||
func newCozeApi(config config.ToolConfig) coze.CozeAPI {
|
||
authCli := coze.NewTokenAuth(config.APISecret)
|
||
cozeApi := coze.NewCozeAPI(authCli, coze.WithBaseURL(config.BaseURL), coze.WithHttpClient(&http.Client{
|
||
Timeout: time.Second * 120,
|
||
}))
|
||
return cozeApi
|
||
}
|
||
|
||
// Name 返回工具名称
|
||
func (c *CozeCompany) Name() string {
|
||
return "coze_company"
|
||
}
|
||
|
||
// Description 返回工具描述
|
||
func (c *CozeCompany) Description() string {
|
||
return "查询企业信息"
|
||
}
|
||
|
||
// Definition 返回工具定义
|
||
func (c *CozeCompany) Definition() entitys.ToolDefinition {
|
||
return entitys.ToolDefinition{
|
||
Type: "function",
|
||
Function: entitys.FunctionDef{
|
||
Name: c.Name(),
|
||
Description: c.Description(),
|
||
Parameters: map[string]interface{}{
|
||
"type": "object",
|
||
"properties": map[string]interface{}{
|
||
"company_name": map[string]interface{}{
|
||
"type": "string",
|
||
"description": "企业名称",
|
||
},
|
||
},
|
||
"required": []string{"company_name"},
|
||
},
|
||
},
|
||
}
|
||
}
|
||
|
||
// Execute 执行查询
|
||
func (c *CozeCompany) Execute(ctx context.Context, requireData *entitys.Recognize) error {
|
||
var req map[string]interface{}
|
||
if err := json.Unmarshal([]byte(requireData.Match.Parameters), &req); err != nil {
|
||
return fmt.Errorf("invalid express request: %w", err)
|
||
}
|
||
|
||
if req["company_name"] == "" {
|
||
return fmt.Errorf("company_name is required")
|
||
}
|
||
|
||
// 调用 Coze 工作流
|
||
rsp, err := c.callWorkflow(ctx, req)
|
||
if err != nil {
|
||
return fmt.Errorf("failed to get real weather: %w", err)
|
||
}
|
||
|
||
companyInfo := CompanyInfo{}
|
||
err = json.Unmarshal([]byte(rsp.Data), &companyInfo)
|
||
if err != nil {
|
||
return fmt.Errorf("failed to unmarshal company info: %w", err)
|
||
}
|
||
|
||
// 调用 LLM 模型
|
||
err = c.llm.ChatStream(ctx, requireData.Ch, []api.Message{
|
||
{
|
||
Role: "system",
|
||
Content: `# Role: 企业信息分析与经营诊断专家:
|
||
请基于以下12项指定数据字段(无需补充未提供的信息),完成目标企业的全维度分析总结,要求每部分结论必须100%锚定对应数据,拒绝主观推测,突出“风险可见性”与“关键信息关联性”:
|
||
一、输入数据清单(需逐一对应分析)
|
||
行政处罚:公司是否有行政处罚(含处罚事由、处罚机关、处罚日期、处罚文号)
|
||
清算信息:公司的清算信息(含清算原因、清算组构成、清算进展状态)
|
||
变更记录:公司的变更记录(含变更事项:注册资本/股东/法定代表人/经营范围、变更时间、变更前后内容)
|
||
主要成员:公司名搜索公司的主要成员(含姓名、职位、任职时间、核心履历关键词)
|
||
企业详情:公司名称,搜索公司详细信息(含成立时间、注册资本、经营范围、行业分类、注册地址)
|
||
经营异常:公司是否有经营异常(含列入原因、列入日期、移出状态)
|
||
破产重组:公司破产重组的信息(含申请法院、受理时间、重组方案核心内容)
|
||
严重违法:是否有严重违法信息(含违法事由、认定机关、公示期限)
|
||
司法信息:司法信息(含案件类型、原被告身份、判决结果/进展)
|
||
被执行信息:公司的被执行信息(含执行法院、执行标的、未履行金额、失信状态)
|
||
企业手机号:公司名称查询企业手机号(需标注是否为公开备案号)
|
||
股东信息:公司对应的股东(含股东名称、出资额、出资比例、股东类型:自然人/企业/机构)
|
||
二、分析总结框架(严格对应数据)
|
||
1. 企业基础画像(锚定公司名称,搜索公司详细信息)
|
||
核心属性:成立时间、注册资本(实缴/认缴)、行业分类(如“批发和零售业”“软件和信息技术服务业”)、主营业务(从经营范围中提炼1-2个核心赛道,如“专注于智能仓储设备研发与销售”);
|
||
注册地址:是否与主要经营地一致(若公司名称,搜索公司详细信息有披露)。
|
||
2. 股权结构与股东特征(锚定公司对应的股东)
|
||
股权集中度:前三大股东出资占比之和(如“第一大股东持股60%,为绝对控股股东”);
|
||
股东类型分布:自然人股东、企业股东、机构股东的占比(如“70%为企业股东,含1家行业头部企业”);
|
||
关键股东亮点:若有知名企业/机构股东,需明确标注(如“股东含XX产业投资基金,具备产业链资源协同潜力”)。
|
||
3. 经营稳定性与合规风险(锚定公司是否有行政处罚/公司是否有经营异常/是否有严重违法信息/公司的清算信息/公司破产重组的信息)
|
||
行政处罚风险:是否存在行政处罚?
|
||
若有:列清「处罚事由(如“虚假宣传”“税务逾期申报”)、处罚机关、处罚日期」,并判断“是否属于高频违规”(如1年内≥2次同类处罚→高风险);
|
||
若无:标注“无公开行政处罚记录”。
|
||
经营异常风险:是否存在经营异常?
|
||
若有:说明「列入原因(如“通过登记的住所无法联系”“未公示年度报告”)、是否已移出」,并评估对业务的影响(如“地址失联可能导致客户信任下降”);
|
||
若无:标注“无经营异常记录”。
|
||
严重违法红线:是否存在严重违法?
|
||
若有:明确「违法事由(如“拒不履行生效法律文书”“欺诈消费者”)、认定机关、公示期限」,并标注“触及监管红线,需重点核查整改情况”;
|
||
若无:标注“无严重违法记录”。
|
||
极端状态预警:是否存在清算或破产重组?
|
||
若有清算:说明「清算原因(如“股东会决议解散”“营业期限届满”)、清算进展(如“清算组已完成资产清查”)」;
|
||
若有破产重组:说明「申请法院、受理时间、重组方案核心内容(如“拟引入战略投资者注资5000万”)」;
|
||
若无:标注“无清算或破产重组记录”。
|
||
4. 司法与执行风险(锚定司法信息/公司的被执行信息)
|
||
涉诉情况:司法案件的核心特征(如“80%为买卖合同纠纷,20%为劳动争议仲裁”;“作为被告的案件占比75%”;“判决胜诉率约60%”);
|
||
被执行压力:是否存在被执行信息?
|
||
若有:列清「执行法院、执行标的金额、未履行金额、是否纳入失信被执行人名单」,并计算“未履行金额占注册资本的比例”(如“未履行800万,占注册资本的20%”);
|
||
若无:标注“无公开被执行记录”。
|
||
5. 管理团队与联系信息(锚定公司名搜索公司的主要成员/公司名称查询企业手机号)
|
||
核心团队稳定性:主要成员的任职时间分布(如“CEO任职4年,CFO任职2年,核心团队平均任职3年”);是否有频繁变动(如“1年内2位高管离职”→需提示“管理稳定性风险”);
|
||
关键岗位资质:核心成员(如法定代表人、CEO、CFO)的过往履历亮点(如“CEO曾任职XX上市公司,主导过亿元级项目落地”);
|
||
联系信息可信度:企业手机号是否为公开备案(如“与工商登记预留电话一致→可信度高”;“为非备案号→需提示‘联系信息真实性存疑’”)。
|
||
6. 综合结论与行动建议(整合所有数据)
|
||
整体风险评级:基于数据密度,给出“低风险/中风险/高风险”定性(示例:“无行政处罚、无被执行、仅1条普通合同纠纷→低风险”;“有失信被执行+严重违法→高风险”);
|
||
Top3核心风险:按“严重违法>被执行>破产重组>行政处罚>经营异常>司法纠纷”排序,列出最需关注的3个问题(如“1. 未履行金额占注册资本20%,存在债务违约风险;2. 1年内2次地址异常,经营稳定性弱;3. 自然人股东占比过高,决策易受个人因素影响”);
|
||
actionable 建议:针对每个核心风险,给出可执行的核查/应对动作(如“核查未履行金额对应的案件进展,评估企业偿债能力;要求企业提供近1年的地址证明,确认经营场所稳定性;穿透核查自然人股东的资产状况,降低决策风险”)。
|
||
三、输出规则(强制遵守)
|
||
数据溯源:每句结论必须标注对应数据字段(如“根据公司是否有行政处罚,企业2023年因‘税务逾期申报’被区税务局处罚”);
|
||
量化优先:拒绝模糊表述(如不说“很多案件”,要说“近1年涉及5起买卖合同纠纷”);
|
||
风险分级:用“★”标注风险等级(★越多越严重,如“严重违法★★★”“被执行★★”“经营异常★”);
|
||
语言风格:专业简洁,避免冗余,适合风控/投资/合作前的快速决策阅读。
|
||
|
||
【示例输出片段】
|
||
3. 经营稳定性与合规风险
|
||
|
||
行政处罚:根据公司是否有行政处罚,企业2022年11月因“发布虚假广告”被区市场监管局处以3万元罚款(文号:X市监罚字〔2022〕456号),无后续同类处罚→风险等级★;
|
||
|
||
经营异常:根据公司是否有经营异常,企业2023年6月因“通过登记的住所无法联系”被列入异常名录,2023年12月已移出→风险等级★;
|
||
|
||
严重违法:根据是否有严重违法信息,无公开严重违法记录→风险等级无;
|
||
|
||
极端状态:根据公司的清算信息/公司破产重组的信息,无清算或破产重组记录→风险等级无。
|
||
|
||
6. 综合结论与行动建议
|
||
|
||
整体评级:低风险(仅1次轻微行政处罚,无重大合规瑕疵);
|
||
|
||
Top3核心风险:1. 根据司法信息,近1年作为被告的合同纠纷占比75%,需警惕应收账款回收风险★★;2. 根据公司名搜索公司的主要成员,1年内2位销售总监离职,管理稳定性弱★;3. 根据公司名称查询企业手机号,企业手机号为非备案号,联系信息真实性存疑★;
|
||
|
||
建议:核查合同纠纷案件的原告身份及回款情况,评估坏账概率;要求企业提供离职人员的交接说明,确认业务连续性;索要企业备案的联系方式,验证沟通有效性。
|
||
`,
|
||
},
|
||
|
||
{
|
||
Role: "assistant",
|
||
Content: fmt.Sprintf(`请分析企业:%s,
|
||
公司是否有行政处罚:%v,
|
||
公司的清算信息:%v,
|
||
公司的变更记录:%v,
|
||
公司名搜索公司的主要成员:%v,
|
||
公司名称,搜索公司详细信息:%v,
|
||
公司是否有经营异常:%v,
|
||
公司破产重组的信息:%v,
|
||
是否有严重违法信息:%v,
|
||
司法信息:%v,
|
||
公司的被执行信息:%v,
|
||
公司名称查询企业手机号:%v,
|
||
公司对应的股东:%v`, req["company_name"], companyInfo.Xzcf, companyInfo.Clears, companyInfo.Changes, companyInfo.Employees, companyInfo.Searchdata, companyInfo.Operations, companyInfo.BankruptcyPublicList, companyInfo.Illegals, companyInfo.JudicialList, companyInfo.Executes, companyInfo.Phone, companyInfo.Partners),
|
||
},
|
||
{
|
||
Role: "user",
|
||
Content: requireData.UserContent.Text,
|
||
},
|
||
},
|
||
c.Name(), "")
|
||
if err != nil {
|
||
return fmt.Errorf("failed to get express info: %w", err)
|
||
}
|
||
|
||
//entitys.ResText(requireData.Ch, "", rsp.Data)
|
||
|
||
return nil
|
||
}
|
||
|
||
// CallWorkflow 调用 Coze 工作流
|
||
// 参数:
|
||
// - ctx: 上下文,用于控制超时和取消
|
||
// - workflowId: 工作流 ID
|
||
// - params: 工作流参数
|
||
// 返回:
|
||
// - interface{}: 工作流执行结果
|
||
// - error: 错误信息
|
||
func (c *CozeCompany) callWorkflow(ctx context.Context, params map[string]interface{}) (*coze.RunWorkflowsResp, error) {
|
||
// 准备工作流请求参数
|
||
workflowReq := &coze.RunWorkflowsReq{
|
||
WorkflowID: c.config.APIKey,
|
||
Parameters: params,
|
||
}
|
||
|
||
// 调用工作流
|
||
resp, err := c.cozeApi.Workflows.Runs.Create(ctx, workflowReq)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("工作流调用失败: %w", err)
|
||
}
|
||
|
||
// 处理工作流响应
|
||
if resp == nil {
|
||
return nil, fmt.Errorf("工作流响应为空")
|
||
}
|
||
|
||
// 返回工作流执行结果
|
||
return resp, nil
|
||
}
|
||
|
||
type CompanyInfo struct {
|
||
BankruptcyPublicList interface{} `json:"bankruptcy_public_list"` // 破产公示列表
|
||
Changes interface{} `json:"changes"` // 变更记录
|
||
Clears interface{} `json:"clears"` // 清算记录
|
||
Employees interface{} `json:"employees"` // 员工列表
|
||
Executes interface{} `json:"executes"` // 执行记录
|
||
Illegals interface{} `json:"illegals"` // 违法记录
|
||
JudicialList interface{} `json:"judicial_list"` // 司法记录
|
||
Operations interface{} `json:"operations"` // 经营记录
|
||
Partners interface{} `json:"partners"` // 合伙人列表
|
||
Phone string `json:"phone"` // 联系电话
|
||
// 搜索数据
|
||
Searchdata struct {
|
||
Authority interface{} `json:"authority"`
|
||
BusinessScope interface{} `json:"business_scope"`
|
||
Capital interface{} `json:"capital"`
|
||
CompanyAddress interface{} `json:"company_address"`
|
||
CompanyName string `json:"company_name"`
|
||
CompanyStatus interface{} `json:"company_status"`
|
||
CompanyType interface{} `json:"company_type"`
|
||
CreditNo interface{} `json:"credit_no"`
|
||
EstablishDate interface{} `json:"establish_date"`
|
||
Industry interface{} `json:"industry"`
|
||
LegalPerson interface{} `json:"legal_person"`
|
||
Province interface{} `json:"province"`
|
||
} `json:"searchdata"`
|
||
Xzcf interface{} `json:"xzcf"` // 行政处罚
|
||
}
|