File size: 5,870 Bytes
4375b7f
4e683ec
76a154f
7e59d5e
 
 
 
76a154f
 
b1c12fa
76a154f
c201b35
e5eef56
a92dd39
 
501c87a
 
bc679cd
501c87a
 
 
 
 
 
 
a68ab17
501c87a
 
 
bc679cd
501c87a
 
a92dd39
 
406f79b
 
a92dd39
 
 
 
406f79b
21ddc42
501c87a
 
3b16adf
501c87a
76bf9d2
4e683ec
a92dd39
 
 
76a154f
4e683ec
dd2ac3b
76a154f
 
 
4e683ec
98df5b4
76a154f
4e683ec
2f39e6b
cd9b772
 
 
76a154f
 
76bf9d2
b1c12fa
76a154f
 
4e683ec
76a154f
4e683ec
 
 
 
 
 
 
 
 
 
 
 
406f79b
a92dd39
d9f674b
a92dd39
f1ac54e
a92dd39
 
 
 
 
 
 
 
438a481
 
 
 
406f79b
438a481
a92dd39
8a9f83e
6111f2c
 
 
 
ed9bdc3
4e683ec
 
6111f2c
4e683ec
 
 
 
 
 
 
 
 
ed9bdc3
4e683ec
 
ed9bdc3
4e683ec
 
 
 
cb73e1e
21ddc42
 
501c87a
76a154f
76bf9d2
4e683ec
 
 
a400f4b
4e683ec
 
76a154f
 
 
 
4e683ec
 
 
4ee1547
76a154f
 
4ee1547
4e683ec
 
 
76a154f
 
 
4e683ec
 
 
 
76a154f
 
 
 
4e683ec
 
 
 
 
 
76bf9d2
4e683ec
 
 
 
7a75c62
 
 
1360bf2
7a75c62
4e683ec
 
 
 
 
 
 
76a154f
4e683ec
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
import os
from threading import Thread
from typing import Iterator
import json
from datetime import datetime
from pathlib import Path
from uuid import uuid4

import gradio as gr
import spaces
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer, AutoModel
from pathlib import Path
from pinecone.grpc import PineconeGRPC as Pinecone
import torch
from huggingface_hub import CommitScheduler

HF_UPLOAD = os.environ.get("HF_UPLOAD")

JSON_DATASET_DIR = Path("json_dataset")
JSON_DATASET_DIR.mkdir(parents=True, exist_ok=True)

JSON_DATASET_PATH = JSON_DATASET_DIR / f"train-{uuid4()}.json"

scheduler = CommitScheduler(
    repo_id="psyche/llama3-mrc-chat-log",
    repo_type="dataset",
    folder_path=JSON_DATASET_DIR,
    path_in_repo="data",
    token=HF_UPLOAD
)

pc = Pinecone(api_key=os.environ.get("PINECONE"))
index = pc.Index("commonsense")
"""
device = torch.device("cuda" if torch.cuda.is_available() else "CPU")
retriever_tokenizer = AutoTokenizer.from_pretrained("psyche/dpr-longformer-ko-4096")
retriever = AutoModel.from_pretrained("psyche/dpr-longformer-ko-4096")
retriever.eval()
retriever.to(device)
"""
def save_json(question: str, answer: str) -> None:
    with scheduler.lock:
        with JSON_DATASET_PATH.open("a") as f:
            json.dump({"question": question, "answer": answer, "datetime": datetime.now().isoformat(), "label":""}, f, ensure_ascii=False)
            f.write("\n")


MAX_MAX_NEW_TOKENS = 8192
DEFAULT_MAX_NEW_TOKENS = 4096
MAX_INPUT_TOKEN_LENGTH = 2048

DESCRIPTION = """\
# Llama-3 8B Korean QA Chatbot \
"""

if not torch.cuda.is_available():
    DESCRIPTION += "\n<p>Running on CPU πŸ₯Ά This demo does not work on CPU.</p>"


if torch.cuda.is_available():
    model_id = "psyche/llama3-8b-instruct-ko"
    #model_id = "psyche/meta-llama3-experiments"
    model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto", load_in_4bit=True, revision="v4.3")
    tokenizer = AutoTokenizer.from_pretrained(model_id, revision="v4.3")



