wanggenfu commited on
Commit
ab2cf61
·
verified ·
1 Parent(s): 92f5d84

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +272 -0
app.py ADDED
@@ -0,0 +1,272 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+ from typing import TypedDict, List, Dict, Any, Optional
4
+ from langgraph.graph import StateGraph, START, END
5
+ # from langchain_openai import ChatOpenAI
6
+ from langchain_core.messages import HumanMessage, AIMessage
7
+ # from llama_index.llms.huggingface_api import HuggingFaceInferenceAPI
8
+ from huggingface_hub import InferenceClient
9
+
10
+ class EmailState(TypedDict):
11
+ # 正在处理的电子邮件
12
+ email: Dict[str, Any] # 包含主题、发件人、正文等。
13
+
14
+ # 分析与决策
15
+ is_spam: Optional[bool]
16
+
17
+ spam_reason: Optional[str]
18
+
19
+ email_category: Optional[str]
20
+
21
+ # 响应生成
22
+ draft_response: Optional[str]
23
+
24
+ # 处理元数据
25
+ messages: List[Dict[str, Any]] # 跟踪与 LLM 的对话以进行分析
26
+
27
+ # Initialize our LLM
28
+ # model = ChatOpenAI(temperature=0)
29
+ # model = HuggingFaceInferenceAPI(model_name="Qwen/Qwen2.5-Coder-32B-Instruct")
30
+
31
+ model = InferenceClient(
32
+ model="Qwen/Qwen2.5-Coder-32B-Instruct",
33
+ timeout=30 # 超时时间,避免长文本生成卡住
34
+ )
35
+
36
+ def query_llm(prompt: str):
37
+ response = model.chat.completions.create(messages=[
38
+ {
39
+ "role": "user",
40
+ "content": prompt
41
+ }],temperature=0)
42
+ return response.choices[0].message
43
+
44
+ def read_email(state: EmailState):
45
+ """Alfred reads and logs the incoming email"""
46
+ email = state["email"]
47
+
48
+ # 在这里我们可能会做一些初步的预处理
49
+ print(f"Alfred is processing an email from {email['sender']} with subject: {email['subject']}")
50
+
51
+ # 这里不需要更改状态
52
+ return {}
53
+
54
+
55
+ def classify_email(state: EmailState):
56
+ """Alfred uses an LLM to determine if the email is spam or legitimate"""
57
+ email = state["email"]
58
+
59
+ # 为 LLM 准备提示
60
+ prompt = f"""
61
+ As Alfred the butler, analyze this email and determine if it is spam or legitimate.
62
+
63
+ Email:
64
+ From: {email['sender']}
65
+ Subject: {email['subject']}
66
+ Body: {email['body']}
67
+
68
+ First, determine if this email is spam. If it is spam, explain why.
69
+ If it is legitimate, categorize it (inquiry, complaint, thank you, etc.).
70
+
71
+ Please answer strictly in the following format:
72
+ Is spam:
73
+ Reason for spam:
74
+ Email category: inquiry, complaint, thank you, spam, etc.
75
+ """
76
+
77
+ # Call the LLM
78
+ # messages = [HumanMessage(content=prompt)]
79
+ response = query_llm(prompt)
80
+
81
+ # 解析响应的简单逻辑(在实际应用中,您需要更强大的解析)
82
+ response_text = response.content.lower()
83
+ # print(f"test response_text:{response_text}")
84
+ is_spam = "is spam: yes" in response_text
85
+ # print(f"test is_spam:{is_spam and "reasoning:" in response_text}")
86
+ # print(f"test reasoning:{response_text.split("reasoning:")[1].strip()}")
87
+ # 如果是垃圾邮件,请提取原因,输出的格式可能不同,需要根据提示词固定格式。
88
+ spam_reason = None
89
+ spam_reason_keyword="reason for spam:"
90
+ if is_spam and spam_reason_keyword in response_text:
91
+ spam_reason = response_text.split(spam_reason_keyword)[1].strip()
92
+
93
+ # print(f"test spam_reason:{spam_reason}")
94
+
95
+ # 确定类别是否合法
96
+ email_category = None
97
+ if not is_spam:
98
+ categories = ["inquiry", "complaint", "thank you", "request", "information"]
99
+ for category in categories:
100
+ if category in response_text:
101
+ email_category = category
102
+ break
103
+
104
+ # 更新消息以进行追踪
105
+ new_messages = state.get("messages", []) + [
106
+ {"role": "user", "content": prompt},
107
+ {"role": "assistant", "content": response.content}
108
+ ]
109
+
110
+ # 返回状态更新
111
+ return {
112
+ "is_spam": is_spam,
113
+ "spam_reason": spam_reason,
114
+ "email_category": email_category,
115
+ "messages": new_messages
116
+ }
117
+
118
+ def route_email(state: EmailState) -> str:
119
+ """Determine the next step based on spam classification"""
120
+ # print(f"route_email,state={state}")
121
+ if state["is_spam"]:
122
+ return "spam"
123
+ else:
124
+ return "legitimate"
125
+
126
+
127
+ def handle_spam(state: EmailState):
128
+ """Alfred discards spam email with a note"""
129
+ # print(f"handle_spam,state={state}")
130
+ # print(f"is_spam:{state.get("is_spam","none")}")
131
+ print(f"Alfred has marked the email as spam. Reason: {state.get("spam_reason","none")}")
132
+ print("The email has been moved to the spam folder.")
133
+
134
+ # 我们已处理完这封电子邮件
135
+ return {}
136
+
137
+ def draft_response(state: EmailState):
138
+ """Alfred drafts a preliminary response for legitimate emails"""
139
+ email = state["email"]
140
+ category = state["email_category"] or "general"
141
+
142
+ # 为 LLM 准备提示词
143
+ prompt = f"""
144
+ As Alfred the butler, draft a polite preliminary response to this email.
145
+
146
+ Email:
147
+ From: {email['sender']}
148
+ Subject: {email['subject']}
149
+ Body: {email['body']}
150
+
151
+ This email has been categorized as: {category}
152
+
153
+ Draft a brief, professional response that Mr. Hugg can review and personalize before sending.
154
+ """
155
+
156
+ # Call the LLM
157
+ # messages = [HumanMessage(content=prompt)]
158
+ response = query_llm(prompt)
159
+
160
+ # 更新消息以进行追踪
161
+ new_messages = state.get("messages", []) + [
162
+ {"role": "user", "content": prompt},
163
+ {"role": "assistant", "content": response.content}
164
+ ]
165
+
166
+ # 返回状态更新
167
+ return {
168
+ "draft_response": response.content,
169
+ "messages": new_messages
170
+ }
171
+
172
+ def notify_mr_hugg(state: EmailState):
173
+ """Alfred notifies Mr. Hugg about the email and presents the draft response"""
174
+ email = state["email"]
175
+
176
+ print("\n" + "="*50)
177
+ print(f"Sir, you've received an email from {email['sender']}.")
178
+ print(f"Subject: {email['subject']}")
179
+ print(f"Category: {state['email_category']}")
180
+ print("\nI've prepared a draft response for your review:")
181
+ print("-"*50)
182
+ print(state["draft_response"])
183
+ print("="*50 + "\n")
184
+
185
+ # 我们已处理完这封电子邮件
186
+ return {}
187
+
188
+
189
+
190
+ # 创建 graph
191
+ email_graph = StateGraph(EmailState)
192
+
193
+ # 添加 nodes
194
+ email_graph.add_node("read_email", read_email)
195
+ email_graph.add_node("classify_email", classify_email)
196
+ email_graph.add_node("handle_spam", handle_spam)
197
+ email_graph.add_node("draft_response", draft_response)
198
+ email_graph.add_node("notify_mr_hugg", notify_mr_hugg)
199
+
200
+ # 添加 edges - 定义流程
201
+ email_graph.add_edge(START, "read_email")
202
+ email_graph.add_edge("read_email", "classify_email")
203
+
204
+ # 从 classify_email 添加条件分支
205
+ email_graph.add_conditional_edges(
206
+ "classify_email",
207
+ route_email,
208
+ {
209
+ "spam": "handle_spam",
210
+ "legitimate": "draft_response"
211
+ }
212
+ )
213
+
214
+ # 添加最后的 edges
215
+ email_graph.add_edge("handle_spam", END)
216
+ email_graph.add_edge("draft_response", "notify_mr_hugg")
217
+ email_graph.add_edge("notify_mr_hugg", END)
218
+
219
+ # 编译 graph
220
+ compiled_graph = email_graph.compile()
221
+
222
+
223
+ # 合法电子邮件示例
224
+ legitimate_email = {
225
+ "sender": "john.smith@example.com",
226
+ "subject": "Question about your services",
227
+ "body": "Dear Mr. Hugg, I was referred to you by a colleague and I'm interested in learning more about your consulting services. Could we schedule a call next week? Best regards, John Smith"
228
+ }
229
+
230
+ # 垃圾邮件示例
231
+ spam_email = {
232
+ "sender": "winner@lottery-intl.com",
233
+ "subject": "YOU HAVE WON $5,000,000!!!",
234
+ "body": "CONGRATULATIONS! You have been selected as the winner of our international lottery! To claim your $5,000,000 prize, please send us your bank details and a processing fee of $100."
235
+ }
236
+
237
+ # # 处理合法电子邮件
238
+ # print("\nProcessing legitimate email...")
239
+ # legitimate_result = compiled_graph.invoke({
240
+ # "email": legitimate_email,
241
+ # "is_spam": None,
242
+ # "spam_reason": None,
243
+ # "email_category": None,
244
+ # "draft_response": None,
245
+ # "messages": []
246
+ # })
247
+
248
+ # 处理垃圾邮件
249
+ # print("\nProcessing spam email...")
250
+ # spam_result = compiled_graph.invoke({
251
+ # "email": spam_email,
252
+ # "is_spam": None,
253
+ # "spam_reason": None,
254
+ # "email_category": None,
255
+ # "draft_response": None,
256
+ # "messages": []
257
+ # })
258
+
259
+ def classify_email(email):
260
+ result = compiled_graph.invoke({
261
+ "email": email,
262
+ "is_spam": None,
263
+ "spam_reason": None,
264
+ "email_category": None,
265
+ "draft_response": None,
266
+ "messages": []
267
+ })
268
+ return f"is_spam:{result.get("is_spam")}\nspam_reason:{result.get("spam_reason")}"
269
+
270
+
271
+ demo = gr.Interface(fn=greet, inputs="text", outputs="text")
272
+ demo.launch()