SayknowLab commited on
Commit
6188838
ยท
1 Parent(s): f27b5bc

sayknow upload

Browse files
Files changed (3) hide show
  1. Dockerfile +15 -0
  2. app.py +134 -58
  3. requirements.txt +7 -0
Dockerfile ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Dockerfile (์ด๊ฑฐ ๊ทธ๋Œ€๋กœ ๋ณต์‚ฌํ•ด์„œ Dockerfile ์ด๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ์ €์žฅ!)
2
+ FROM python:3.9-slim-buster
3
+
4
+ WORKDIR /app
5
+
6
+ COPY requirements.txt .
7
+ RUN pip install --no-cache-dir -r requirements.txt
8
+
9
+ COPY app.py .
10
+ COPY dataset.xlsx .
11
+
12
+ EXPOSE 7860
13
+
14
+ # ๋„ค Flask ์•ฑ์„ ์›น ์„œ๋ฒ„์ฒ˜๋Ÿผ ์‹คํ–‰์‹œ์ผœ์ฃผ๋Š” ๋ช…๋ น์–ด (Gunicorn์ด ๋„์™€์คŒ)
15
+ CMD ["gunicorn", "--bind", "0.0.0.0:7860", "app:app"]
app.py CHANGED
@@ -1,70 +1,146 @@
1
- import gradio as gr
2
- from huggingface_hub import InferenceClient
 
 
 
3
 
 
4
 
5
- def respond(
6
- message,
7
- history: list[dict[str, str]],
8
- system_message,
9
- max_tokens,
10
- temperature,
11
- top_p,
12
- hf_token: gr.OAuthToken,
13
- ):
14
- """
15
- For more information on `huggingface_hub` Inference API support, please check the docs: https://huggingface.co/docs/huggingface_hub/v0.22.2/en/guides/inference
16
- """
17
- client = InferenceClient(token=hf_token.token, model="openai/gpt-oss-20b")
18
 
19
- messages = [{"role": "system", "content": system_message}]
 
 
 
 
 
 
20
 
21
- messages.extend(history)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
- messages.append({"role": "user", "content": message})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
- response = ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
- for message in client.chat_completion(
28
- messages,
29
- max_tokens=max_tokens,
30
- stream=True,
31
- temperature=temperature,
32
- top_p=top_p,
33
- ):
34
- choices = message.choices
35
- token = ""
36
- if len(choices) and choices[0].delta.content:
37
- token = choices[0].delta.content
38
 
39
- response += token
40
- yield response
 
 
 
 
 
 
 
 
 
 
41
 
 
 
 
 
 
 
 
 
 
42
 
43
- """
44
- For information on how to customize the ChatInterface, peruse the gradio docs: https://www.gradio.app/docs/chatinterface
45
- """
46
- chatbot = gr.ChatInterface(
47
- respond,
48
- type="messages",
49
- additional_inputs=[
50
- gr.Textbox(value="You are a friendly Chatbot.", label="System message"),
51
- gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
52
- gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
53
- gr.Slider(
54
- minimum=0.1,
55
- maximum=1.0,
56
- value=0.95,
57
- step=0.05,
58
- label="Top-p (nucleus sampling)",
59
- ),
60
- ],
61
- )
 
 
 
 
 
 
 
 
62
 
63
- with gr.Blocks() as demo:
64
- with gr.Sidebar():
65
- gr.LoginButton()
66
- chatbot.render()
67
 
68
-
69
- if __name__ == "__main__":
70
- demo.launch()
 
1
+ import pandas as pd
2
+ import torch
3
+ from flask import Flask, request, Response
4
+ from transformers import AutoTokenizer, GPT2LMHeadModel
5
+ from dicttoxml import dicttoxml
6
 
7
+ app = Flask(__name__)
8
 
9
+ # 1. ๋ชจ๋ธ ๋กœ๋“œ
10
+ print("ํ† ํฌ๋‚˜์ด์ € ๋กœ๋”ฉ ์ค‘...")
11
+ tokenizer = AutoTokenizer.from_pretrained("EleutherAI/polyglot-ko-1.3b", trust_remote_code=True)
12
+ print("๋ชจ๋ธ ๋กœ๋”ฉ ์ค‘...")
13
+ model = GPT2LMHeadModel.from_pretrained("EleutherAI/polyglot-ko-1.3b", trust_remote_code=True)
14
+ print("๋ชจ๋ธ ๋กœ๋”ฉ ์™„๋ฃŒ!")
 
 
 
 
 
 
 
15
 
