File size: 7,517 Bytes
479c5b5
d1c6587
ebf808d
8f66103
0f61c06
b516947
8f66103
 
 
 
b516947
 
 
 
479c5b5
8f66103
 
 
d1c6587
b516947
8f66103
 
d1c6587
 
b516947
d1c6587
 
 
 
 
 
ebf808d
 
b516947
ebf808d
 
 
 
37ae3c7
 
 
 
b516947
 
 
 
 
 
37ae3c7
ebf808d
37ae3c7
d1c6587
 
 
b516947
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8f66103
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c0529d2
d1c6587
8f66103
c0529d2
 
 
 
 
 
 
d1c6587
8f66103
c0529d2
d1c6587
479c5b5
c0529d2
 
 
 
 
 
8f66103
479c5b5
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
196
197
198
199
200
201
202
203
204
205
206
207
208
import gradio as gr
import subprocess
import json
import requests
from bs4 import BeautifulSoup

"""
General helper functions
"""

def strip_html_tags(html_text):
    # Use BeautifulSoup to parse and clean HTML content
    soup = BeautifulSoup(html_text, 'html.parser')
    return soup.get_text()

"""
Padlet API Interactions
"""
def api_call(input_text):

    #TODO: Refactor to be one function that can get OR post

    curl_command = [
        'curl', '-s', '--request', 'GET',
        '--url', f"https://api.padlet.dev/v1/boards/{board_id}?include=posts%2Csections",
        '--header', 'X-Api-Key: pdltp_0e380a0de1ff32d77b12dbcc030b1373199b7525681ddc81bd1b9ef3e4e3dd49577a23',
        '--header', 'accept: application/vnd.api+json'
    ]
    
    try:
        response = subprocess.check_output(curl_command, universal_newlines=True)
        response_data = json.loads(response)
        
        # Extract the contents of all posts, stripping HTML tags from bodyHtml
        posts_data = response_data.get("included", [])
        post_contents = []
        for post in posts_data:
            if post.get("type") == "post":
                attributes = post.get("attributes", {}).get("content", {})
                subject = attributes.get("subject", "")
                body_html = attributes.get("bodyHtml", "")
                
                if subject:
                    post_content = f"Subject: {subject}"
                    if body_html:
                        cleaned_body = strip_html_tags(body_html)
                        post_content += f"\nBody Text: {cleaned_body}"
                    
                    post_contents.append(post_content)
        
        return "\n\n".join(post_contents) if post_contents else "No post contents found."
    except subprocess.CalledProcessError:
        return "Error: Unable to fetch data using cURL."

def create_post(board_id, post_content):

    curl_command = [
        'curl', '-s', '--request', 'POST',
        '--url', f"https://api.padlet.dev/v1/boards/{board_id}/posts",
        '--header', 'X-Api-Key: pdltp_0e380a0de1ff32d77b12dbcc030b1373199b7525681ddc81bd1b9ef3e4e3dd49577a23',
        '--header', 'accept: application/vnd.api+json',
        '--header', 'content-type: application/vnd.api+json',
        '--data',
        json.dumps({
            "data": {
                "type": "post",
                "attributes": {
                    "content": {
                        "subject": post_content
                    }
                }
            }
        })
    ]
    
    try:
        response = subprocess.check_output(curl_command, universal_newlines=True)
        response_data = json.loads(response)
        return "Post created successfully."
    except subprocess.CalledProcessError as e:
        return f"Error: Unable to create post - {str(e)}"

"""
LLM Functions
"""
        
#Streaming endpoint 
API_URL = "https://api.openai.com/v1/chat/completions" #os.getenv("API_URL") + "/generate_stream"

