#AI夏令营 #Datawhale #夏令营
1. 基于星火大模型的群聊对话分角色要素提取挑战赛
赛事链接:challenge.xfyun.cn/h5/detail?t…
报名了还不算完,提交自己的结果还有调用星火的资源需要实名认证,
2. 白嫖大模型额度
报名成功之后就有 200 万,查看链接:console.xfyun.cn/app/myapp
然后现在 Spark3.5 Max 模型正在搞活动,新用户点击即送 1 亿 token!领取地址如下:
1 亿 token 需要个人或者企业认证,前面认证过这里就很方便了。在领取的时候会让你选择将这个额度绑定到一个应用上,可以新创建一个应用,也可以直接指定到这次赛题的应用上去。
3. 30 分钟体验一站式 baseline
项目链接:aistudio.baidu.com/projectdeta…
项目在百度的平台上,所以还需要登录百度账号才能继续愉快玩耍
aistudio 界面好久没用现在焕然一新啊,点进去之后是一个 notebook,跟着里面的步骤走即可。
然后你会发现自己运行不了这个 notebook,需要在自己账号下创建一个副本,点击运行一下按钮
之后让你启动环境,选择不花钱的最基础的环境就可以启动了。启动前是这样的
启动后是这样的
界面是有变化的,比起以前的界面要好一些,以前总是在预览的时候不小心运行了哪一块代码,然后展示出来的结果就更新了,顺带着还把账号里的计算资源浪费了,以前被双击的鼠标坑过,现在这样分开阅读和编辑模式还是很好的。
然后拿到这个 notebook 主要是把 step 2 里面的 API 信息填入。
API 信息其实就是前面报名挑战赛白嫖的额度,在查看资源链接里面点击这个挑战赛应用,然后左边栏选择 Spark Max,在右侧可以看到服务接口认证信息,这里就分别对应着上面代码里的 SPARKAI_APP_ID,SPARKAI_API_SECRET,SPARKAI_API_KEY
分别复制过去,然后在 notebook 运行这边选择运行全部的 cell
等大概 30 分钟就有一个结果了。
我把 notebook 里主要的代码放到下面,供日后自己参考
Step1:下载相关库(大概 10 s)
!pip install --upgrade -q spark_ai_python
WARNING: Skipping page https://mirror.baidu.com/pypi/simple/tenacity/ because the GET request got Content-Type: application/octet-stream. The only supported Content-Types are application/vnd.pypi.simple.v1+json, application/vnd.pypi.simple.v1+html, and text/html
WARNING: Skipping page https://mirror.baidu.com/pypi/simple/pip/ because the GET request got Content-Type: application/octet-stream. The only supported Content-Types are application/vnd.pypi.simple.v1+json, application/vnd.pypi.simple.v1+html, and text/html
Step2:配置导入
from sparkai.llm.llm import ChatSparkLLM, ChunkPrintHandler
from sparkai.core.messages import ChatMessage
import json
#星火认知大模型Spark3.5 Max的URL值,其他版本大模型URL值请前往文档(https://www.xfyun.cn/doc/spark/Web.html)查看
SPARKAI_URL = 'wss://spark-api.xf-yun.com/v3.5/chat'
#星火认知大模型调用秘钥信息,请前往讯飞开放平台控制台(https://console.xfyun.cn/services/bm35)查看
SPARKAI_APP_ID = ''
SPARKAI_API_SECRET = ''
SPARKAI_API_KEY = ''
#星火认知大模型Spark3.5 Max的domain值,其他版本大模型domain值请前往文档(https://www.xfyun.cn/doc/spark/Web.html)查看
SPARKAI_DOMAIN = 'generalv3.5'
Step3:模型测试
def get_completions(text):
messages = [ChatMessage(
role="user",
content=text
)]
spark = ChatSparkLLM(
spark_api_url=SPARKAI_URL,
spark_app_id=SPARKAI_APP_ID,
spark_api_key=SPARKAI_API_KEY,
spark_api_secret=SPARKAI_API_SECRET,
spark_llm_domain=SPARKAI_DOMAIN,
streaming=False,
)
handler = ChunkPrintHandler()
a = spark.generate([messages], callbacks=[handler])
return a.generations[0][0].text
# 测试模型配置是否正确
text = "你好"
get_completions(text)
'你好!有什么我可以帮忙的吗?'
Step4:数据读取
def read_json(json_file_path):
"""读取json文件"""
with open(json_file_path, 'r') as f:
data = json.load(f)
return data
def write_json(json_file_path, data):
"""写入json文件"""
with open(json_file_path, 'w') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
# 读取数据
train_data = read_json("dataset/train.json")
test_data = read_json("dataset/test_data.json")
Step5:Prompt 设计
这个 prompt 里面有 markdown 标记,如果要在笔记里正常显示内容,需要在一些标记符号前面加上反斜杠。不要直接复制这里的内容,复制完之后自己检查一下有没有多余的反斜杠。
# prompt 设计
PROMPT_EXTRACT = """
你将获得一段群聊对话记录。你的任务是根据给定的表单格式从对话记录中提取结构化信息。在提取信息时,请确保它与类型信息完全匹配,不要添加任何没有出现在下面模式中的属性。
表单格式如下:
info: Array<Dict(
"基本信息-姓名": string | "", // 客户的姓名。
"基本信息-手机号码": string | "", // 客户的手机号码。
"基本信息-邮箱": string | "", // 客户的电子邮箱地址。
"基本信息-地区": string | "", // 客户所在的地区或城市。
"基本信息-详细地址": string | "", // 客户的详细地址。
"基本信息-性别": string | "", // 客户的性别。
"基本信息-年龄": string | "", // 客户的年龄。
"基本信息-生日": string | "", // 客户的生日。
"咨询类型": string[] | [], // 客户的咨询类型,如询价、答疑等。
"意向产品": string[] | [], // 客户感兴趣的产品。
"购买异议点": string[] | [], // 客户在购买过程中提出的异议或问题。
"客户预算-预算是否充足": string | "", // 客户的预算是否充足。示例:充足, 不充足
"客户预算-总体预算金额": string | "", // 客户的总体预算金额。
"客户预算-预算明细": string | "", // 客户预算的具体明细。
"竞品信息": string | "", // 竞争对手的信息。
"客户是否有意向": string | "", // 客户是否有购买意向。示例:有意向, 无意向
"客户是否有卡点": string | "", // 客户在购买过程中是否遇到阻碍或卡点。示例:有卡点, 无卡点
"客户购买阶段": string | "", // 客户当前的购买阶段,如合同中、方案交流等。
"下一步跟进计划-参与人": string[] | [], // 下一步跟进计划中涉及的人员(客服人员)。
"下一步跟进计划-时间点": string | "", // 下一步跟进的时间点。
"下一步跟进计划-具体事项": string | "" // 下一步需要进行的具体事项。
)>
请分析以下群聊对话记录,并根据上述格式提取信息:
**对话记录:**
\`\`\`
{content}
\`\`\`
请将提取的信息以JSON格式输出。
不要添加任何澄清信息。
输出必须遵循上面的模式。
不要添加任何没有出现在模式中的附加字段。
不要随意删除字段。
**输出:**
\`\`\`
[{{
"基本信息-姓名": "姓名",
"基本信息-手机号码": "手机号码",
"基本信息-邮箱": "邮箱",
"基本信息-地区": "地区",
"基本信息-详细地址": "详细地址",
"基本信息-性别": "性别",
"基本信息-年龄": "年龄",
"基本信息-生日": "生日",
"咨询类型": ["咨询类型"],
"意向产品": ["意向产品"],
"购买异议点": ["购买异议点"],
"客户预算-预算是否充足": "充足或不充足",
"客户预算-总体预算金额": "总体预算金额",
"客户预算-预算明细": "预算明细",
"竞品信息": "竞品信息",
"客户是否有意向": "有意向或无意向",
"客户是否有卡点": "有卡点或无卡点",
"客户购买阶段": "购买阶段",
"下一步跟进计划-参与人": ["跟进计划参与人"],
"下一步跟进计划-时间点": "跟进计划时间点",
"下一步跟进计划-具体事项": "跟进计划具体事项"
}}, ...]
\`\`\`
"""
Step6:主函数启动
import json
class JsonFormatError(Exception):
def __init__(self, message):
self.message = message
super().__init__(self.message)
def convert_all_json_in_text_to_dict(text):
"""提取LLM输出文本中的json字符串"""
dicts, stack = [], []
for i in range(len(text)):
if text[i] == '{':
stack.append(i)
elif text[i] == '}':
begin = stack.pop()
if not stack:
dicts.append(json.loads(text[begin:i+1]))
return dicts
# 查看对话标签
def print_json_format(data):
"""格式化输出json格式"""
print(json.dumps(data, indent=4, ensure_ascii=False))
def check_and_complete_json_format(data):
required_keys = {
"基本信息-姓名": str,
"基本信息-手机号码": str,
"基本信息-邮箱": str,
"基本信息-地区": str,
"基本信息-详细地址": str,
"基本信息-性别": str,
"基本信息-年龄": str,
"基本信息-生日": str,
"咨询类型": list,
"意向产品": list,
"购买异议点": list,
"客户预算-预算是否充足": str,
"客户预算-总体预算金额": str,
"客户预算-预算明细": str,
"竞品信息": str,
"客户是否有意向": str,
"客户是否有卡点": str,
"客户购买阶段": str,
"下一步跟进计划-参与人": list,
"下一步跟进计划-时间点": str,
"下一步跟进计划-具体事项": str
}
if not isinstance(data, list):
raise JsonFormatError("Data is not a list")
for item in data:
if not isinstance(item, dict):
raise JsonFormatError("Item is not a dictionary")
for key, value_type in required_keys.items():
if key not in item:
item[key] = [] if value_type == list else ""
if not isinstance(item[key], value_type):
raise JsonFormatError(f"Key '{key}' is not of type {value_type.__name__}")
if value_type == list and not all(isinstance(i, str) for i in item[key]):
raise JsonFormatError(f"Key '{key}' does not contain all strings in the list")
return data
from tqdm import tqdm
retry_count = 5 # 重试次数
result = []
error_data = []
for index, data in tqdm(enumerate(test_data)):
index += 1
is_success = False
for i in range(retry_count):
try:
res = get_completions(PROMPT_EXTRACT.format(content=data["chat_text"]))
infos = convert_all_json_in_text_to_dict(res)
infos = check_and_complete_json_format(infos)
result.append({
"infos": infos,
"index": index
})
is_success = True
break
except Exception as e:
print("index:", index, ", error:", e)
continue
if not is_success:
data["index"] = index
error_data.append(data)
2it [00:42, 21.59s/it]2024-07-01 16:18:04 CST - SparkPythonSDK - ERROR - [/opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages/sparkai/llm/llm.py:687] - SparkLLMClient wait LLM api response timeout 30 seconds
10it [03:42, 21.40s/it]2024-07-01 16:21:04 CST - SparkPythonSDK - ERROR - [/opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages/sparkai/llm/llm.py:687] - SparkLLMClient wait LLM api response timeout 30 seconds
21it [07:43, 20.22s/it]2024-07-01 16:25:05 CST - SparkPythonSDK - ERROR - [/opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages/sparkai/llm/llm.py:687] - SparkLLMClient wait LLM api response timeout 30 seconds
22it [08:14, 23.55s/it]
index: 23 , error: Key '下一步跟进计划-具体事项' is not of type str
23it [08:54, 28.37s/it]2024-07-01 16:26:16 CST - SparkPythonSDK - ERROR - [/opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages/sparkai/llm/llm.py:687] - SparkLLMClient wait LLM api response timeout 30 seconds
38it [13:45, 17.50s/it]2024-07-01 16:31:06 CST - SparkPythonSDK - ERROR - [/opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages/sparkai/llm/llm.py:687] - SparkLLMClient wait LLM api response timeout 30 seconds
2024-07-01 16:31:37 CST - SparkPythonSDK - ERROR - [/opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages/sparkai/llm/llm.py:687] - SparkLLMClient wait LLM api response timeout 30 seconds
42it [16:04, 25.40s/it]2024-07-01 16:33:26 CST - SparkPythonSDK - ERROR - [/opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages/sparkai/llm/llm.py:687] - SparkLLMClient wait LLM api response timeout 30 seconds
52it [19:24, 14.75s/it]2024-07-01 16:36:46 CST - SparkPythonSDK - ERROR - [/opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages/sparkai/llm/llm.py:687] - SparkLLMClient wait LLM api response timeout 30 seconds
53it [20:04, 22.05s/it]2024-07-01 16:37:25 CST - SparkPythonSDK - ERROR - [/opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages/sparkai/llm/llm.py:687] - SparkLLMClient wait LLM api response timeout 30 seconds
55it [20:48, 22.71s/it]
# 故障数据处理
if error_data:
retry_count = 10 # 重试次数
error_data_temp = []
while True:
if error_data_temp:
error_data = error_data_temp
error_data_temp = []
for data in tqdm(error_data):
is_success = False
for i in range(retry_count):
try:
res = get_completions(PROMPT_EXTRACT.format(content=data["chat_text"]))
infos = convert_all_json_in_text_to_dict(res)
infos = check_and_complete_json_format(infos)
result.append({
"infos": infos,
"index": data["index"]
})
is_success = True
break
except Exception as e:
print("index:", index, ", error:", e)
continue
if not is_success:
error_data_temp.append(data)
if not error_data_temp:
break
result = sorted(result, key=lambda x: x["index"])
Step7:生成提交文件
# 保存输出
write_json("output.json", result)
Step8:下载 output.json
等左侧文件区域有了 output.json 文件后,点击右键,下载文件!
回到比赛提交结果咯~
🎉恭喜你已经跑通了竞赛代码!即将获得自己的第一个分数!
快快回到 速通学习手册(点击跳转) 继续完成接下去的步骤吧!
最后这个大 json 文件就不贴到这里了。提交完等一两分钟就会有结果了
之后再分析这些代码在干什么。