ivyyy0601 commited on
Commit
473378e
·
verified ·
1 Parent(s): 2489a4d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +112 -28
app.py CHANGED
@@ -1,46 +1,130 @@
 
1
  import gradio as gr
2
- from transformers import BlenderbotSmallTokenizer, BlenderbotSmallForConditionalGeneration
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
- # 选用小模型,能在免费 CPU 上跑
5
- MODEL_NAME = "facebook/blenderbot_small-90M"
6
- tokenizer = BlenderbotSmallTokenizer.from_pretrained(MODEL_NAME)
7
- model = BlenderbotSmallForConditionalGeneration.from_pretrained(MODEL_NAME)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
 
 
 
 
 
 
9
  SYSTEM_PROMPT = (
10
- "You are Ivy (Jiexin Chen). Answer briefly and friendly in first person. "
11
- "Focus on Ivy's background: HKBU CS (First Class Honours), Oxford exchange (AI/ML), "
12
- "Columbia MS Statistics (Advanced ML Track, 2025–2027); Experience: StudyCo (social media analyst), "
13
- "Wisers (data science intern, Weibo NLP sentiment). Skills: Python, Java, C, R, MATLAB, PyTorch, SQL, Tableau, Excel, HTML/CSS/JS; "
14
- "Core: ML, DL, NLP, Data Analysis. If question is unrelated to Ivy, gently steer back."
15
  )
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  def chat_fn(message, history):
18
- # 把历史合并成一个上下文小模型+免费CPU,尽量短
19
- context = SYSTEM_PROMPT + "\n\n"
20
- for user, bot in history[-5:]:
21
- context += f"User: {user}\nIvy: {bot}\n"
22
- context += f"User: {message}\nIvy:"
23
-
24
- inputs = tokenizer([context], return_tensors="pt")
25
- reply_ids = model.generate(
 
 
 
 
 
 
26
  **inputs,
27
- max_new_tokens=120,
28
- do_sample=True,
29
- top_p=0.9,
30
  temperature=0.7,
 
 
 
 
31
  pad_token_id=tokenizer.eos_token_id,
32
  )
33
- reply = tokenizer.decode(reply_ids[0], skip_special_tokens=True)
 
 
 
 
34
 
