搭建自己的ai客服
本节介绍的ai客服搭建主要服务于初学者,一套下来希望你对前进的道路更加坚定!那我们开始吧
1.准备工作
1.Agent角色设定
随心设计好Agent的角色,并完成相应的个性化文档供大模型学习
这里的话建议提前构思好,写好专家文档txt,可以与我不一样,无所谓的。
2.准备好openai的key
本文中调用的是openai的gpt-3.5-turbo,经济实惠
2.搭建flask框架(pycharm)
这里的话代码自己研究研究,可以拓展tools的,不懂问问GPT
1.安装环境
pip install -r requirements.txt
requirements.txt内容:
annotated-types==0.6.0
anyio==3.7.1
blinker==1.7.0
certifi==2023.7.22
charset-normalizer==3.3.2
click==8.1.7
distro==1.8.0
exceptiongroup==1.1.3
flask==3.0.0
functions==0.7.0
h11==0.14.0
httpcore==1.0.2
httpx==0.25.1
idna==3.4
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.3
openai==1.2.3
packaging==23.2
pydantic==2.4.2
pydantic-core==2.10.1
requests==2.31.0
sniffio==1.3.0
tqdm==4.66.1
typing-extensions==4.8.0
urllib3==2.1.0
werkzeug==3.0.1
2.app.py源码(框架运行)
import json
import os
import time
from flask import Flask, request, jsonify
import openai
from openai import OpenAI
import functions
from packaging import version
required_version = version.parse("1.1.1")
current_version = version.parse(openai.__version__)
OPENAI_API_KEY = '<填你自己的openai-key>'
#OPENAI_API_BASE ='https://api.novelnetwork.online/v1'
if current_version < required_version:
raise ValueError(
f"Error: OpenAI version {openai.__version__} is less than the required version 1.1.1"
)
else:
print("OpenAI version is compatible.")
# Flask常规操作
app = Flask(__name__)
# KEY写自己的
client = OpenAI(api_key=OPENAI_API_KEY)#,base_url=OPENAI_API_BASE)
# 加载助手
assistant_id = functions.create_assistant(
client) # this function comes from "functions.py"
# 得到对话请求
@app.route('/start', methods=['GET'])
def start_conversation():
print("Starting a new conversation...")
thread = client.beta.threads.create()
print(f"New thread created with ID: {thread.id}")
return jsonify({"thread_id": thread.id})
# 调用GPT和API产生结果
@app.route('/chat', methods=['POST'])
def chat():
data = request.json
thread_id = data.get('thread_id')
user_input = data.get('message', '')
if not thread_id:
print("Error: Missing thread_id")
return jsonify({"error": "Missing thread_id"}), 400
print(f"Received message: {user_input} for thread ID: {thread_id}")
client.beta.threads.messages.create(thread_id=thread_id,
role="user",
content=user_input)
run = client.beta.threads.runs.create(thread_id=thread_id,
assistant_id=assistant_id)
# 是否需要调用API
while True:
run_status = client.beta.threads.runs.retrieve(thread_id=thread_id,
run_id=run.id)
# print(f"Run status: {run_status.status}")
if run_status.status == 'completed':
break
elif run_status.status == 'requires_action':
# 处理各种API
for tool_call in run_status.required_action.submit_tool_outputs.tool_calls:
if tool_call.function.name == "create_lead":
# Process lead creation
arguments = json.loads(tool_call.function.arguments)
output = functions.create_lead(arguments["name"], arguments["phone"],
arguments["wechat"], arguments["address"], arguments["summary"], arguments["intention"])
client.beta.threads.runs.submit_tool_outputs(thread_id=thread_id,
run_id=run.id,
tool_outputs=[{
"tool_call_id":
tool_call.id,
"output":
json.dumps(output)
}])
time.sleep(1) # Wait for a second before checking again
# 返回结果
messages = client.beta.threads.messages.list(thread_id=thread_id)
response = messages.data[0].content[0].text.value
print(f"Assistant response: {response}")
return jsonify({"response": response})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
3.functions.py源码
import json
import requests
import os
from openai import OpenAI
import openai
from prompts import assistant_instructions
#注意你复制完可能要加上Bearer这个前缀
AIRTABLE_API_KEY = '<填你自己的airtable-key>'
OPENAI_API_KEY = '<填你自己的openai-key>'
#OPENAI_API_BASE ='https://api.novelnetwork.online/v1'
# Init OpenAI Client
client = OpenAI(api_key=OPENAI_API_KEY)#,base_url=OPENAI_API_BASE)
# 创建一个表单数据
def create_lead(name, phone, wechat,address,summary,intention):
url = "<替换成自己的在线表单地址>" # 替换自己的(后续有讲)
headers = {
"Authorization": AIRTABLE_API_KEY,
"Content-Type": "application/json"
}
data = {
"records": [{
"fields": {
"Name": name,
"Phone": phone,
"Wechat": wechat,
"Address": address,
"Summary": summary,
"Intention": intention
}
}]
}
response = requests.post(url, headers=headers, json=data)
if response.status_code == 200:
print("Lead created successfully.")
return response.json()
else:
print(f"Failed to create lead: {response.text}")
# 创建助手
def create_assistant(client):
assistant_file_path = 'assistant.json'
# 如果json不存在就创建一个,如果换本地知识库要删除原来的
if os.path.exists(assistant_file_path):
with open(assistant_file_path, 'r') as file:
assistant_data = json.load(file)
assistant_id = assistant_data['assistant_id']
print("Loaded existing assistant ID.")
else:
file = client.files.create(file=open("<填写ai要学习的文档地址>", "rb"),
purpose='assistants')
assistant = client.beta.assistants.create(
# 这里面要调用你写好的指令和接下来会用到的API
instructions=assistant_instructions,
model="gpt-3.5-turbo",
tools=[
{
"type": "retrieval" # This adds the knowledge base as a tool
},
{
"type": "function", # 写表单
"function": {
"name": "create_lead",
"description":
"Capture lead details and save to Airtable.",
"parameters": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name of the lead."
},
"phone": {
"type": "string",
"description": "Phone number of the lead."
},
"wechat": {
"type": "string",
"description": "Phone number of the lead."
},
"address": {
"type": "string",
"description": "Address of the lead."
},
"summary": {
"type": "string",
"description": "Summarize students’ questions."
},
"intention": {
"type": "string",
"description": "Students’ purchase intention."
}
},
"required": ["name", "phone","wechat","address","summary","intention"]
}
}
}
],
file_ids=[file.id])
# 要创建一个新的json
with open(assistant_file_path, 'w') as file:
json.dump({'assistant_id': assistant.id}, file)
print("Created a new assistant and saved the ID.")
assistant_id = assistant.id
return assistant_id
4.prompts.py源码
assistant_instructions = """
本助手的角色是金牌销售员,擅长根据你学习到的销售话语与客户进行交流。请你用中文描述学员所咨询问题和答案以及客户的购买意向是否强烈,以便销售团队进行进一步营销,不要发给客户我们已经记录信息了。注意每回答一次学员的问题都尽可能要求他留下详细的信息,因为你的核心目的是销售,只有获取到手机号或者微信号
这两个关键信息后,本助手才需要调用create_lead函数来生成表单,需要向该函数提供学员的姓名,电话,微信号,地址,总结的问题和购买意向这六项参数,如果部分信息未知可以用null来替换;如果客户未提供关键信息则不需要调用。
"""
设置ai的提示词,可自行修改,注意写好prompt的三要素:指令、上下文、角色。
3.运行flask并发布公网
1.运行
flask框架正常运行的样式,这里没有直接写与前端交互的代码,所以第一个http请求会报404,因为我们这个ai的需求其实是嵌入式的(嵌入网页里头,后面会讲嵌入式的前端怎么处理)
2.发布公网
参考文章网址https://blog.csdn.net/fq157856469/article/details/135271176?ops_request_misc=&request_id=&biz_id=102&utm_term=flask%E6%90%AD%E5%BB%BA%E5%85%AC%E7%BD%91%E6%9C%8D%E5%8A%A1%E5%99%A8&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-0-135271176.142v100pc_search_result_base1&spm=1018.2226.3001.4187
1.注册Cpolar(内网穿透)
由于我们的flask框架运行在局域网,要实现公网的ai嵌入需要内网穿透(这里需要花99块买个二级子域名的权限,舍不着孩子套不着ai)
点击官网地址进行注册下载客户端
点进去
进入创建隧道
创建隧道后,隧道名称任意修改,本地地址改为flask运行的端口,我的是5000,其他不动。
进入隧道列表查看
点击编辑
点击二级子域名,sub Domain随便填,地区与创建时对应,我一开始没冲钱,想着白嫖,后面才知道随机域名对现实生产环境没什么卵用,要二级子域名公网的地址才能稳定,这里就麻烦了一点。你们要是提前冲好,一开始创建时就可以设置二级子域名了。
这就是发布到公网的地址,你可以上浏览器搜搜,能搜出来(可能是404 not found 别忘了前端没做呢)就行
4.前端嵌入实现
1.注册Voiceflow
这是一个拖拽式的模块化的前端生成工具,这里是他的使用说明
https://learn.voiceflow.com/hc/en-us/articles/10569376208781-Launching-to-your-Website
了解了他的相关作用我们创建一个Agent并进入他的工作空间
2.逻辑编写
按如下方式连线,整个流程按照箭头指向来完成
注意几个细节
/start前放你发布到公网的网址
下面的Capture Response不要改动,这是传参的
可以点击send Request来看看能不能发送get请求,200就ok
同样的/chat前网址做一个替换
其余保持不变
也可以发送一下请求看看可以没
5.外部API的调用
1.注册Airtable
https://airtable.com/
2.创表
新建一个工作区间,并进行如图所示的创表
注意
每个标签的数据格式都要时text的(single还是long都没事)
3.获取表单的token值
点击这个
给读写权限并制定表名,创建token
记得保存好,只会出现一次
然后回到表单位置,看网址部分
进行替换
4.用postman测试api联通
在网上下载安装postman
进入postman新建connections
把刚刚换好的地址填进去,发送
第一次发送一般不成功,还要点击headers(7)这里添加
key值不变动,value换成你刚刚获取的token值,对Bearer 后的进行替换,再次发送,出现200就ok
一般作项目开发都是先想好要调哪些api,然后测试api连不连得上,然后才应用到代码中,postman就显得很重要了
6.在线调试
重新回到Voiceflow,点击run,点击agent test进行测试,在pycharm中也可以进行调试
这里的话就多根据ai反馈调整prompt的书写,我的prompt写的不咋地,可能很多业务场景都给不出很好的回复,这也是以后我们学习大模型微调的意义
这里的话提示词可能设的不大好,summary和intention都是英文,大家自己改改看,我这里就演示下流程哈
7.部署上线
这里当然不可能直接部署到别人网站去,我们可以随便找个html文件
1.集成voiceflow的agent
发布版本,并点击弹窗的链接
general和appearance可以调整ai嵌入的样式,自行修改
复制这个黑框框的内容
2.嵌入到HTML中
随便打开一个html,把刚刚复制的嵌入到前
再次点击
可以看到右下角出现了个小圆圈,点击即可进入ai会话
恭喜你已经全部完成啦!!!!