#Inference function
def predict(openai_gpt4_key, system_msg, api_result, top_p, temperature, chat_counter, chatbot=[], history=[]): 

    headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {openai_gpt4_key}"  #Users will provide their own OPENAI_API_KEY 
    }
    print(f"system message is ^^ {system_msg}")
    if system_msg.strip() == '':
        initial_message = [{"role": "user", "content": f"{inputs}"},]
        multi_turn_message = []
    else:
        initial_message= [{"role": "system", "content": system_msg},
                   {"role": "user", "content": f"{inputs}"},]
        multi_turn_message = [{"role": "system", "content": system_msg},]
        
    if chat_counter == 0 :
        payload = {
        "model": "gpt-4",
        "messages": initial_message , 
        "temperature" : 1.0,
        "top_p":1.0,
        "n" : 1,
        "stream": True,
        "presence_penalty":0,
        "frequency_penalty":0,
        }
        print(f"chat_counter - {chat_counter}")
    else: #if chat_counter != 0 :
        messages=multi_turn_message # Of the type of - [{"role": "system", "content": system_msg},]
        for data in chatbot:
          user = {}
          user["role"] = "user" 
          user["content"] = data[0] 
          assistant = {}
          assistant["role"] = "assistant" 
          assistant["content"] = data[1]
          messages.append(user)
          messages.append(assistant)
        temp = {}
        temp["role"] = "user" 
        temp["content"] = inputs
        messages.append(temp)
        #messages
        payload = {
        "model": "gpt-4",
        "messages": messages, # Of the type of [{"role": "user", "content": f"{inputs}"}],
        "temperature" : temperature, #1.0,
        "top_p": top_p, #1.0,
        "n" : 1,
        "stream": True,
        "presence_penalty":0,
        "frequency_penalty":0,}

    chat_counter+=1

    history.append(inputs)
    print(f"Logging : payload is - {payload}")
    # make a POST request to the API endpoint using the requests.post method, passing in stream=True
    response = requests.post(API_URL, headers=headers, json=payload, stream=True)
    print(f"Logging : response code - {response}")
    token_counter = 0 
    partial_words = "" 

    counter=0
    for chunk in response.iter_lines():
        #Skipping first chunk
        if counter == 0:
          counter+=1
          continue
        # check whether each line is non-empty
        if chunk.decode() :
          chunk = chunk.decode()
          # decode each line as response data is in bytes
          if len(chunk) > 12 and "content" in json.loads(chunk[6:])['choices'][0]['delta']:
              partial_words = partial_words + json.loads(chunk[6:])['choices'][0]["delta"]["content"]
              if token_counter == 0:
                history.append(" " + partial_words)
              else:
                history[-1] = partial_words
              chat = [(history[i], history[i + 1]) for i in range(0, len(history) - 1, 2) ]  # convert to tuples of list
              token_counter+=1
              yield chat, history, chat_counter, response  # resembles {chatbot: chat, state: history}  
                   
#Resetting to blank
def reset_textbox():
    return gr.update(value='')

#to set a component as visible=False
def set_visible_false():
    return gr.update(visible=False)

#to set a component as visible=True
def set_visible_true():
    return gr.update(visible=True)

# Define the Gradio interface
iface = gr.Interface(
    fn=predict,  # Use 'predict' as the function
    inputs=[
        gr.inputs.Textbox(label="OpenAI GPT4 Key", type="password", placeholder="sk.."),
        gr.inputs.Textbox(label="System Message", default=""),
        gr.inputs.Textbox(label="Input Board ID for api_call"),
        gr.inputs.Textbox(label="Output Board ID for create_post"),
    ],
    outputs=gr.outputs.Textbox(label="Summary"),
    live=True,
    title="Padlet API Caller with cURL and LLM",
    description="Enter OpenAI GPT4 key, system message, input board ID for api_call, and output board ID for create_post",
)

# Add event handlers to call 'api_call' and 'create_post' when the "Generate Summary" and "Post Summary" buttons are clicked
iface.inputs[4].submit(api_call, [gr.inputs.Textbox])
iface.inputs[4].click(api_call, [gr.inputs.Textbox])

iface.inputs[5].submit(create_post, [gr.inputs.Textbox, gr.outputs.Textbox])
iface.inputs[5].click(create_post, [gr.inputs.Textbox, gr.outputs.Textbox])

iface.launch()