Spaces:
Running
Running
File size: 7,666 Bytes
e868919 c8fc333 39579a4 4825030 9fa1b7a 01c4ff9 e868919 39dc2b9 9e84942 9fa1b7a 270c2ee e868919 39dc2b9 01c4ff9 a5287d0 e868919 6a2d729 9fa1b7a 6a2d729 117c412 6a2d729 4825030 9e84942 09d75db 12eb228 3bb82b5 06f9d4d 3bb82b5 4165181 8b940b1 4165181 bee7437 6a2d729 a401049 a16a1ba 466550c 8c476af bee7437 c5b225d bee7437 de67bca 1506390 117c412 12eb228 117c412 12eb228 117c412 12eb228 f80b936 c5b225d bee7437 34c5931 e50d664 6ca2c86 c4c1112 9e84942 bee7437 defb6fc de67bca 3bb82b5 e868919 310f716 01c4ff9 defb6fc e057440 7049ced 9ac5b58 de67bca bee7437 a23b158 1015d8a 5b2f741 bee7437 de67bca e868919 225eb24 b1622bf 01c4ff9 e4e2020 b1622bf 01c4ff9 6a2d729 9e84942 310f716 b1622bf bee7437 b1622bf |
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 |
import os
import time
import json
import gradio
import functools
import uuid
import httpx
from httpx_sse import connect_sse
from tavily import TavilyClient
from linkup import LinkupClient
from ddgs import DDGS
from langfuse import Langfuse
from langfuse.openai import OpenAI
tavily = TavilyClient(os.getenv("TAVILY_API_KEY"))
linkup = LinkupClient(os.getenv("LINKUP_API_KEY"))
openai = OpenAI(base_url=os.getenv("NVIDIA_BASE_URL"), api_key=os.getenv("NVIDIA_API_KEY"))
langfuse = Langfuse()
system_prompt = "Jesteś pomocnym Asystentem Interesanta Gov.pl stworzonym przez Jerzego Głowackiego z wbudowaną funkcją wyszukiwania na stronach rządowych Gov.pl. Twoim zadaniem jest dostarczanie aktualnych, rzetelnych, szczegółowych i wyczerpujących odpowiedzi, krok po kroku, korzystając z własnej wiedzy oraz z podanych wyników wyszukiwania na stronach Gov.pl. Dzisiaj jest " + time.strftime("%d.%m.%Y") + " r. Wybory Prezydenta RP w 2025 r. wygrał Karol Nawrocki, który pokonał w drugiej turze Rafała Trzaskowskiego i jest aktualnym Prezydentem RP, a Premierem jest Donald Tusk."
def set_new_session_id():
global session_id
session_id = str(uuid.uuid4())
set_new_session_id()
@functools.lru_cache(maxsize=500)
def tavily_search(query):
search = tavily.search(
query=query,
search_depth="advanced",
chunks_per_source=2,
# include_raw_content=True,
country="poland",
include_domains=["gov.pl"]
)
return [{"tytul": r["title"], "url": r["url"], "tresc": r["content"]} for r in search["results"]]
@functools.lru_cache(maxsize=500)
def linkup_search(query):
search = linkup.search(
query=query,
depth="standard",
output_type="searchResults",
include_domains=["gov.pl"],
include_images=False
)
return [{"tytul": r.name, "url": r.url, "tresc": r.content} for r in search.results[:5]]
@functools.lru_cache(maxsize=500)
def ddgs_search(query):
results = DDGS().text(
query=query+" site:gov.pl",
region="pl-pl",
max_results=5
)
return [{"tytul": r["title"], "url": r["href"], "tresc": r["body"]} for r in results]
def search(message, search_provider):
return tavily_search(message[:400]) if search_provider == "tavily" else linkup_search(message) if search_provider == "linkup" else ddgs_search(message)
def bielik_inference(history, trace_id, model_id):
return openai.chat.completions.create(
model="speakleash/"+model_id,
messages=history,
temperature=0.1,
stream=True,
trace_id=trace_id,
stop=["Źródła:"]
)
def pllum_inference(history, model_id):
json = {
"prompt": f"{history[0]['content']}\n\n{history[-1]['content']}",
"system_prompt": "",
"temperature": 0.1,
"top_p": 0.5,
"model": model_id
}
try:
with httpx.Client() as client:
with connect_sse(client, "POST", os.getenv("PLLUM_BASE_URL"), json=json) as event_source:
for sse in event_source.iter_sse():
if sse.event == "new_message":
yield sse.data
except httpx.HTTPError as ex:
print(ex)
def respond(message, history, model_id="bielik-11b-v2.3-instruct", search_provider="tavily"):
if not message:
return
message = message.strip()
global session_id
trace = langfuse.trace(name="respond", session_id=session_id, input=message, metadata={"model_id": model_id})
response = gradio.ChatMessage(content="", metadata={"title": "Wyszukiwanie na stronach Gov.pl…", "id": 0, "status": "pending"})
yield response
start_time = time.time()
span = trace.span(name="search", input=message[:400])
try:
serp = search(message, search_provider)
except:
try:
search_provider = "linkup" if search_provider == "tavily" else "ddgs" if search_provider == "linkup" else "tavily"
serp = search(message, search_provider)
except:
search_provider = "ddgs" if search_provider == "tavily" else "tavily" if search_provider == "linkup" else "linkup"
serp = search(message, search_provider)
span.end(output=serp)
response.content = "Gotowe!"
response.metadata["status"] = "done"
response.metadata["duration"] = time.time() - start_time
yield response
system_message = f"{system_prompt}\n\nWyniki wyszukiwania w formacie JSON: {json.dumps(serp).encode('utf-8').decode('unicode_escape')}"
history = [h for h in history if h["content"] != "Gotowe!"]
history.insert(0, {"role": "system", "content": system_message})
history.append({"role": "user", "content": message})
print("===\nsearch: ", search_provider, "\n", history)
curr_chunk = ""
response = [response, gradio.ChatMessage(content="")]
completion = bielik_inference(history, trace.id, model_id) if model_id.startswith("bielik") else pllum_inference(history, model_id)
for chunk in completion:
if type(chunk) is str:
curr_chunk = chunk
response[1].content += curr_chunk
yield response
elif chunk.choices[0].delta.content is not None:
curr_chunk = chunk.choices[0].delta.content
response[1].content += curr_chunk
yield response
if curr_chunk and response[1].content.endswith(curr_chunk * 2):
response[1].content = response[1].content[:-len(curr_chunk)]
yield response
print(response[1])
if serp:
response[1].content += "\n\nŹródła:\n" + "\n".join([f"{str(i)}. [{r['tytul']}]({r['url']})" for i, r in enumerate(serp, 1)])
yield response
trace.update(output=response[1].content)
with gradio.Blocks(theme="shivi/calm_seafoam",css=":root{--body-text-color:var(--neutral-900)}button.primary{font-size:0 !important}button.primary:after{font-size:var(--button-medium-text-size);content:'Nowy czat'}#component-0 .form:first-child{order:1}") as chat:
textbox = gradio.Textbox(
show_label=False,
label="Pytanie",
placeholder="Zadaj pytanie…",
scale=7,
autofocus=True,
submit_btn=True,
stop_btn=True
)
chatbot = gradio.Chatbot(
label="Czatbot",
scale=1,
height=400,
type="messages",
autoscroll=True,
show_share_button=False,
show_copy_button=True
)
chatbot.clear(set_new_session_id)
gradio.ChatInterface(
respond,
chatbot=chatbot,
textbox=textbox,
title="Asystent Interesanta Gov.pl",
description="Czatbot AI pomagający wyszukiwać aktualne informacje na stronach Gov.pl, oparty o polski otwarty model językowy Bielik 11B od SpeakLeash. Stworzony przez Jerzego Głowackiego na licencji Apache 2.0. Sprawdź też <a href='https://ai-gov.pl/widzet.html' target='_blank'>widżet czatu na stronę WWW</a> i <a href='https://huggingface.co/spaces/jglowa/ai-gov.pl/tree/main' target='_blank'>kod źródłowy</a>. Wersja beta, używasz na własną odpowiedzialność.",
examples=[["Jak uzyskać NIP?"], ["Jak założyć profil zaufany?"], ["Komu przysługuje zasiłek pielęgnacyjny?"], ["Jak zarejestrować JDG?"]],
cache_mode="lazy",
save_history=True,
analytics_enabled=False,
show_progress="full",
type="messages",
additional_inputs=[
gradio.Dropdown(["bielik-11b-v2.3-instruct", "pllum-12b-chat"], label="Model językowy"),
gradio.Dropdown(["tavily", "linkup", "ddgs"], label="Silnik wyszukiwania")
]
)
chat.launch() |