16
+ # 2. ๋ฐ์ดํ„ฐ์…‹ ๋กœ๋“œ (์—‘์…€์˜ ํ•œ ์ปฌ๋Ÿผ์— ์ง€์‹ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ชฐ๋ ค์žˆ๋Š” ๊ฒฝ์šฐ)
17
+ try:
18
+ df = pd.read_excel('dataset.xlsx')
19
+ knowledge_list = df['๋ฐ์ดํ„ฐ์…‹์— ๋„ฃ์„ ๋‚ด์šฉ(*)'].tolist() # ๋ฐ์ดํ„ฐ์…‹ ๋ฌธ์žฅ ๋ฆฌ์ŠคํŠธํ™”
20
+ except Exception as e:
21
+ print(f"๋ฐ์ดํ„ฐ์…‹ ๋กœ๋“œ ์—๋Ÿฌ: {e}")
22
+ knowledge_list = []
23
 
24
+ def find_relevant_context(query, top_n=2):
25
+ """๋ฐ์ดํ„ฐ์…‹์—์„œ ์งˆ๋ฌธ๊ณผ ๊ด€๋ จ๋œ ๋ฌธ์žฅ์„ ์ฐพ์•„ ๋ฐ˜ํ™˜"""
26
+ # ํ‚ค์›Œ๋“œ ๊ธฐ๋ฐ˜ ํ•„ํ„ฐ๋ง - ๊ณต๋ฐฑ ์ œ๊ฑฐํ•ด์„œ ๊ฒ€์ƒ‰
27
+ query_words = query.replace(" ", "").lower()
28
+ relevant_sentences = []
29
+
30
+ for s in knowledge_list:
31
+ s_text = str(s).replace(" ", "").replace("\n", "").lower()
32
+ # ํ‚ค์›Œ๋“œ๊ฐ€ ๋ฌธ์žฅ์— ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ
33
+ if any(word.replace(" ", "") in s_text for word in query.split()):
34
+ relevant_sentences.append(s)
35
+
36
+ if relevant_sentences:
37
+ return " ".join(str(s) for s in relevant_sentences[:top_n])
38
+ return ""
39
 
40
+ def ask_sayknow(query):
41
+ try:
42
+ context = find_relevant_context(query)
43
+
44
+ # ์ž๊ธฐ์†Œ๊ฐœ/์ธ์‚ฌ ์งˆ๋ฌธ์— ๋Œ€ํ•œ ๋ช…์‹œ์  ์•ˆ๋‚ด ์ถ”๊ฐ€
45
+ # ์—ญํ• , ์˜ˆ์‹œ, ์ •๋ณด/์งˆ๋ฌธ ๊ตฌ๋ถ„, context ์—†์„ ๋•Œ '์ •๋ณด ์—†์Œ' ๋ช…์‹œ
46
+ persona_guide = (
47
+ "๋„ˆ๋Š” ์ง€์‹ ๊ธฐ๋ฐ˜ ํ•œ๊ตญ์–ด ์ฑ—๋ด‡ Sayknow์•ผ. ์ž๊ธฐ์†Œ๊ฐœ(์ด๋ฆ„, ์ •์ฒด, ์ธ์‚ฌ ๋“ฑ) ์งˆ๋ฌธ์—” '์ €๋Š” Sayknow์ž…๋‹ˆ๋‹ค.'๋ผ๊ณ  ๋‹ตํ•ด. "
48
+ "๊ทธ ์™ธ์—๋Š” ์•„๋ž˜ ์ •๋ณด๋ฅผ ์ฐธ๊ณ ํ•ด ์งˆ๋ฌธ์— ๋Œ€ํ•ด ์ •ํ™•ํ•˜๊ณ  ์ž์—ฐ์Šค๋Ÿฌ์šด ํ•œ๊ตญ์–ด ๋ฌธ์žฅ์œผ๋กœ 80์ž ์ด๋‚ด๋กœ ๋‹ตํ•ด.\n"
49
+ "์˜ˆ์‹œ: Q: ๋ถ„์ˆ˜์˜ ๋ง์…ˆ์ด ๋ญ์•ผ?\nA: ๋ถ„๋ชจ๊ฐ€ ๊ฐ™์„ ๋•Œ ๋ถ„์ž๋ผ๋ฆฌ ๋”ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.\n"
50
+ )
51
+ info = context if context else "์ •๋ณด ์—†์Œ"
52
+ prompt = (
53
+ f"{persona_guide}---\n[์ •๋ณด]\n{info}\n[์งˆ๋ฌธ]\n{query}\n[๋‹ต๋ณ€] "
54
+ )
55
 
56
+ input_ids = tokenizer.encode(prompt, return_tensors='pt')
57
+ model.eval()
58
+ with torch.no_grad():
59
+ gen_ids = model.generate(
60
+ input_ids,
61
+ max_new_tokens=60,
62
+ min_length=5,
63
+ repetition_penalty=1.3,
64
+ do_sample=True,
65
+ top_k=30,
66
+ top_p=0.85,
67
+ pad_token_id=tokenizer.pad_token_id,
68
+ temperature=0.5,
69
+ num_beams=1
70
+ )
71
+ response = tokenizer.decode(gen_ids[0], skip_special_tokens=True)
72
+ # ๋‹ต๋ณ€ ๋ถ€๋ถ„๋งŒ ์ž˜๋ผ๋‚ด๊ธฐ
73
+ if "๋‹ต๋ณ€:" in response:
74
+ answer = response.split("๋‹ต๋ณ€:")[-1].strip()
75
+ else:
76
+ answer = response.strip()
77
 
