bayuramadhans commited on
Commit
b4573d1
·
verified ·
1 Parent(s): 1b6b14f

Upload folder using huggingface_hub

Browse files
Files changed (6) hide show
  1. .gitignore +6 -0
  2. README.md +3 -9
  3. app.py +139 -0
  4. me/ats-cv-bayu-ramadhan.pdf +93 -0
  5. me/summary.txt +6 -0
  6. requirements.txt +6 -0
.gitignore ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ community_contributions/*
2
+ me/linkedin.pdf
3
+ 1_lab1.ipynb
4
+ 2_lab2.ipynb
5
+ 3_lab3.ipynb
6
+ 4_lab4.ipynb
README.md CHANGED
@@ -1,12 +1,6 @@
1
  ---
2
- title: Virtual Me
3
- emoji: 🐢
4
- colorFrom: blue
5
- colorTo: red
6
- sdk: gradio
7
- sdk_version: 5.47.0
8
  app_file: app.py
9
- pinned: false
 
10
  ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: virtual-me
 
 
 
 
 
3
  app_file: app.py
4
+ sdk: gradio
5
+ sdk_version: 5.34.2
6
  ---
 
 
app.py ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from dotenv import load_dotenv
2
+ from openai import OpenAI
3
+ import json
4
+ import os
5
+ import requests
6
+ from pypdf import PdfReader
7
+ import gradio as gr
8
+
9
+
10
+ load_dotenv(override=True)
11
+
12
+ def push(text):
13
+ requests.post(
14
+ "https://api.pushover.net/1/messages.json",
15
+ data={
16
+ "token": os.getenv("PUSHOVER_TOKEN"),
17
+ "user": os.getenv("PUSHOVER_USER"),
18
+ "message": text,
19
+ }
20
+ )
21
+
22
+
23
+ def record_user_details(email, name="Name not provided", notes="not provided"):
24
+ push(f"Recording {name} with email {email} and notes {notes}")
25
+ return {"recorded": "ok"}
26
+
27
+ def record_unknown_question(question):
28
+ push(f"Recording {question}")
29
+ return {"recorded": "ok"}
30
+
31
+ record_user_details_json = {
32
+ "name": "record_user_details",
33
+ "description": "Use this tool to record that a user is interested in being in touch and provided an email address",
34
+ "parameters": {
35
+ "type": "object",
36
+ "properties": {
37
+ "email": {
38
+ "type": "string",
39
+ "description": "The email address of this user"
40
+ },
41
+ "name": {
42
+ "type": "string",
43
+ "description": "The user's name, if they provided it"
44
+ }
45
+ ,
46
+ "notes": {
47
+ "type": "string",
48
+ "description": "Any additional information about the conversation that's worth recording to give context"
49
+ }
50
+ },
51
+ "required": ["email"],
52
+ "additionalProperties": False
53
+ }
54
+ }
55
+
56
+ record_unknown_question_json = {
57
+ "name": "record_unknown_question",
58
+ "description": "Always use this tool to record any question that couldn't be answered as you didn't know the answer",
59
+ "parameters": {
60
+ "type": "object",
61
+ "properties": {
62
+ "question": {
63
+ "type": "string",
64
+ "description": "The question that couldn't be answered"
65
+ },
66
+ },
67
+ "required": ["question"],
68
+ "additionalProperties": False
69
+ }
70
+ }
71
+
72
+ tools = [{"type": "function", "function": record_user_details_json},
73
+ {"type": "function", "function": record_unknown_question_json}]
74
+
75
+
76
+ class Me:
77
+
78
+ def __init__(self):
79
+ self.openrouter_api_key = os.getenv('OPENROUTER_API_KEY')
80
+ self.client = OpenAI(
81
+ api_key=self.openrouter_api_key,
82
+ base_url="https://openrouter.ai/api/v1"
83
+ )
84
+
85
+ self.name = "Bayu Ramadhan Shafiyuddin"
86
+ reader = PdfReader("me/ats-cv-bayu-ramadhan.pdf")
87
+ self.linkedin = ""
88
+ for page in reader.pages:
89
+ text = page.extract_text()
90
+ if text:
91
+ self.linkedin += text
92
+ with open("me/summary.txt", "r", encoding="utf-8") as f:
93
+ self.summary = f.read()
94
+
95
+
96
+ def handle_tool_call(self, tool_calls):
97
+ results = []
98
+ for tool_call in tool_calls:
99
+ tool_name = tool_call.function.name
100
+ arguments = json.loads(tool_call.function.arguments)
101
+ print(f"Tool called: {tool_name}", flush=True)
102
+ tool = globals().get(tool_name)
103
+ result = tool(**arguments) if tool else {}
104
+ results.append({"role": "tool","content": json.dumps(result),"tool_call_id": tool_call.id})
105
+ return results
106
+
107
+ def system_prompt(self):
108
+ system_prompt = f"You are acting as {self.name}. You are answering questions on {self.name}'s website, \
109
+ particularly questions related to {self.name}'s career, background, skills and experience. \
110
+ Your responsibility is to represent {self.name} for interactions on the website as faithfully as possible. \
111
+ You are given a summary of {self.name}'s background and LinkedIn profile which you can use to answer questions. \
112
+ Be professional and engaging, as if talking to a potential client or future employer who came across the website. \
113
+ If you don't know the answer to any question, use your record_unknown_question tool to record the question that you couldn't answer, even if it's about something trivial or unrelated to career. \
114
+ If the user is engaging in discussion, try to steer them towards getting in touch via email; ask for their email and record it using your record_user_details tool. "
115
+
116
+ system_prompt += f"\n\n## Summary:\n{self.summary}\n\n## LinkedIn Profile:\n{self.linkedin}\n\n"
117
+ system_prompt += f"With this context, please chat with the user, always staying in character as {self.name}."
118
+ return system_prompt
119
+
120
+ def chat(self, message, history):
121
+ messages = [{"role": "system", "content": self.system_prompt()}] + history + [{"role": "user", "content": message}]
122
+ done = False
123
+ while not done:
124
+ response = self.client.chat.completions.create(model="deepseek/deepseek-chat-v3.1:free", messages=messages, tools=tools)
125
+ if response.choices[0].finish_reason=="tool_calls":
126
+ message = response.choices[0].message
127
+ tool_calls = message.tool_calls
128
+ results = self.handle_tool_call(tool_calls)
129
+ messages.append(message)
130
+ messages.extend(results)
131
+ else:
132
+ done = True
133
+ return response.choices[0].message.content
134
+
135
+
136
+ if __name__ == "__main__":
137
+ me = Me()
138
+ gr.ChatInterface(me.chat, type="messages").launch()
139
+
me/ats-cv-bayu-ramadhan.pdf ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ %PDF-1.4
2
+ %���� ReportLab Generated PDF document http://www.reportlab.com
3
+ 1 0 obj
4
+ <<
5
+ /F1 2 0 R /F2 3 0 R
6
+ >>
7
+ endobj
8
+ 2 0 obj
9
+ <<
10
+ /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
11
+ >>
12
+ endobj
13
+ 3 0 obj
14
+ <<
15
+ /BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font
16
+ >>
17
+ endobj
18
+ 4 0 obj
19
+ <<
20
+ /Contents 9 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 8 0 R /Resources <<
21
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
22
+ >> /Rotate 0 /Trans <<
23
+
24
+ >>
25
+ /Type /Page
26
+ >>
27
+ endobj
28
+ 5 0 obj
29
+ <<
30
+ /Contents 10 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 8 0 R /Resources <<
31
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
32
+ >> /Rotate 0 /Trans <<
33
+
34
+ >>
35
+ /Type /Page
36
+ >>
37
+ endobj
38
+ 6 0 obj
39
+ <<
40
+ /PageMode /UseNone /Pages 8 0 R /Type /Catalog
41
+ >>
42
+ endobj
43
+ 7 0 obj
44
+ <<
45
+ /Author (\(anonymous\)) /CreationDate (D:20250922135912+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20250922135912+00'00') /Producer (ReportLab PDF Library - www.reportlab.com)
46
+ /Subject (\(unspecified\)) /Title (\(anonymous\)) /Trapped /False
47
+ >>
48
+ endobj
49
+ 8 0 obj
50
+ <<
51
+ /Count 2 /Kids [ 4 0 R 5 0 R ] /Type /Pages
52
+ >>
53
+ endobj
54
+ 9 0 obj
55
+ <<
56
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 2014
57
+ >>
58
+ stream
59
+ Gat=,?$"^Z'RfGR\1cZ0[Y/$uKA!0I=4=NeRfqHjm,UUf_C4%LQ#.p*rUG4[RflXUCbqJe>LpJK](b!T$P%=KkLe*7,s!'qnU$$2Qc;sE]XC>j+^L&aI"10U1]%4G4f9;'K)c[3dBP?Hr!'UTUH9<iE935r(g!kU*"DhSj)bC9*_1<kb16aPZ'7[5->>;H;m@sL8B=.:5LB1$3nfu4'Y!kl7H/J4OZ\!@)[p$Uku9(9iJu`u7<u+@XkFG=dhT<7\o*F^ISqBNS-*.\<9^ZLa4lf`$km588^rdfhf6e,@LVJ`AmYeJaCiK1HJ*9=&+=fs"jVY0Npfjnk^"2CIG=2orS$Z9rSP\YB6PHMh;;m'j]NppA-n6Q1hD!h#f;"8V4'Z1e21Mec07R76?95CKud)j0U*MSppB0WB;DECIk8)F>_]mckBtAb[GVWO)%i4&)WK_tY1n6r)!lrW;%_qnj]`u:[Urf7aNU)nc)+DO[N"u)piV/]"94X;*mK6^X'O<B[sMDe5\E0mmD/+9^-g5M=Am#;mp^a$Nj&Xq1&Z.ud.@$BaXrlCncoAs+[?H.VF&9ZA25c>bd5'mE,HORrhJ.:[Uc.0MacKs91AR[QR[RZrF(W(lNQ1Y\ln2P-!U#&MKo"A_n_%srP!X>3S*eKT]%Dtk8F4a6SZss6tendfmPHp(%+$hF*fiVRXmLO3`RZUOSK'qJH[PIUH/s(f/c!+3Ld7SESYBpNQUfoo?ls07Ft/OlMM>TCHU4NiENq!;Mj)dkBt9lA&Rd,4%KtWF=@dOTaH\df/kmYM#@+X7HZ.jF1p\Q0^Bt_+"C%@?/f;#@81K^K,`=Q*U?ZlSXknF.HS_n]=)',oY'MnDDpY5?8[J,bnt+tNo?iTF8XIe\Q3$TJ#u4Z:g8uen$Vi`%1K"i8"")>"4,`)aW99AnQj_4?,>+H#0%_+CXFMp/m)_HM#2hqJM%Dn,JiTtIU6bh/FF$#Uo,\+^jNVDU\+oC[&RHa+a0AZ`4^$/c7b9?T'<@J+fS*s31Y7=q'r-NRO^D.4&pTN454d[A70O/\eS8HcU[V=!PO?J&A0Y:@ad>B_'1)FEd1]CLi;$a_M8G1T>+^'+5tFKZ7s3>!NjR=0T0D'Lp/ugdRBn]SC]9o#udb1U$*!O,M8N-#jML&F1Prr;Q<UQmu%=mc<3-)Dg_*m?]a5Y9HP.J(PgWjD8JP>1/a9JK'gmuKBsNi1oJ+Sql`fq&4'VfbG@329IM-WLaCYgPLYR@XI-u6SMB,M.7+Mh(W4Z!+YCk(DeH84";3=b\3e>sf1?Rn*#`GW_4J#q,%N]Gfn2B0fppAf&qNI*Y-+um:Q]TPO\[`pQep^g=A&*7#H2.WQ\%Tej2NKm[Ja(6>9CZ<Y';4;XA-HR0$js"c*C?`2nu#nc#9L?^M^e%*ea08QhQ`N][4<mSPu[="j88ebZj_CaB!+LB4F!M)/GN4:"4=2KJ`3P'6h`C0u#CGpsag?/;M"4H.kk&aVGkg3.L`7.Me7!l?D)g=.k%Og,dKn(W^&TP;NeqDteS*I%bXWM..d1bhO=cM\$)0rs)8$#,Jl2F/Gbt$a"CQmY3Mq&jVc*OOjJE\RD%fR#W(R_sQ"&`bhZdB%icMjC;>mKiSI9,4_d8Hsf!8Ea>OE5ud_Q'Nbu._$_OZ\h>+qmbUG4q%8bIqH;Op5%>K?Qo$@,&VTPV8@N0(%T'Y.R!7l2q)O(o\$<[M\,[]=C"!4-l+c"]m#TSOd&&%J)1@W:57rW-h7F6V.p;EP9@IP`Y,6<`6@>7j)-6-LRE0iV#*.rJ05jUag[;Vm?G"[#7,3-+?:S6-5klJ])3)KNqGZ\-848@"#?=)4Ksk3;Ud&8LrP;&Bnq:ej(Pogpm?R>02:KnAS_B=>^[mB$G"PQIR/f+(5W.,3hu6g+n%J":FL%ES&r%f^'@PC3q$)Am)-S3IThT;Ok.;8eU/Z=&E:hJa.:X'83+qBC;H:NEL*Mh25N^T`=^=IdTu:CmX0A'?<p_O7Ztk!Z+6un2Sc~>endstream
60
+ endobj
61
+ 10 0 obj
62
+ <<
63
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 366
64
+ >>
65
+ stream
66
+ Garo<>u/<k'Sc)N/)Dd4%,s=1NCu\;80ES%hJlKWfi$;,cj_2uHJ8o)18`0Vk3RMfpQQi*LGdtj"<LIr4u'8QBb&__ooW!(8\MOPp4#OdU3kILj'ca;hVquY*_1!!BEk@'/=%;MQ<@BaB_dW6Fq0">$Eh<+YD$"^@e-oN,=lCq62HH1g9k$fl3;n)7!E7RMk.j>12U)"SF!]sr#6pSk(?Wm;,ujS1h,YgY:A/$Cp1s`Wi>>o,`Lfa-og(JfTN4%]u/8?CI>%WQci.Qdab__B<;P5Gbco_D:^b7`cC\-4X,,n!ab_3^kV$F(QtiC"tei,#(JEbY'<7/dp4-=RO:5Bbdc`G9!lHsmDI!=L%b[R)3T[~>endstream
67
+ endobj
68
+ xref
69
+ 0 11
70
+ 0000000000 65535 f
71
+ 0000000073 00000 n
72
+ 0000000114 00000 n
73
+ 0000000221 00000 n
74
+ 0000000333 00000 n
75
+ 0000000536 00000 n
76
+ 0000000740 00000 n
77
+ 0000000808 00000 n
78
+ 0000001091 00000 n
79
+ 0000001156 00000 n
80
+ 0000003261 00000 n
81
+ trailer
82
+ <<
83
+ /ID
84
+ [<67970e30f5384019a1d55c288e4fe1e4><67970e30f5384019a1d55c288e4fe1e4>]
85
+ % ReportLab generated PDF document -- digest (http://www.reportlab.com)
86
+
87
+ /Info 7 0 R
88
+ /Root 6 0 R
89
+ /Size 11
90
+ >>
91
+ startxref
92
+ 3718
93
+ %%EOF
me/summary.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ Bayu Ramadhan Shafiyuddin is a Software Engineer with over 5 years of experience.
2
+ He has developed more than 30 products that handle millions of daily users.
3
+ His skills include JavaScript, PHP, Go (Golang), and Python.
4
+ He is proficient with frameworks like Laravel and VueJS , and databases such as PostgreSQL and MySQL.
5
+ In his career, he has improved web performance by increasing the speed index up to 70% and reducing initial page requests by up to 96%.
6
+ He holds a Bachelor's degree in Information System from Airlangga University.
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ requests
2
+ python-dotenv
3
+ gradio
4
+ pypdf
5
+ openai
6
+ openai-agents