今天接到个新工作,公司入职离职的同事开启和禁用 Gitlab 账号要我来维护。
也就是入职后需要 Gitlab 的话,主管或者员工自己会给我发个邮件, 我去增加一个 Gitlab 账号,员工离职的时候还是会收到一封邮件,然后去关闭账号。
既然万物即可LLM,那我就用 LLM 实现下,先看下效果图:
流程图
今天实现的功能主要流程如下:
现状
先看下我们收到的邮件吧,比如注销邮件的,
以上内容为虚拟信息
当然发件人的内容五花八门,我就不举例了。
实现过程
再看看流程图,我们主要做以下几件事:
• 定时拉去邮件,解析然后入库
• 这么做是为了方便结构化查询
• 客户端解析和 UI 优化
• LangChain 集成新的工具实现上面需求
MailSQL
我们先定义一个 MailSQL,定义数据库文件:
class MailSqlite(BaseModel):
db_file: str = 'emails.db'
然后定义数据库连接:
@property
def conn(self) -> Connection:
try:
conn = sqlite3.connect(self.db_file)
except:
raise ValueError("数据库创建失败")
return conn
创建数据库表,记录 邮件的所有信息:
def create_table(self):
conn = self.conn
cursor = conn.cursor()
cursor.execute(
"""CREATE TABLE IF NOT EXISTS emails (
id INTEGER PRIMARY KEY,
from_text TEXT,
from_email TEXT,
from_name TEXT,
to_emails TEXT,
subject TEXT,
subject_charset TEXT,
cc TEXT,
date DATE,
date_beijing TEXT,
body TEXT,
body_charset TEXT,
multipart INTEGER,
description TEXT
)"""
)
conn.commit()
保存邮件的方法:
def save_mail(self, mail: Email):
conn = self.conn
cursor = conn.cursor()
cursor.execute(
"""INSERT INTO emails (id, from_text, from_name, from_email, to_emails, subject, subject_charset, cc,
date, date_beijing, body, multipart, description)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT (id) DO UPDATE
SET description=?
""",
(
mail.id,
mail.from_text,
mail.from_name,
mail.from_email,
mail.to_emails,
mail.subject,
mail.subject_charset,
mail.cc,
mail.date,
mail.date_beijing,
mail.body,
mail.multipart,
mail.description,
# update
mail.description,
),
)
conn.commit()
最后是数据库的查询,因为我们只处理公司内部邮件,所有这里可以限制下发件人的条件:
def account_mails(self, limit:int = 3):
sql = "select id, subject, date, description from emails where from_email like '%@wings.com' order by id desc limit " + str(limit)
return self.conn.cursor().execute(sql).fetchall()
MailGit 工具
接下来实现 MailGit 工具,(描述使用中文效果相同)。
class MailCheckUser(BaseMailTool, ABC):
name: str = "mail-checker"
description: str = (
"Use this tool to find emails to apply for an gitlab or git account."
" Returns the email id, subject and sender."
)
return_direct = True
判断逻辑
邮件的意图判断,我们使用 LLM 来实现,这个是本次所以工作的核心:
prompt = """帮我根据邮件信息判断,是不是要申请或者注销 Git 或者 gitlab 账号,员工离职都需要注销账号,
- 如果是申请账号邮件:请告诉我申请人的信息,如果有多人申请一起以下面格式 JSON 回复我,不要回复多余单词:
```
[
{
"类型": "创建账号",
"姓名": "<name>",
"邮件": "<email>",
"部门": "<department>",
"操作": ""
}
]
```
- 如果是注销账号邮件:请以下面的格式 JSON 回复我,不要回复多余单词:
```
[
{
"类型": "禁用账号",
"姓名": "<name>",
"邮件": "<email>",
"操作": ""
}
]
```
- 如果不是申请或者注销账号,请以下面的格式 JSON 回复我,不要回复多余单词:
```
{
"类型": "other"
}
```
你需要判断邮件相关内容如下:
```
%s
```
"""
使用 OpenAI 或者其他的 LLM 来执行 Prompt:
result_json = openai.predict(self.prompt % description)
最后同样转成 Markdown 返回:
def _run(
self,
number: int = 10,
) -> str:
"""Run the tool."""
mails = self.account_mails()
md = tabulate(mails, headers='keys', tablefmt='pipe')
print(md)
return md
运行看下效果:
--- END ---