78
+ # 1. ์˜๋ฏธ ์—†๋Š” ์ˆ˜์‹/์˜๋ฌธ/ํŠน์ˆ˜๋ฌธ์ž/๋ฐ˜๋ณต๋ฌธ์ž ๋“ฑ ํ•„ํ„ฐ๋ง
79
+ import re
80
+ # ํ•œ๊ธ€, ์ˆซ์ž, ๊ธฐ๋ณธ ๊ตฌ๋‘์ ๋งŒ ํ—ˆ์šฉ
81
+ answer = re.sub(r"[^๊ฐ€-ํžฃ0-9 .,!?~\n]", "", answer)
82
+ # ๋ฐ˜๋ณต๋˜๋Š” ํŠน์ˆ˜๋ฌธ์ž, ์ˆซ์ž, ์˜๋ฌธ ์ œ๊ฑฐ
83
+ answer = re.sub(r"([.,!?~])\1{2,}", r"\1", answer)
84
+ answer = re.sub(r"[a-zA-Z]+", "", answer)
85
+ # ์ˆ˜์‹(=, ^, *, / ๋“ฑ) ์ œ๊ฑฐ
86
+ answer = re.sub(r"[=^*/\\]+", "", answer)
87
+ # ์—ฐ์† ๊ณต๋ฐฑ ์ •๋ฆฌ
88
+ answer = re.sub(r"\s+", " ", answer).strip()
89
 
90
+ # 2. 80์ž ์ด๋‚ด๋กœ ์ž๋ฅด๊ธฐ (ํ•œ๊ธ€ ๊ธฐ์ค€)
91
+ def truncate_korean(text, max_len=80):
92
+ count = 0
93
+ result = ""
94
+ for ch in text:
95
+ # ํ•œ๊ธ€, ํ•œ์ž, ์˜๋ฌธ, ์ˆซ์ž, ๊ตฌ๋‘์  ๋ชจ๋‘ 1์ž๋กœ ์ทจ๊ธ‰
96
+ result += ch
97
+ count += 1
98
+ if count >= max_len:
99
+ break
100
+ return result
101
+ answer = truncate_korean(answer, 80)
102
 
103
+ # 3. ๋ฌธ์žฅ ๋์ด ์ž์—ฐ์Šค๋Ÿฝ์ง€ ์•Š์œผ๋ฉด ๋งˆ์นจํ‘œ ์ถ”๊ฐ€
104
+ if answer and answer[-1] not in ".!?":
105
+ answer += "."
106
+ return answer
107
+ except Exception as e:
108
+ print(f"ask_sayknow ์—๋Ÿฌ: {e}")
109
+ import traceback
110
+ traceback.print_exc()
111
+ return f"์˜ค๋ฅ˜: {str(e)}"
112
 
113
+ # 3. REST API ์—”๋“œํฌ์ธํŠธ
114
+ @app.route('/chatapi.html', methods=['GET'])
115
+ @app.route('/index.html', methods=['GET'])
116
+ @app.route('/', methods=['GET'])
117
+ def chat_api():
118
+ query = request.args.get('askdata', '')
119
+
120
+ if not query:
121
+ result = {"status": "error", "message": "No data"}
122
+ else:
123
+ try:
124
+ answer = ask_sayknow(query)
125
+ result = {
126
+ "service": "Sayknow",
127
+ "question": query,
128
+ "answer": answer
129
+ }
130
+ except Exception as e:
131
+ print(f"chat_api ์—๋Ÿฌ: {e}")
132
+ import traceback
133
+ traceback.print_exc()
134
+ result = {
135
+ "service": "Sayknow",
136
+ "question": query,
137
+ "answer": f"์—๋Ÿฌ ๋ฐœ์ƒ: {str(e)}",
138
+ "error": str(e)
139
+ }
140
 
141
+ # XML ๋ณ€ํ™˜
142
+ xml_output = dicttoxml(result, custom_root='SayknowAPI', attr_type=False)
143
+ return Response(xml_output, mimetype='text/xml')
 
144
 
145
+ if __name__ == '__main__':
146
+ app.run(host='0.0.0.0', port=7860)
 
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ # requirements.txt
2
+ pandas
3
+ torch
4
+ flask
5
+ transformers
6
+ dicttoxml
7
+ gunicorn # โ˜…โ˜…โ˜…โ˜… ์ด๊ฑฐ ์ค‘์š”! ๋’ค์—์„œ ์„ค๋ช…ํ•  Flask ์•ฑ ์‹คํ–‰ ๋„์šฐ๋ฏธ!