File size: 5,128 Bytes
be82a8a 4971496 2c21af2 be82a8a 4971496 d6fd3b7 2c21af2 cdfe590 2c21af2 cdfe590 2c21af2 b8aee7e 2c21af2 4971496 e0d2fc3 2c21af2 cdfe590 2c21af2 d6fd3b7 b8aee7e 2c21af2 be82a8a 4971496 2c21af2 4bd3834 2c21af2 4bd3834 d6fd3b7 2c21af2 4bd3834 d6fd3b7 2c21af2 4bd3834 2c21af2 4bd3834 d6fd3b7 4971496 be82a8a 2c21af2 b8aee7e 2c21af2 b8aee7e 2c21af2 b8aee7e 2c21af2 b8aee7e d6fd3b7 b8aee7e 2c21af2 85e06dd 2c21af2 b8aee7e d6fd3b7 b8aee7e 2c21af2 d6fd3b7 2c21af2 e0d2fc3 2c21af2 |
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 |
import gradio as gr
from huggingface_hub import InferenceClient
from duckduckgo_search import DDGS
import re
client = InferenceClient("Pinkstack/Superthoughts-lite-v1")
def format_search_results(query, results, result_type):
formatted = f"{result_type} search results for '{query}':\n"
for i, result in enumerate(results):
title = result.get('title', 'No title')
description = result.get('body', '') or result.get('snippet', '') or 'No description'
url = result.get('href', '') or result.get('url', '') or 'No URL'
formatted += f"{i+1}. [{title}]({url})\n{description}\n\n"
return formatted
def extract_key_phrases(message):
words = re.split(r'[,.!?;:\s]+', message.strip())
phrases = [message]
for i in range(len(words) - 1):
if len(words[i]) > 3 and len(words[i+1]) > 3:
phrases.append(f"{words[i]} {words[i+1]}")
return phrases[:3]
def respond(
message,
history: list[tuple[str, str]],
system_message,
max_tokens,
temperature,
top_p,
search_option,
):
search_text = ""
if search_option != "No search":
with DDGS() as ddgs:
if search_option == "Normal search":
web_results = ddgs.text(message, max_results=3)
search_text = format_search_results(message, web_results, "Web")
elif search_option == "Deep research":
queries = extract_key_phrases(message)
search_texts = []
for query in queries:
web_results = ddgs.text(query, max_results=3)
news_results = ddgs.news(query, max_results=2)
search_texts.append(format_search_results(query, web_results, "Web"))
search_texts.append(format_search_results(query, news_results, "News"))
search_text = "\n".join(search_texts)
message += "\n\n**Search Results:**\n" + search_text
messages = [{"role": "system", "content": system_message}]
for user_msg, assistant_msg in history:
if user_msg:
messages.append({"role": "user", "content": user_msg})
if assistant_msg:
messages.append({"role": "assistant", "content": assistant_msg})
messages.append({"role": "user", "content": message})
response = ""
for msg in client.chat_completion(
messages,
max_tokens=max_tokens,
stream=True,
temperature=temperature,
top_p=top_p,
):
token = msg.choices[0].delta.content
if token:
response += token
# Clean response: normalize line breaks to prevent extra <p> tags
response = re.sub(r'\n\s*\n+', '\n', response.strip())
# Process response to convert tags to HTML divs
formatted_response = response
formatted_response = formatted_response.replace("<think>", '<div class="thinking">').replace("</think>", "</div>")
formatted_response = formatted_response.replace("<output>", '<div class="output">').replace("</output>", "</div>")
yield formatted_response
css = """
.thinking {
background-color: #333;
color: white;
padding: 15px;
border-radius: 8px;
margin-bottom: 10px;
}
.output {
background-color: #f0f0f0;
color: black !important;
padding: 15px;
border-radius: 8px;
}
.output * {
color: black !important;
}
.gr-chatbot {
background-color: #f5f5f5;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
.gr-chatbot .message {
padding: 12px;
border-radius: 12px;
margin-bottom: 12px;
max-width: 80%;
}
.gr-chatbot .message.user {
background-color: #d1d5db;
align-self: flex-end;
}
.gr-chatbot .message.assistant {
background-color: #ffffff;
align-self: flex-start;
box-shadow: 0 1px 2px rgba(0,0,0,0.1);
}
.gr-chatbot .message.assistant * {
color: inherit;
}
"""
system_message_default = """
Respond in the following format:
<think>
Your thought process here...
</think>
<output>
Your final answer here...
If search results are provided, you must cite relevant sources at the end of this section as a numbered list in the format:
1. [Title](URL)
2. [Title](URL)
</output>
"""
demo = gr.ChatInterface(
respond,
additional_inputs=[
gr.Textbox(value=system_message_default, label="System message", lines=8),
gr.Slider(minimum=1, maximum=4096, value=2048, step=1, label="Max new tokens"),
gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
gr.Slider(minimum=0.1, maximum=1.0, value=0.95, step=0.05, label="Top-p"),
gr.Dropdown(
choices=["No search", "Normal search", "Deep research"],
value="No search",
label="Web search",
info="Choose 'Deep research' for comprehensive web and news results."
),
],
css=css,
title="Pinkchat - Superthoughts lite v1 (Just 1.7B parameters!)",
description="""Chat with an AI that thinks step-by-step and has web search.
BETA:Added deep research."""
)
if __name__ == "__main__":
demo.launch() |