itam-assistant 0.1.1__py3-none-any.whl → 0.1.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
main/ailyapp_client.py ADDED
@@ -0,0 +1,132 @@
1
+ import json
2
+
3
+ import lark_oapi as lark
4
+ from lark_oapi.api.auth.v3 import *
5
+ from lark_oapi.api.aily.v1 import *
6
+
7
+
8
+ # SDK 使用说明: https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/server-side-sdk/python--sdk/preparations-before-development
9
+ # 以下示例代码默认根据文档示例值填充,如果存在代码问题,请在 API 调试台填上相关必要参数后再复制代码使用
10
+ # 复制该 Demo 后, 需要将 "YOUR_APP_ID", "YOUR_APP_SECRET" 替换为自己应用的 APP_ID, APP_SECRET.
11
+
12
+ class AilyLarkClient:
13
+ def __init__(self):
14
+ """
15
+ 初始化 Client 实例,tenant_access_token 会在 Client 初始化时自动获取
16
+ """
17
+ self.aily_app_id = "spring_f17d05d924__c"
18
+ self.app_id = "cli_a6e3aea1a13c900c"
19
+ self.app_secret = "J0fAPt3BL6bv4KUJV0dJMdTUdr0pv3xx"
20
+ # 创建 Lark-tenant tenant客户端
21
+ self.tlark_client = lark.Client.builder().app_id(self.app_id).app_secret(self.app_secret).build()
22
+
23
+ # 创建 Lark-tenant user 客户端
24
+ self.ulark_client = lark.Client.builder().enable_set_token(True).log_level(lark.LogLevel.DEBUG).build()
25
+
26
+ def get_tenant_access_token(self):
27
+ # 构造请求对象
28
+ request: InternalTenantAccessTokenRequest = InternalTenantAccessTokenRequest.builder() \
29
+ .request_body(InternalTenantAccessTokenRequestBody.builder()
30
+ .app_id(self.app_id)
31
+ .app_secret(self.app_secret)
32
+ .build()) \
33
+ .build()
34
+
35
+ # 发起请求
36
+ response: InternalTenantAccessTokenResponse = self.tlark_client.auth.v3.tenant_access_token.internal(request)
37
+
38
+ # 处理失败返回
39
+ if not response.success():
40
+ lark.logger.error(
41
+ f"client.auth.v3.tenant_access_token.internal failed, code: {response.code}, msg: {response.msg}, log_id: {response.get_log_id()}, resp: \n{json.dumps(json.loads(response.raw.content), indent=4, ensure_ascii=False)}")
42
+ return
43
+ # 处理业务结果
44
+ lark.logger.info(lark.JSON.marshal(response.raw, indent=4))
45
+ tenant_access_token = json.loads(response.raw.content).get("tenant_access_token")
46
+ if tenant_access_token:
47
+ return tenant_access_token
48
+ else:
49
+ lark.logger.error(
50
+ f"client.auth.v3.tenant_access_token.internal failed, code: {response.code}, msg: {response.msg}, log_id: {response.get_log_id()}, resp: \n{json.dumps(json.loads(response.raw.content), indent=4, ensure_ascii=False)}")
51
+ return
52
+
53
+ def create_ailysession(self, access_token):
54
+ # 创建会话
55
+ # 构造请求对象
56
+ request: CreateAilySessionRequest = CreateAilySessionRequest.builder() \
57
+ .request_body(CreateAilySessionRequestBody.builder()
58
+ .channel_context("{}")
59
+ .metadata("{}")
60
+ .build()) \
61
+ .build()
62
+
63
+ # 发起请求
64
+ option = lark.RequestOption.builder().user_access_token(access_token).build()
65
+ response: CreateAilySessionResponse = self.ulark_client.aily.v1.aily_session.create(request, option)
66
+
67
+ # 处理失败返回
68
+ if not response.success():
69
+ lark.logger.error(
70
+ f"client.aily.v1.aily_session.create failed, code: {response.code}, msg: {response.msg}, log_id: {response.get_log_id()}, resp: \n{json.dumps(json.loads(response.raw.content), indent=4, ensure_ascii=False)}")
71
+ return
72
+
73
+ # 处理业务结果
74
+ lark.logger.info(lark.JSON.marshal(response.data, indent=4))
75
+ return response.data.session.id
76
+
77
+ def create_ailysessionaily_message(self, access_token, session_id, content):
78
+ # 发送智能伙伴消息
79
+ # 构造请求对象
80
+ request: CreateAilySessionAilyMessageRequest = CreateAilySessionAilyMessageRequest.builder() \
81
+ .aily_session_id(session_id) \
82
+ .request_body(CreateAilySessionAilyMessageRequestBody.builder()
83
+ .content(content)
84
+ .content_type("MDX")
85
+ .idempotent_id("idempotent_id_1")
86
+ .build()) \
87
+ .build()
88
+ # 发起请求
89
+ option = lark.RequestOption.builder().user_access_token(access_token).build()
90
+ response: CreateAilySessionAilyMessageResponse = self.ulark_client.aily.v1.aily_session_aily_message.create(
91
+ request,
92
+ option)
93
+ # 处理失败返回
94
+ if not response.success():
95
+ lark.logger.error(
96
+ f"client.aily.v1.aily_session_aily_message.create failed, code: {response.code}, msg: {response.msg}, log_id: {response.get_log_id()}, resp: \n{json.dumps(json.loads(response.raw.content), indent=4, ensure_ascii=False)}")
97
+ return
98
+ # 处理业务结果
99
+ lark.logger.info(lark.JSON.marshal(response.data, indent=4))
100
+ return response.data.message.id
101
+
102
+ def create_ailysession_run(self, access_token, aily_session_id):
103
+ # 创建运行
104
+ # 构造请求对象
105
+ request: CreateAilySessionRunRequest = CreateAilySessionRunRequest.builder() \
106
+ .aily_session_id(aily_session_id) \
107
+ .request_body(CreateAilySessionRunRequestBody.builder()
108
+ .app_id(self.aily_app_id)
109
+ .build()) \
110
+ .build()
111
+ # 发起请求
112
+ option = lark.RequestOption.builder().user_access_token(
113
+ access_token).build()
114
+ response: CreateAilySessionRunResponse = self.ulark_client.aily.v1.aily_session_run.create(request, option)
115
+ # 处理失败返回
116
+ if not response.success():
117
+ lark.logger.error(
118
+ f"client.aily.v1.aily_session_run.create failed, code: {response.code}, msg: {response.msg}, log_id: {response.get_log_id()}, resp: \n{json.dumps(json.loads(response.raw.content), indent=4, ensure_ascii=False)}")
119
+ return
120
+
121
+ # 处理业务结果
122
+ lark.logger.info(lark.JSON.marshal(response.data, indent=4))
123
+
124
+
125
+
126
+ if __name__ == '__main__':
127
+ tenant_access_token = AilyLarkClient().get_tenant_access_token()
128
+ seseion_id = AilyLarkClient().create_ailysession(tenant_access_token)
129
+ print(seseion_id)
130
+ message_id = AilyLarkClient().create_ailysessionaily_message(tenant_access_token, seseion_id, "你好")
131
+ runs = AilyLarkClient().create_ailysession_run(tenant_access_token, seseion_id)
132
+
main/do_ai.py ADDED
@@ -0,0 +1,177 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from it_assistant.ailyapp_client import AilyLarkClient
4
+ from it_assistant.lark_client import LarkdocsClient
5
+ from it_assistant.intent_detail import *
6
+ import datetime
7
+
8
+
9
+ # Testsuitelink = "https://bytedance.larkoffice.com/sheets/ZVzfsw4rMhkMF6tjtxmc4BdSnMb"
10
+
11
+
12
+
13
+ def do_ai_auto(Testsuitelink):
14
+ """
15
+ 自动化执行AI测试用例
16
+ """
17
+ startAt = 0
18
+ try:
19
+ # 获取租户访问令牌
20
+ tenant_access_token = AilyLarkClient().get_tenant_access_token()
21
+ if not tenant_access_token:
22
+ raise ValueError("未能获取到有效的租户访问令牌")
23
+ # 通过文档链接获取spreadsheet_token
24
+ spreadsheet_token = Testsuitelink.split("/")[-1]
25
+ if not spreadsheet_token:
26
+ raise ValueError("未能从文档链接中提取到有效的spreadsheet_token")
27
+ # 读取表格用户输入
28
+ spreadsheet = LarkdocsClient().get_the_worksheet(spreadsheet_token)
29
+ if not spreadsheet:
30
+ raise ValueError("未能获取到有效的工作表数据")
31
+ for i in spreadsheet.sheets:
32
+ column_count = i.grid_properties.column_count
33
+ row_count = i.grid_properties.row_count
34
+ sheet_id = i.sheet_id
35
+ title = i.title
36
+ if title == "测试集":
37
+ # 构建JSON字符串
38
+ json_str = {"ranges": [sheet_id + "!A1:A" + str(row_count)]}
39
+ # 获取纯文本内容
40
+ test = LarkdocsClient().get_plaintextcontent(json_str, spreadsheet_token, sheet_id)
41
+ test = json.loads(test)
42
+ userinput = test['data']['value_ranges'][0]['values']
43
+ print(f"表头为{userinput[0]}")
44
+ for i in range(1, row_count):
45
+ if userinput[i][0]:
46
+ if startAt == 0:
47
+ startAt = int(time.time())
48
+ # 创建会话
49
+ seseion_id = AilyLarkClient().create_ailysession(tenant_access_token)
50
+ if not seseion_id:
51
+ raise ValueError("未能成功创建会话")
52
+ # 创建消息
53
+ message_id = AilyLarkClient().create_ailysessionaily_message(tenant_access_token, seseion_id,
54
+ userinput[i][0])
55
+ if not message_id:
56
+ raise ValueError("未能成功创建消息")
57
+ # 创建运行实例
58
+ runs = AilyLarkClient().create_ailysession_run(tenant_access_token, seseion_id)
59
+ #可不需等待运行实例创建完成
60
+ #if not runs:
61
+ # raise ValueError("未能成功创建运行实例")
62
+ time.sleep(1)
63
+ else:
64
+ return startAt, i
65
+ break
66
+ return startAt, row_count
67
+ break
68
+ except KeyError as ke:
69
+ print(f"KeyError 发生: 数据中缺少必要的键,错误详情: {ke}")
70
+ return None, None
71
+ except json.JSONDecodeError as jde:
72
+ print(f"JSON 解析错误: {jde}")
73
+ return None, None
74
+ except ValueError as ve:
75
+ print(f"值错误: {ve}")
76
+ return None, None
77
+ except Exception as e:
78
+ print(f"发生未知错误: {e}")
79
+ return None, None
80
+
81
+
82
+ def get_conversationlogs1(startAt):
83
+ """
84
+ 对话ID 技能分发 用户输入
85
+ res_data = {
86
+ 'intentID': 7485259579248705537,
87
+ 'skillLabels': ["GUI 设备/配件申请"],
88
+ 'userInput': "我要申请一个鼠标",
89
+
90
+ }
91
+ """
92
+ data = webapiClient().get_intent_detail_list(startAt)
93
+
94
+
95
+ def get_conversationlogs(startAt, pageSize=10):
96
+ """
97
+ 对话ID 技能分发 用户输入
98
+ res_data = {
99
+ 'intentID': 7485259579248705537,
100
+ 'skillLabels': ["GUI 设备/配件申请"],
101
+ 'userInput': "我要申请一个鼠标",
102
+
103
+ }
104
+ """
105
+ try:
106
+ # 之前提到形参 'pageSize' 未填,这里假设默认值为 10,你可按需修改
107
+ data = webapiClient().get_intent_detail_list(startAt, pageSize=10)
108
+ return data
109
+ except KeyError as ke:
110
+ print(f"KeyError 发生: 数据中缺少必要的键,错误详情: {ke}")
111
+ return None
112
+ except IndexError as ie:
113
+ print(f"IndexError 发生: 索引超出范围,错误详情: {ie}")
114
+ return None
115
+ except Exception as e:
116
+ print(f"发生未知错误: {e}")
117
+ return None
118
+
119
+
120
+ def write_reslut(data, Testsuitelink, title):
121
+ """
122
+ 写入表格
123
+ """
124
+ try:
125
+ # 解析 spreadsheet_token
126
+ spreadsheet_token = Testsuitelink.split("/")[-1]
127
+
128
+ # 生成新工作表名称
129
+ new_sheet_title = f"{title}{datetime.datetime.now().strftime('%Y_%m_%d_%H_%M_%S')}"
130
+ sheetinfo = {"index": 0, "title": new_sheet_title}
131
+
132
+ # 创建新工作表
133
+ spreadsheet0 = LarkdocsClient().createsheets(spreadsheet_token, sheetinfo)
134
+ sheet_id = spreadsheet0['sheet_id']
135
+
136
+ # 准备表头数据
137
+ headers = list(data[0].keys())
138
+ header_data = [
139
+ {
140
+ "range": f"{sheet_id}!{chr(ord('A') + col)}1:{chr(ord('A') + col)}1",
141
+ "values": [[[{"text": {"text": header}, "type": "text"}]]]
142
+ }
143
+ for col, header in enumerate(headers)
144
+ ]
145
+
146
+ # 写入表头
147
+ LarkdocsClient().writesheets(spreadsheet_token, sheet_id, {"value_ranges": header_data})
148
+
149
+ # 写入数据
150
+ for row, row_data in enumerate(data, start=1):
151
+ row_values = [
152
+ {
153
+ "range": f"{sheet_id}!{chr(ord('A') + col)}{row + 1}:{chr(ord('A') + col)}{row + 1}",
154
+ "values": [[[{"text": {"text": str(row_data[header])}, "type": "text"}]]]
155
+ }
156
+ for col, header in enumerate(headers)
157
+ ]
158
+ LarkdocsClient().writesheets(spreadsheet_token, sheet_id, {"value_ranges": row_values})
159
+
160
+ return True
161
+ except KeyError as ke:
162
+ print(f"KeyError 发生: 数据中缺少必要的键,错误详情: {ke}")
163
+ return False
164
+ except IndexError as ie:
165
+ print(f"IndexError 发生: 索引超出范围,错误详情: {ie}")
166
+ return False
167
+ except Exception as e:
168
+ print(f"发生未知错误: {e}")
169
+ return False
170
+
171
+
172
+ if __name__ == '__main__':
173
+ Testsuitelink = "https://bytedance.larkoffice.com/sheets/ZVzfsw4rMhkMF6tjtxmc4BdSnMb"
174
+ startAt, num = do_ai_auto(Testsuitelink)
175
+ data = webapiClient().get_intent_detail_list(startAt, num)
176
+ data_qqq = webapiClient().get_intent_detail_llm(data)
177
+ aaaa = write_reslut(data_qqq, Testsuitelink, "测试")
main/intent_detail.py ADDED
@@ -0,0 +1,326 @@
1
+ # -*- coding: utf-8 -*-
2
+ import http.client
3
+ import json
4
+ import time
5
+ import requests
6
+ headers = {
7
+ 'cookie':'X-Kunlun-SessionId=L%3A3b34958803f34f43a52c.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2YWwiOnsidGVuYW50X2lkIjozOTAsInVzZXJfaWQiOjE3MjIxNjYwNzMxOTk2NDUsInRlbmFudF9kb21haW5fbmFtZSI6ImFwYWFzIiwic2Vzc2lvbl92ZXJzaW9uIjoidjIwMjAtMDUtMTkiLCJ3c190b2tlbiI6Ilc6OTk3Y2MwNTA3OTRlNGFmYWFkYzEiLCJsb2dpbl90b2tlbiI6IjE3MDE3ZmFlMWJlNjVlMzdzSzBhMzA0ZjY0N2MyZmFjY2QwSjRFYmNmNGVjNzAzZDgwOWYxNDVnNDY0MzY1ZjEyNWI0YmZlZDhhTmMiLCJzb3VyY2VfY2hhbm5lbCI6ImZlaXNodSIsInRlbmFudF9rZXkiOiI3MzY1ODhjOTI2MGYxNzVkIiwiZXh0ZXJuYWxfZG9tYWluX25hbWUiOiJieXRlZGFuY2UiLCJvcmlnaW5hbF90ZW5hbnRfaWQiOjAsIm9yaWdpbmFsX3VzZXJfaWQiOjAsImlkcF9jaGFubmVsIjoiIn0sImV4cCI6MTc1ODk0MTY3MH0.l9yn5zbWFhOEJml5iA69TpFwZ7qgLMzj7L0cj4Ryozc; passport_web_did=7487801556726579201; passport_trace_id=7487801556748156956; QXV0aHpDb250ZXh0=2f506053fdd544e7aa0df84c66a287f9; locale=zh-CN; landing_url=https://accounts.feishu.cn/accounts/page/login?app_id=107&no_trap=1&redirect_uri=https%3A%2F%2Fapaas.feishu.cn%2Fai%2Fspring_f17d05d924__c%2Fmanagement%2Fchat-log; _gcl_au=1.1.1249684330.1743389657; s_v_web_id=verify_m8wh6ssk_JRUTLUkb_AJsu_4Xjm_ANzV_gLPDip941iqw; __tea__ug__uid=7487801495396992562; _ga=GA1.2.1834362348.1743389657; _gid=GA1.2.758422620.1743389658; session=XN0YXJ0-4e7g6c2c-da65-4492-a6f6-6413002bd949-WVuZA; session_list=XN0YXJ0-4e7g6c2c-da65-4492-a6f6-6413002bd949-WVuZA; login_recently=1; _ga_VPYRHN104D=GS1.1.1743389657.1.1.1743389669.48.0.0; msToken=4W_kQaUJyB5jBl5FX8vjfY6SYAFcNAp7NiDqM3-QyBN0XIF24a5SyaOeTpfzIZAuNfH-cGjXK1u3tNXV3ETo8Z2ZTQFLGSTFF2KmMr35XQsODVrddz8FdHAfyJg4F7ayxiDsicO5ObKgK0Y_95Bq1d12vKKbJ99vm9IZWEpcRFLG; kunlun-session-v2=L%3A3b34958803f34f43a52c.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2YWwiOnsidGVuYW50X2lkIjozOTAsInVzZXJfaWQiOjE3MjIxNjYwNzMxOTk2NDUsInRlbmFudF9kb21haW5fbmFtZSI6ImFwYWFzIiwic2Vzc2lvbl92ZXJzaW9uIjoidjIwMjAtMDUtMTkiLCJ3c190b2tlbiI6Ilc6OTk3Y2MwNTA3OTRlNGFmYWFkYzEiLCJsb2dpbl90b2tlbiI6IjE3MDE3ZmFlMWJlNjVlMzdzSzBhMzA0ZjY0N2MyZmFjY2QwSjRFYmNmNGVjNzAzZDgwOWYxNDVnNDY0MzY1ZjEyNWI0YmZlZDhhTmMiLCJzb3VyY2VfY2hhbm5lbCI6ImZlaXNodSIsInRlbmFudF9rZXkiOiI3MzY1ODhjOTI2MGYxNzVkIiwiZXh0ZXJuYWxfZG9tYWluX25hbWUiOiJieXRlZGFuY2UiLCJvcmlnaW5hbF90ZW5hbnRfaWQiOjAsIm9yaWdpbmFsX3VzZXJfaWQiOjAsImlkcF9jaGFubmVsIjoiIn0sImV4cCI6MTc1ODk0MTY3MH0.l9yn5zbWFhOEJml5iA69TpFwZ7qgLMzj7L0cj4Ryozc; kunlun-session-token=2b32fc3c28f44fb89bab94ad072a05c9f2f844c49705c95d76bae40479a189b7; _tea_utm_cache_1229=undefined; sl_session=eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NDM0MzI4NzEsInVuaXQiOiJldV9uYyIsInJhdyI6eyJtZXRhIjoiQVdIazBuRzhRUUFDQUFBQUFBQUFBQUZuNmdQWUFVNEFBV2ZxQTlnQlRnQUJaK29ENWRES3dBSUNLZ0VBUVVGQlFVRkJRVUZCUVVKdU5tZFFiRE40ZDBGQlp6MDkiLCJzdW0iOiJlMmM4YTIwMTcyMDcxNmVjYTFiOWRlOTQ5Yjc3OGJkNDczOGIzOTAwNWJiNTJhYTkyOTM2YTRhZWIzMGI2ZTY0IiwibG9jIjoiemhfY24iLCJhcGMiOiJSZWxlYXNlIiwiaWF0IjoxNzQzMzg5NjcxLCJzYWMiOnsiVXNlclN0YWZmU3RhdHVzIjoiMSIsIlVzZXJUeXBlIjoiNDIifSwibG9kIjpudWxsLCJjbmYiOnsiamt0IjoiYkx6aTdPRDBHS09mNllOQ0xGamtPZWtuQkNRSHM2ZFh5STdmcTVubE93VSJ9LCJucyI6ImxhcmsiLCJuc191aWQiOiI3MDUzOTk0MzAyMzAwNTUzMjE4IiwibnNfdGlkIjoiMSIsIm90IjozLCJjdCI6MTc0MzM4OTY3MCwicnQiOjE3NDMzODk2NzB9fQ.2pQlqU6fuqnw_iqtJe1sH1FfSSXBpFQ0RAoaRccxHEaHSBvqsdc9_7e4zjgcHOhTjISi3mGw3EC3EXftLj5Otw; passport_app_access_token=eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NDM0MzI4NzIsInVuaXQiOiJldV9uYyIsInJhdyI6eyJtX2FjY2Vzc19pbmZvIjp7IjEwNyI6eyJpYXQiOjE3NDMzODk2NzIsImFjY2VzcyI6dHJ1ZX19LCJzdW0iOiJlMmM4YTIwMTcyMDcxNmVjYTFiOWRlOTQ5Yjc3OGJkNDczOGIzOTAwNWJiNTJhYTkyOTM2YTRhZWIzMGI2ZTY0In19.jtfbxALtDnZYTJx4cb6ohPy2uDVCHTuh0x-Dg7Ui1F4vMO3aka7rvOeZTIwGJ7IlAn0b-OjBOWQEVQvHthhEwQ; swp_csrf_token=a239a297-e0f7-4820-aa3a-6349c8a04977; t_beda37=10a0c227407070710f979ef9d5b530118d080fd0ec27f2c3ce04c251a5a20d70',
8
+ 'x-kunlun-token': '17017fae1be65e37sK0a304f647c2faccd0J4Ebcf4ec703d809f145g464365f125b4bfed8aNc',
9
+ 'Content-Type': 'application/json'
10
+ }
11
+ itamheaders = {
12
+ 'authorization': 'Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6InYyIiwidHlwIjoiSldUIn0.eyJleHAiOjE3NDI1NDYyMTcsImp0aSI6ImJKMk9hV0dkanU5QStMMXciLCJpYXQiOjE3NDEyNTAyMTcsImlzcyI6InRhbm5hIiwic3ViIjoiMzgzMDMxOUBieXRlZGFuY2UucGVvcGxlIiwidGVuYW50X2lkIjoiYnl0ZWRhbmNlLnBlb3BsZSIsInRlbmFudF9uYW1lIjoiIiwicHJvamVjdF9rZXkiOiJjcm1TZmdIVmU1dXhIMHJyIiwidW5pdCI6ImV1X25jIiwiYXV0aF9ieSI6Mn0.eHghtX4NOnD1uD65bzqv7n1J3mtnPPXJoVKIWDwl4PMZPkqc3FisH4RMXxDqeOyDCgRHYhmam7VEenl8T0UIKpzI8ad8yMiZytvAkNhclLjCdmokLB7DdwnbO1qeDLxdqjL-S3da0KHHkOT8j-rWR94XJ0N7T_snoko4Ovsp13w',
13
+ 'Content-Type': 'application/json'
14
+
15
+ }
16
+
17
+ class webapiClient:
18
+ def __init__(self):
19
+ """
20
+ 初始化 Client 实例,tenant_access_token 会在 Client 初始化时自动获取
21
+ """
22
+ self.headers = headers
23
+ self.itamheaders = headers
24
+ self.conn = http.client.HTTPSConnection("apaas.feishu.cn")
25
+
26
+ def get_intent_detail_list1(self, startAt,pageSize):
27
+ """
28
+ outdata:
29
+ 对话ID 技能分发 用户输入
30
+ res_ = {
31
+ 'intentID': 7485259579248705537,
32
+ 'userInput': "我要申请一个鼠标",
33
+ 'skillLabels': ["GUI 设备/配件申请"],
34
+ 'apply_day':"",
35
+ 'apply_num':"",
36
+ 'asset_name':"",
37
+ 'device_type':""
38
+ }
39
+ """
40
+ endAt = int(time.time())
41
+ payload = json.dumps({
42
+ "startAt": startAt,
43
+ "endAt": endAt,
44
+ "matchIntentID": "",
45
+ "matchStatus": [],
46
+ "pageSize": pageSize+10
47
+ })
48
+ self.conn.request("POST",
49
+ "/ai/api/v1/conversational_runtime/namespaces/spring_f17d05d924__c/stats/intent_detail_list",
50
+ payload, self.headers)
51
+ res = self.conn.getresponse()
52
+ data = res.read()
53
+ data = json.loads(data.decode("utf-8"))
54
+ res_list = []
55
+
56
+ for i in data['data']['intentDetailList']:
57
+ if i['channelType'] in ["LARK_OPEN_API","LARK_BOT","ANONYMOUS_CUI_SDK"]:
58
+ res_list.append(
59
+ {'对话日志/intentID': i['intentID'],
60
+ '用户输入/userInput': i['userInput'],
61
+ '数据是否有效/isdatavalid': "是",
62
+ '语言/language': "zh",
63
+ '是否 IT 问题/isITproblem': "是",
64
+ '业务场景/businessscenario': "NULL",
65
+ '分发技能/skill': i['skillLabels'],
66
+ '型号关键字词/asset_name': "NULL",
67
+ '型号类型/device_type': "NULL",
68
+ '匹配型号/AssetNamelist': "NULL",
69
+ })
70
+
71
+
72
+ return res_list
73
+
74
+ def get_intent_detail_list(self, startAt, pageSize):
75
+ """
76
+ outdata:
77
+ 对话ID 技能分发 用户输入
78
+ res_ = {
79
+ 'intentID': 7485259579248705537,
80
+ 'userInput': "我要申请一个鼠标",
81
+ 'skillLabels': ["GUI 设备/配件申请"],
82
+ 'apply_day':"",
83
+ 'apply_num':"",
84
+ 'asset_name':"",
85
+ 'device_type':""
86
+ }
87
+ """
88
+ # 输入参数类型和范围检查
89
+ if not isinstance(startAt, int) or startAt < 0:
90
+ raise ValueError("startAt 必须是一个非负整数")
91
+ if not isinstance(pageSize, int) or pageSize < 0:
92
+ raise ValueError("pageSize 必须是一个非负整数")
93
+
94
+ endAt = int(time.time())
95
+ payload = json.dumps({
96
+ "startAt": startAt,
97
+ "endAt": endAt,
98
+ "matchIntentID": "",
99
+ "matchStatus": [],
100
+ "pageSize": pageSize + 10
101
+ })
102
+ try:
103
+ self.conn.request("POST",
104
+ "/ai/api/v1/conversational_runtime/namespaces/spring_f17d05d924__c/stats/intent_detail_list",
105
+ payload, self.headers)
106
+ res = self.conn.getresponse()
107
+
108
+ # 检查响应状态码
109
+ if res.status != 200:
110
+ raise http.client.HTTPException(f"请求失败,状态码: {res.status}, 原因: {res.reason}")
111
+
112
+ data = res.read()
113
+ try:
114
+ data = json.loads(data.decode("utf-8"))
115
+ except json.JSONDecodeError:
116
+ raise ValueError("无法将响应数据解析为 JSON 格式")
117
+
118
+ # 检查响应数据结构
119
+ if 'data' not in data or 'intentDetailList' not in data['data']:
120
+ raise ValueError("响应数据缺少必要的字段 'data' 或 'intentDetailList'")
121
+
122
+ res_list = []
123
+ for i in data['data']['intentDetailList']:
124
+ if i['channelType'] in ["LARK_OPEN_API", "LARK_BOT", "ANONYMOUS_CUI_SDK"]:
125
+ res_list.append({
126
+ '对话日志/intentID': i['intentID'],
127
+ '用户输入/userInput': i['userInput'],
128
+ '数据是否有效/isdatavalid': "是",
129
+ '语言/language': "zh",
130
+ '是否 IT 问题/isITproblem': "是",
131
+ '业务场景/businessscenario': "NULL",
132
+ '分发技能/skill': i['skillLabels'],
133
+ '型号关键字词/asset_name': "NULL",
134
+ '型号类型/device_type': "NULL",
135
+ '匹配型号/AssetNamelist': "NULL",
136
+ })
137
+ return res_list
138
+ except http.client.HTTPException as http_err:
139
+ print(f"HTTP 请求错误: {http_err}")
140
+ return []
141
+ except ValueError as value_err:
142
+ print(f"值错误: {value_err}")
143
+ return []
144
+ except Exception as general_err:
145
+ print(f"发生未知错误: {general_err}")
146
+ return []
147
+
148
+
149
+
150
+
151
+ def get_intent_detail_llm0(self, res_list):
152
+ """
153
+ 提取关键词
154
+ 'apply_day': "",'apply_num': "",'asset_name': "",'device_type': ""'对话日志/intentID': 7485264011232886786,
155
+ '用户输入/userInput': "我要申请一个鼠标",
156
+ '数据是否有效/isdatavalid': "是",
157
+ '语言/language': "zh",
158
+ '是否 IT 问题/isITproblem': "是",
159
+ '业务场景/businessscenario': "NULL",
160
+ '分发技能/skill': "NULL",
161
+ '型号关键字词/asset_name': "NULL", #显示器
162
+ '型号类型/device_type': "NULL", # 设备 配件 软件
163
+ '匹配型号/AssetNamelist': "NULL",
164
+ """
165
+ payload = ''
166
+ for i in res_list:
167
+ intentID = i['对话日志/intentID']
168
+ urlintentID = f'https://apaas.feishu.cn/ai/api/v1/conversational_runtime/namespaces/spring_f17d05d924__c/intent/{intentID}?pageSize=20&statusFilter=%5B%5D&fieldFilter=_node_id&fieldFilter=status&fieldFilter=usages&fieldFilter=_node_name&fieldFilter=_node_type&fieldFilter=title_for_maker&fieldFilter=associate_id'
169
+ response = requests.request("GET", urlintentID, headers=self.headers, data=payload)
170
+ response = json.loads(response.text)
171
+ for j in response['data']['steps']:
172
+ if j['titleForMaker'] in ["槽位抽取","LLM 2"]:
173
+ nodeid = j['nodeID']
174
+ urlnodeid = f'https://apaas.feishu.cn/ai/api/v1/conversational_runtime/namespaces/spring_f17d05d924__c/association/{intentID}/node/{nodeid}?intentID={intentID}'
175
+ response = requests.request("GET", urlnodeid, headers=self.headers, data=payload)
176
+ data_nodeid = json.loads(response.text)
177
+ nodeid_output = json.loads(data_nodeid['data']['step']['output'])
178
+ if nodeid_output is not None and nodeid_output['response'] is not None:
179
+ # 判断是否为json格式
180
+ if not isinstance(nodeid_output['response'], dict):
181
+ nodeid_output['response'] = json.loads(nodeid_output['response'])
182
+ #i['apply_day'] = nodeid_output['response'].get('apply_day', 'NULL')
183
+ #i['apply_num'] = nodeid_output['response'].get('apply_num', 'NULL')
184
+
185
+ i['型号关键字词/asset_name'] = nodeid_output['response'].get('asset_name', 'NULL')
186
+ i['型号类型/device_type'] = nodeid_output['response'].get('device_type', 'NULL')
187
+ return res_list
188
+
189
+
190
+ def get_intent_detail_llm(self, res_list):
191
+ """
192
+ 提取关键词:
193
+ 槽位提取:'apply_day': "",'apply_num': "",'asset_name': "",'device_type': ""
194
+ 表头字段:
195
+ '对话日志/intentID': 7485264011232886786,
196
+ '用户输入/userInput': "我要申请一个鼠标",
197
+ '数据是否有效/isdatavalid': "是",
198
+ '语言/language': "zh",
199
+ '是否 IT 问题/isITproblem': "是",
200
+ '业务场景/businessscenario': "NULL",
201
+ '分发技能/skill': "NULL",
202
+ '型号关键字词/asset_name': "NULL", #显示器
203
+ '型号类型/device_type': "NULL", # 设备 配件 软件
204
+ '匹配型号/AssetNamelist': "NULL",
205
+ """
206
+ try:
207
+ # 检查 res_list 是否为空
208
+ if not res_list:
209
+ print("输入的 res_list 为空")
210
+ return []
211
+
212
+ payload = ''
213
+ for i in res_list:
214
+ intentID = i['对话日志/intentID']
215
+ urlintentID = f'https://apaas.feishu.cn/ai/api/v1/conversational_runtime/namespaces/spring_f17d05d924__c/intent/{intentID}?pageSize=20&statusFilter=%5B%5D&fieldFilter=_node_id&fieldFilter=status&fieldFilter=usages&fieldFilter=_node_name&fieldFilter=_node_type&fieldFilter=title_for_maker&fieldFilter=associate_id'
216
+ response = requests.request("GET", urlintentID, headers=self.headers, data=payload)
217
+
218
+ # 检查响应状态码
219
+ response.raise_for_status()
220
+
221
+ try:
222
+ response = response.json()
223
+ except json.JSONDecodeError:
224
+ print(f"无法解析来自 {urlintentID} 的响应为 JSON 格式")
225
+ continue
226
+
227
+ # 检查响应数据结构
228
+ if 'data' not in response or 'steps' not in response['data']:
229
+ print(f"来自 {urlintentID} 的响应缺少必要的字段 'data' 或 'steps'")
230
+ continue
231
+
232
+ for j in response['data']['steps']:
233
+ if j['titleForMaker'] in ["槽位抽取", "LLM 2"]:
234
+ nodeid = j['nodeID']
235
+ urlnodeid = f'https://apaas.feishu.cn/ai/api/v1/conversational_runtime/namespaces/spring_f17d05d924__c/association/{intentID}/node/{nodeid}?intentID={intentID}'
236
+ response_nodeid = requests.request("GET", urlnodeid, headers=self.headers, data=payload)
237
+
238
+ # 检查响应状态码
239
+ response_nodeid.raise_for_status()
240
+
241
+ try:
242
+ data_nodeid = response_nodeid.json()
243
+ except json.JSONDecodeError:
244
+ print(f"无法解析来自 {urlnodeid} 的响应为 JSON 格式")
245
+ continue
246
+
247
+ # 检查响应数据结构
248
+ if 'data' not in data_nodeid or 'step' not in data_nodeid['data'] or 'output' not in data_nodeid['data']['step']:
249
+ print(f"来自 {urlnodeid} 的响应缺少必要的字段 'data'、'step' 或 'output'")
250
+ continue
251
+
252
+ nodeid_output = json.loads(data_nodeid['data']['step']['output'])
253
+ if nodeid_output is not None and nodeid_output.get('response') is not None:
254
+ # 判断是否为 json 格式
255
+ if not isinstance(nodeid_output['response'], dict):
256
+ try:
257
+ nodeid_output['response'] = json.loads(nodeid_output['response'])
258
+ except json.JSONDecodeError:
259
+ print(f"无法解析 {urlnodeid} 响应中的 'response' 字段为 JSON 格式")
260
+ continue
261
+ i['型号关键字词/asset_name'] = nodeid_output['response'].get('asset_name', 'NULL')
262
+ i['型号类型/device_type'] = nodeid_output['response'].get('device_type', 'NULL')
263
+
264
+ return res_list
265
+ except requests.RequestException as req_err:
266
+ print(f"请求错误: {req_err}")
267
+ return []
268
+ except Exception as general_err:
269
+ print(f"发生未知错误: {general_err}")
270
+ return []
271
+
272
+
273
+
274
+ def get_bestmatchitemforreturn(self,keyword):
275
+ """
276
+ mock数据,获取最佳匹配的sku/spu
277
+ mock数据:公用配件列表、设备列表、软件列表
278
+ todo:mock数据表格为飞书文档或者其他?
279
+ """
280
+ _urlGetBestMatchItemForReturn = "https://asset-mig-pre.bytedance.net/aily/api/itservice/ai/GetBestMatchItemForReturn"
281
+
282
+ payload = json.dumps({
283
+ "SearchKey": keyword,
284
+ "AiUseType": 1,
285
+ "ListReturnableAccessoryRequest": {
286
+ "IsAll": True,
287
+ "Page": {
288
+ "PageNum": 1,
289
+ "PageSize": 30
290
+ },
291
+ "OwnerUserID": "",
292
+ "AccessoryApplyTypeList": []
293
+ },
294
+ "GetAssetListRequest": {
295
+ "Status": 6,
296
+ "Search": "",
297
+ "IsAll": True,
298
+ "SubStatusList": [
299
+ 12,
300
+ 18,
301
+ 19
302
+ ],
303
+ "Page": {
304
+ "PageNum": 1,
305
+ "PageSize": 30
306
+ },
307
+ "OrganizationalUnitID": 1
308
+ }
309
+ })
310
+ response = requests.request("GET", _urlGetBestMatchItemForReturn, headers=self.headers, data=payload)
311
+ response = json.loads(response.text)
312
+
313
+ def get_segsearchcandidates(self, res_list):
314
+ #获取分数值
315
+ ### 读取设备&配件的信息并拼接到text里面
316
+ ### 遍历res_list中的device_name
317
+ ###判断是否在asset.json里面
318
+ ###调用算法接口获取设备&配件的分数值
319
+ pass
320
+
321
+
322
+
323
+ if __name__ == '__main__':
324
+ data = webapiClient().get_intent_detail_list(1742832000,10)
325
+ data_qqq = webapiClient().get_intent_detail_llm(data)
326
+ print("成都")