35
- # 由于我们把上下文拼成单段,这里简单抽取最后一段作为回答
36
- if "Ivy:" in reply:
37
- reply = reply.split("Ivy:")[-1].strip()
38
- return reply
39
 
 
 
 
40
  demo = gr.ChatInterface(
41
  fn=chat_fn,
42
- title="Ivy Chatbot (Free Demo)",
43
- description="Ask Ivy about education, projects, skills, and experience. (Running on free CPU, first response may take a bit.)",
 
 
 
44
  chatbot=gr.Chatbot(height=420, label="Chat"),
45
  textbox=gr.Textbox(placeholder="Ask me anything about Ivy...", autofocus=True),
46
  theme="soft",
 
1
+ # app.py — Ivy Chatbot (Free RAG Demo on CPU)
2
  import gradio as gr
3
+ import numpy as np
4
+ from transformers import (
5
+ BlenderbotSmallTokenizer,
6
+ BlenderbotSmallForConditionalGeneration
7
+ )
8
+ from sentence_transformers import SentenceTransformer
9
+
10
+ # ---------------------------
11
+ # 1) 模型与向量器(免费CPU可跑)
12
+ # ---------------------------
13
+ GEN_MODEL_NAME = "facebook/blenderbot_small-90M"
14
+ EMB_MODEL_NAME = "sentence-transformers/all-MiniLM-L6-v2" # 小、快、准
15
+
16
+ tokenizer = BlenderbotSmallTokenizer.from_pretrained(GEN_MODEL_NAME)
17
+ gen_model = BlenderbotSmallForConditionalGeneration.from_pretrained(GEN_MODEL_NAME)
18
+ embedder = SentenceTransformer(EMB_MODEL_NAME)
19
 
20
+ # ---------------------------
21
+ # 2) 你的“简历知识库” —— 可继续补充
22
+ # 规则:每一条是一个“可检索文档片段”
23
+ # ---------------------------
24
+ DOCS = [
25
+ # 教育
26
+ "Education: Columbia University, Master's in Statistics (Advanced Machine Learning Track), 2025–2027.",
27
+ "Education: Hong Kong Baptist University, B.Sc. Computer Science and Technology, First Class Honours, 2021–2025.",
28
+ "Exchange: University of Oxford, AI & Machine Learning programme, 2023.",
29
+ # 奖项
30
+ "Awards: First-class Scholarship (2021–2023), Second-class Scholarship (2024), MCM Honorable Mention (2024), Chinese Mathematical Competition Provincial 2nd Prize (2023).",
31
+ # 经验
32
+ "Experience: Social Media Analyst at StudyCo (part-time), Jan 2023–Present, Melbourne (Hybrid). Did audience/product data analysis with Python/Excel, wrote copy, edited short videos, increased Xiaohongshu followers from 3,000+ to 10,000+.",
33
+ "Experience: Data Science Intern at Wisers (May–Jul 2023), Shanghai (Hybrid). Weibo sentiment analysis; Chinese NLP preprocessing (jieba, custom dict, post classification); visualized with matplotlib, wordcloud; Tableau + MySQL real-time dashboards; SQL for data extraction.",
34
+ # 项目(挑重点)
35
+ "Project: Intelligent Retirement — Monte Carlo simulation; economic scenario generator; decision support for investment/consumption under uncertainty (2024).",
36
+ "Project: Predicting Intern Recruitment with Bayesian Networks — VE & Clique Tree inference; DAG with ~12 key nodes; interactive UI to explore outcomes (2024).",
37
+ "Project: LLM Check System — Flask + MySQL + SQLAlchemy; OOA/OOD; unit & integration testing; frontend HTML/CSS/JS (2024).",
38
+ "Project: Twitter Sentiment Analysis — NLP preprocessing; RNN/LSTM/BERT, best accuracy 89% (2024).",
39
+ "Project: Long-text abstraction & character relationship (T5 + PageRank + PySpark) — build character networks, accelerate top-20 character identification (2023).",
40
+ "Project: Online Restaurant Ordering System — ER with 10 entities/15 relationships; VIP, live order status, personalized recommendations; >60k users/products (2022).",
41
+ "Project: Path Planning for Mobile Robots — Q-learning vs DQN; DQN reached 94% in complex mazes (PyTorch) (2022).",
42
+ # 技能
43
+ "Skills: Python, Java, C, R, MATLAB; Web: HTML, CSS, JavaScript; Frameworks/Tools: PyTorch, Tableau, SQL, SPSS, Excel; Core: Machine Learning, Deep Learning, NLP, Data Analysis.",
44
+ ]
45
 
46
+ # 预生成向量
47
+ DOC_EMBS = embedder.encode(DOCS, normalize_embeddings=True)
48
+
49
+ # ---------------------------
50
+ # 3) Prompt 组件
51
+ # ---------------------------
52
  SYSTEM_PROMPT = (
53
+ "You are Ivy (Jiexin Chen). Answer in FIRST PERSON, concise, friendly, professional. "
54
+ "Only talk about Ivy's background, education, projects, skills, and experience. "
55
+ "If asked something unrelated, briefly steer back to career topics.\n"
 
 
56
  )
57
 
58
+ STYLE_HINT = (
59
+ "Style: 2–5 short sentences. Use concrete facts from the provided context if relevant. "
60
+ "If the information is missing, say it briefly and suggest related areas I can talk about."
61
+ )
62
+
63
+ def build_prompt(question: str, retrieved_snippets: list[str]) -> str:
64
+ context_block = "\n".join(f"- {s}" for s in retrieved_snippets)
65
+ prompt = (
66
+ f"{SYSTEM_PROMPT}\n"
67
+ f"{STYLE_HINT}\n\n"
68
+ f"Context:\n{context_block}\n\n"
69
+ f"User: {question}\n"
70
+ f"Ivy:"
71
+ )
72
+ return prompt
73
+
74
+ # ---------------------------
75
+ # 4) 简���检索器(余弦相似度)
76
+ # ---------------------------
77
+ def retrieve(query: str, top_k: int = 4) -> list[str]:
78
+ q_emb = embedder.encode([query], normalize_embeddings=True)[0]
79
+ sims = (DOC_EMBS @ q_emb) # 余弦相似度(已归一化)
80
+ idx = np.argsort(-sims)[:top_k]
81
+ return [DOCS[i] for i in idx]
82
+
83
+ # ---------------------------
84
+ # 5) 对话函数:检索 → 组 Prompt → 生成
85
+ # ---------------------------
86
  def chat_fn(message, history):
87
+ # 最近几轮加入问题提示帮助检索
88
+ history_tail = " ".join([u for u, _ in history[-3:]]) if history else ""
89
+ query = (message or "").strip()
90
+ full_query = (query + " " + history_tail).strip() or "Ivy summary"
91
+
92
+ # 检索
93
+ retrieved = retrieve(full_query, top_k=4)
94
+
95
+ # 构造提示词
96
+ prompt = build_prompt(query, retrieved)
97
+
98
+ # 生成
99
+ inputs = tokenizer([prompt], return_tensors="pt")
100
+ output_ids = gen_model.generate(
101
  **inputs,
102
+ max_new_tokens=140,
 
 
103
  temperature=0.7,
104
+ top_p=0.9,
105
+ do_sample=True,
106
+ no_repeat_ngram_size=3,
107
+ repetition_penalty=1.15,
108
  pad_token_id=tokenizer.eos_token_id,
109
  )
110
+ text = tokenizer.decode(output_ids[0], skip_special_tokens=True)
111
+
112
+ # 抽取 "Ivy:" 之后的回答
113
+ if "Ivy:" in text:
114
+ text = text.split("Ivy:", 1)[-1].strip()
115
 
116
+ return text
 
 
 
117
 
118
+ # ---------------------------
119
+ # 6) UI
120
+ # ---------------------------
121
  demo = gr.ChatInterface(
122
  fn=chat_fn,
123
+ title="Ivy Chatbot (Free RAG Demo)",
124
+ description=(
125
+ "Ask me about my education, projects, skills, and experience. "
126
+ "Runs on free CPU with a small model + retrieval for better accuracy."
127
+ ),
128
  chatbot=gr.Chatbot(height=420, label="Chat"),
129
  textbox=gr.Textbox(placeholder="Ask me anything about Ivy...", autofocus=True),
130
  theme="soft",