@spaces.GPU
def generate(
    message: str,
    chat_history: list[tuple[str, str]],
    system_prompt: str,
    max_new_tokens: int = 1024,
    temperature: float = 0.6,
    top_p: float = 0.9,
    top_k: int = 50,
    repetition_penalty: float = 1.2,
) -> Iterator[str]:
    conversation = []
    if system_prompt:
        conversation.append({"role": "system", "content": system_prompt})
    for user, assistant in chat_history:
        conversation.extend([{"role": "user", "content": user}, {"role": "assistant", "content": assistant}])

    """    
    retriever_inputs = retriever_tokenizer([message], max_length=1024, truncation=True, return_tensors="pt")
    retriever_inputs = {k:v.to(retriever.device) for k,v in retriever_inputs.items()}
    with torch.no_grad():
        embeddings = retriever(**retriever_inputs).pooler_output
        embeddings = embeddings.cpu().numpy()

    results = index.query(
        vector=embeddings[0],
        top_k=1,
        include_values=False,
        include_metadata=True
    )

    results = [result for result in results["matches"] if result["score"] > 0.6]
    if len(results) > 0:
        message = results[0]["metadata"]["text"] + f"\n\nμœ„ λ¬Έλ§₯을 μ°Έκ³ ν•˜μ—¬ 질문 '{message}'에 λ‹΅ν•˜λ©΄?"
    """
    conversation.append({"role": "user", "content": message })
    
    input_ids = tokenizer.apply_chat_template(conversation, return_tensors="pt", add_generation_prompt=True)
    if input_ids.shape[1] > MAX_INPUT_TOKEN_LENGTH:
        input_ids = input_ids[:, -MAX_INPUT_TOKEN_LENGTH:]
        gr.Warning(f"Trimmed input from conversation as it was longer than {MAX_INPUT_TOKEN_LENGTH} tokens.")
    input_ids = input_ids.to(model.device)
    
    streamer = TextIteratorStreamer(tokenizer, timeout=10.0, skip_prompt=True, skip_special_tokens=True)
    generate_kwargs = dict(
        {"input_ids": input_ids},
        streamer=streamer,
        max_new_tokens=max_new_tokens,
        do_sample=True,
        top_p=top_p,
        top_k=top_k,
        temperature=temperature,
        num_beams=1,
        repetition_penalty=repetition_penalty,
    )
    
    t = Thread(target=model.generate, kwargs=generate_kwargs)
    t.start()
    
    outputs = []
    for text in streamer:
        outputs.append(text)
        yield "".join(outputs)
        
   
    save_json(message, "".join(outputs))
    

    
chat_interface = gr.ChatInterface(
    fn=generate,
    additional_inputs=[
        gr.Textbox(label="System prompt", lines=6),
        gr.Slider(
            label="Max new tokens",
            minimum=1,
            maximum=MAX_MAX_NEW_TOKENS,
            step=1,
            value=DEFAULT_MAX_NEW_TOKENS,
        ),
        gr.Slider(
            label="Temperature",
            minimum=0.01,
            maximum=4.0,
            step=0.1,
            value=0.01,
        ),
        gr.Slider(
            label="Top-p (nucleus sampling)",
            minimum=0.05,
            maximum=1.0,
            step=0.05,
            value=0.9,
        ),
        gr.Slider(
            label="Top-k",
            minimum=1,
            maximum=1000,
            step=1,
            value=50,
        ),
        gr.Slider(
            label="Repetition penalty",
            minimum=1.0,
            maximum=2.0,
            step=0.05,
            value=1.15,
        ),
    ],
    stop_btn=None,
    examples=[
        ["μ•ˆλ…•?"],
        ["λ„ˆκ°€ ν•  수 μžˆλŠ”κ²Œ 뭐야?"],
        ["νŒŒμ΄μ¬μ— λŒ€ν•΄μ„œ μ•Œλ €μ€˜"],
        ["λŒ€ν•œλ―Όκ΅­μ˜ μˆ˜λ„λŠ”?"],
        ["λ…λ„λŠ” μ–΄λŠλ‚˜λΌ 땅이야?"],
    ],
)

with gr.Blocks(css="style.css") as demo:
    gr.Markdown(DESCRIPTION)
    gr.DuplicateButton(value="Duplicate Space for private use", elem_id="duplicate-button")
    chat_interface.render()

if __name__ == "__main__":
    demo.queue(max_size=20).launch()