Merge pull request #1820 from hlohaus/bugfix

Add ReplicateImage Provider, Fix BingCreateImages Provider
This commit is contained in:
H Lohaus 2024-04-11 03:36:12 +02:00 committed by GitHub
commit 4271fb9870
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 260 additions and 67 deletions

View File

@ -7,16 +7,33 @@ from typing import Iterator, Union
from ..cookies import get_cookies from ..cookies import get_cookies
from ..image import ImageResponse from ..image import ImageResponse
from ..errors import MissingRequirementsError, MissingAuthError from ..errors import MissingRequirementsError, MissingAuthError
from ..typing import Cookies from ..typing import AsyncResult, Messages, Cookies
from .base_provider import AsyncGeneratorProvider, ProviderModelMixin
from .bing.create_images import create_images, create_session, get_cookies_from_browser from .bing.create_images import create_images, create_session, get_cookies_from_browser
class BingCreateImages: class BingCreateImages(AsyncGeneratorProvider, ProviderModelMixin):
"""A class for creating images using Bing.""" url = "https://www.bing.com/images/create"
working = True
def __init__(self, cookies: Cookies = None, proxy: str = None) -> None: def __init__(self, cookies: Cookies = None, proxy: str = None) -> None:
self.cookies: Cookies = cookies self.cookies: Cookies = cookies
self.proxy: str = proxy self.proxy: str = proxy
@classmethod
async def create_async_generator(
cls,
model: str,
messages: Messages,
api_key: str = None,
cookies: Cookies = None,
proxy: str = None,
**kwargs
) -> AsyncResult:
if api_key is not None:
cookies = {"_U": api_key}
session = BingCreateImages(cookies, proxy)
yield await session.create_async(messages[-1]["content"])
def create(self, prompt: str) -> Iterator[Union[ImageResponse, str]]: def create(self, prompt: str) -> Iterator[Union[ImageResponse, str]]:
""" """
Generator for creating imagecompletion based on a prompt. Generator for creating imagecompletion based on a prompt.

View File

@ -35,7 +35,6 @@ class DeepInfra(Openai):
'Accept-Encoding': 'gzip, deflate, br', 'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'en-US', 'Accept-Language': 'en-US',
'Connection': 'keep-alive', 'Connection': 'keep-alive',
'Content-Type': None,
'Origin': 'https://deepinfra.com', 'Origin': 'https://deepinfra.com',
'Referer': 'https://deepinfra.com/', 'Referer': 'https://deepinfra.com/',
'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Dest': 'empty',
@ -43,7 +42,6 @@ class DeepInfra(Openai):
'Sec-Fetch-Site': 'same-site', 'Sec-Fetch-Site': 'same-site',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
'X-Deepinfra-Source': 'web-embed', 'X-Deepinfra-Source': 'web-embed',
'Accept': None,
'sec-ch-ua': '"Google Chrome";v="119", "Chromium";v="119", "Not?A_Brand";v="24"', 'sec-ch-ua': '"Google Chrome";v="119", "Chromium";v="119", "Not?A_Brand";v="24"',
'sec-ch-ua-mobile': '?0', 'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"macOS"', 'sec-ch-ua-platform': '"macOS"',

View File

@ -0,0 +1,96 @@
from __future__ import annotations
import random
import asyncio
from .base_provider import AsyncGeneratorProvider, ProviderModelMixin
from ..typing import AsyncResult, Messages
from ..requests import StreamSession, raise_for_status
from ..image import ImageResponse
from ..errors import ResponseError
class ReplicateImage(AsyncGeneratorProvider, ProviderModelMixin):
url = "https://replicate.com"
working = True
default_model = 'stability-ai/sdxl'
default_versions = [
"39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b",
"2b017d9b67edd2ee1401238df49d75da53c523f36e363881e057f5dc3ed3c5b2"
]
@classmethod
async def create_async_generator(
cls,
model: str,
messages: Messages,
**kwargs
) -> AsyncResult:
yield await cls.create_async(messages[-1]["content"], model, **kwargs)
@classmethod
async def create_async(
cls,
prompt: str,
model: str,
api_key: str = None,
proxy: str = None,
timeout: int = 180,
version: str = None,
extra_data: dict = {},
**kwargs
) -> ImageResponse:
headers = {
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'en-US',
'Connection': 'keep-alive',
'Origin': cls.url,
'Referer': f'{cls.url}/',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-site',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
'sec-ch-ua': '"Google Chrome";v="119", "Chromium";v="119", "Not?A_Brand";v="24"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"macOS"',
}
if version is None:
version = random.choice(cls.default_versions)
if api_key is not None:
headers["Authorization"] = f"Bearer {api_key}"
async with StreamSession(
proxies={"all": proxy},
headers=headers,
timeout=timeout
) as session:
data = {
"input": {
"prompt": prompt,
**extra_data
},
"version": version
}
if api_key is None:
data["model"] = cls.get_model(model)
url = "https://homepage.replicate.com/api/prediction"
else:
url = "https://api.replicate.com/v1/predictions"
async with session.post(url, json=data) as response:
await raise_for_status(response)
result = await response.json()
if "id" not in result:
raise ResponseError(f"Invalid response: {result}")
while True:
if api_key is None:
url = f"https://homepage.replicate.com/api/poll?id={result['id']}"
else:
url = f"https://api.replicate.com/v1/predictions/{result['id']}"
async with session.get(url) as response:
await raise_for_status(response)
result = await response.json()
if "status" not in result:
raise ResponseError(f"Invalid response: {result}")
if result["status"] == "succeeded":
images = result['output']
images = images[0] if len(images) == 1 else images
return ImageResponse(images, prompt)
await asyncio.sleep(0.5)

View File

@ -38,6 +38,7 @@ from .Llama2 import Llama2
from .Local import Local from .Local import Local
from .PerplexityLabs import PerplexityLabs from .PerplexityLabs import PerplexityLabs
from .Pi import Pi from .Pi import Pi
from .ReplicateImage import ReplicateImage
from .Vercel import Vercel from .Vercel import Vercel
from .WhiteRabbitNeo import WhiteRabbitNeo from .WhiteRabbitNeo import WhiteRabbitNeo
from .You import You from .You import You

View File

@ -34,9 +34,9 @@ async def create_conversation(session: ClientSession, headers: dict, tone: str)
Conversation: An instance representing the created conversation. Conversation: An instance representing the created conversation.
""" """
if tone == "Copilot": if tone == "Copilot":
url = "https://copilot.microsoft.com/turing/conversation/create?bundleVersion=1.1634.3-nodesign2" url = "https://copilot.microsoft.com/turing/conversation/create?bundleVersion=1.1686.0"
else: else:
url = "https://www.bing.com/turing/conversation/create?bundleVersion=1.1626.1" url = "https://www.bing.com/turing/conversation/create?bundleVersion=1.1686.0"
async with session.get(url, headers=headers) as response: async with session.get(url, headers=headers) as response:
if response.status == 404: if response.status == 404:
raise RateLimitError("Response 404: Do less requests and reuse conversations") raise RateLimitError("Response 404: Do less requests and reuse conversations")

View File

@ -151,7 +151,7 @@ async def create_images(session: ClientSession, prompt: str, proxy: str = None,
if response.status != 200: if response.status != 200:
raise RuntimeError(f"Polling images faild. Code: {response.status}") raise RuntimeError(f"Polling images faild. Code: {response.status}")
text = await response.text() text = await response.text()
if not text: if not text or "GenerativeImagesStatusPage" in text:
await asyncio.sleep(1) await asyncio.sleep(1)
else: else:
break break

View File

@ -0,0 +1,78 @@
from __future__ import annotations
import asyncio
from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin
from ..helper import format_prompt, filter_none
from ...typing import AsyncResult, Messages
from ...requests import StreamSession, raise_for_status
from ...image import ImageResponse
from ...errors import ResponseError, MissingAuthError
class Replicate(AsyncGeneratorProvider, ProviderModelMixin):
url = "https://replicate.com"
working = True
default_model = "mistralai/mixtral-8x7b-instruct-v0.1"
api_base = "https://api.replicate.com/v1/models/"
@classmethod
async def create_async_generator(
cls,
model: str,
messages: Messages,
api_key: str = None,
proxy: str = None,
timeout: int = 180,
system_prompt: str = None,
max_new_tokens: int = None,
temperature: float = None,
top_p: float = None,
top_k: float = None,
stop: list = None,
extra_data: dict = {},
headers: dict = {},
**kwargs
) -> AsyncResult:
model = cls.get_model(model)
if api_key is None:
raise MissingAuthError("api_key is missing")
headers["Authorization"] = f"Bearer {api_key}"
async with StreamSession(
proxies={"all": proxy},
headers=headers,
timeout=timeout
) as session:
data = {
"stream": True,
"input": {
"prompt": format_prompt(messages),
**filter_none(
system_prompt=system_prompt,
max_new_tokens=max_new_tokens,
temperature=temperature,
top_p=top_p,
top_k=top_k,
stop_sequences=",".join(stop) if stop else None
),
**extra_data
},
}
url = f"{cls.api_base.rstrip('/')}/{model}/predictions"
async with session.post(url, json=data) as response:
await raise_for_status(response)
result = await response.json()
if "id" not in result:
raise ResponseError(f"Invalid response: {result}")
async with session.get(result["urls"]["stream"], headers={"Accept": "text/event-stream"}) as response:
await raise_for_status(response)
event = None
async for line in response.iter_lines():
if line.startswith(b"event: "):
event = line[7:]
elif event == b"output":
if line.startswith(b"data: "):
yield line[6:].decode()
elif not line.startswith(b"id: "):
continue#yield "+"+line.decode()
elif event == b"done":
break

View File

@ -58,6 +58,12 @@
</button> </button>
</div> </div>
<div class="bottom_buttons"> <div class="bottom_buttons">
<!--
<button onclick="open_album();">
<i class="fa-solid fa-toolbox"></i>
<span>Images Album</span>
</button>
-->
<button onclick="open_settings();"> <button onclick="open_settings();">
<i class="fa-solid fa-toolbox"></i> <i class="fa-solid fa-toolbox"></i>
<span>Open Settings</span> <span>Open Settings</span>
@ -77,6 +83,9 @@
<span id="version_text" class="convo-title"></span> <span id="version_text" class="convo-title"></span>
</div> </div>
</div> </div>
</div>
<div class="images hidden">
</div> </div>
<div class="settings hidden"> <div class="settings hidden">
<div class="paper"> <div class="paper">
@ -101,7 +110,7 @@
<label for="auto_continue" class="toogle" title="Continue large responses in OpenaiChat"></label> <label for="auto_continue" class="toogle" title="Continue large responses in OpenaiChat"></label>
</div> </div>
<div class="field box"> <div class="field box">
<label for="message-input-height" class="label" title="">Input max. grow height</label> <label for="message-input-height" class="label" title="">Input max. height</label>
<input type="number" id="message-input-height" value="200"/> <input type="number" id="message-input-height" value="200"/>
</div> </div>
<div class="field box"> <div class="field box">
@ -109,40 +118,40 @@
<input type="text" id="recognition-language" value="" placeholder="navigator.language"/> <input type="text" id="recognition-language" value="" placeholder="navigator.language"/>
</div> </div>
<div class="field box"> <div class="field box">
<label for="OpenaiChat-api_key" class="label" title="">OpenaiChat: api_key</label> <label for="Bing-api_key" class="label" title="">Bing:</label>
<textarea id="OpenaiChat-api_key" name="OpenaiChat[api_key]" placeholder="..."></textarea> <textarea id="Bing-api_key" name="Bing[api_key]" class="BingCreateImages-api_key" placeholder="&quot;_U&quot; cookie"></textarea>
</div> </div>
<div class="field box"> <div class="field box">
<label for="Bing-api_key" class="label" title="">Bing: "_U" cookie</label> <label for="DeepInfra-api_key" class="label" title="">DeepInfra:</label>
<textarea id="Bing-api_key" name="Bing[api_key]" placeholder="..."></textarea> <textarea id="DeepInfra-api_key" name="DeepInfra[api_key]" class="DeepInfraImage-api_key" placeholder="api_key"></textarea>
</div> </div>
<div class="field box"> <div class="field box">
<label for="Gemini-api_key" class="label" title="">Gemini: Cookies</label> <label for="Gemini-api_key" class="label" title="">Gemini:</label>
<textarea id="Gemini-api_key" name="Gemini[api_key]" placeholder="..."></textarea> <textarea id="Gemini-api_key" name="Gemini[api_key]" placeholder="Cookies"></textarea>
</div> </div>
<div class="field box"> <div class="field box">
<label for="Openai-api_key" class="label" title="">Openai: api_key</label> <label for="GeminiPro-api_key" class="label" title="">GeminiPro:</label>
<textarea id="Openai-api_key" name="Openai[api_key]" placeholder="..."></textarea> <textarea id="GeminiPro-api_key" name="GeminiPro[api_key]" placeholder="api_key"></textarea>
</div> </div>
<div class="field box"> <div class="field box">
<label for="Groq-api_key" class="label" title="">Groq: api_key</label> <label for="Groq-api_key" class="label" title="">Groq:</label>
<textarea id="Groq-api_key" name="Groq[api_key]" placeholder="..."></textarea> <textarea id="Groq-api_key" name="Groq[api_key]" placeholder="api_key"></textarea>
</div> </div>
<div class="field box"> <div class="field box">
<label for="GeminiPro-api_key" class="label" title="">GeminiPro: api_key</label> <label for="HuggingFace-api_key" class="label" title="">HuggingFace:</label>
<textarea id="GeminiPro-api_key" name="GeminiPro[api_key]" placeholder="..."></textarea> <textarea id="HuggingFace-api_key" name="HuggingFace[api_key]" placeholder="api_key"></textarea>
</div> </div>
<div class="field box"> <div class="field box">
<label for="OpenRouter-api_key" class="label" title="">OpenRouter: api_key</label> <label for="Openai-api_key" class="label" title="">Openai:</label>
<textarea id="OpenRouter-api_key" name="OpenRouter[api_key]" placeholder="..."></textarea> <textarea id="Openai-api_key" name="Openai[api_key]" placeholder="api_key"></textarea>
</div> </div>
<div class="field box"> <div class="field box">
<label for="HuggingFace-api_key" class="label" title="">HuggingFace: api_key</label> <label for="OpenaiChat-api_key" class="label" title="">OpenaiChat:</label>
<textarea id="HuggingFace-api_key" name="HuggingFace[api_key]" placeholder="..."></textarea> <textarea id="OpenaiChat-api_key" name="OpenaiChat[api_key]" placeholder="api_key"></textarea>
</div> </div>
<div class="field box"> <div class="field box">
<label for="DeepInfra-api_key" class="label" title="">DeepInfra: api_key</label> <label for="OpenRouter-api_key" class="label" title="">OpenRouter:</label>
<textarea id="DeepInfra-api_key" name="DeepInfra[api_key]" placeholder="..."></textarea> <textarea id="OpenRouter-api_key" name="OpenRouter[api_key]" placeholder="api_key"></textarea>
</div> </div>
</div> </div>
<div class="bottom_buttons"> <div class="bottom_buttons">

View File

@ -653,7 +653,7 @@ select {
font-size: 15px; font-size: 15px;
width: 100%; width: 100%;
color: var(--colour-3); color: var(--colour-3);
min-height: 50px; min-height: 49px;
height: 59px; height: 59px;
outline: none; outline: none;
padding: var(--inner-gap) var(--section-gap); padding: var(--inner-gap) var(--section-gap);
@ -809,7 +809,7 @@ ul {
} }
.mobile-sidebar { .mobile-sidebar {
display: none !important; display: none;
position: absolute; position: absolute;
z-index: 100000; z-index: 100000;
top: 0; top: 0;
@ -850,12 +850,8 @@ ul {
gap: 15px; gap: 15px;
} }
.field {
width: fit-content;
}
.mobile-sidebar { .mobile-sidebar {
display: flex !important; display: flex;
} }
#systemPrompt { #systemPrompt {
@ -1090,7 +1086,13 @@ a:-webkit-any-link {
} }
.settings textarea { .settings textarea {
height: 51px; height: 19px;
min-height: 19px;
padding: 0;
}
.settings .field.box {
padding: var(--inner-gap) var(--inner-gap) var(--inner-gap) 0;
} }
.settings, .images { .settings, .images {
@ -1112,7 +1114,6 @@ a:-webkit-any-link {
.settings textarea { .settings textarea {
background-color: transparent; background-color: transparent;
border: none; border: none;
padding: var(--inner-gap) 0;
} }
.settings input { .settings input {
@ -1130,10 +1131,7 @@ a:-webkit-any-link {
.settings .label { .settings .label {
font-size: 15px; font-size: 15px;
padding: var(--inner-gap) 0; margin-left: var(--inner-gap);
width: fit-content;
min-width: 190px;
margin-left: var(--section-gap);
white-space:nowrap; white-space:nowrap;
} }

View File

@ -179,12 +179,14 @@ const register_message_buttons = async () => {
} }
const delete_conversations = async () => { const delete_conversations = async () => {
const remove_keys = [];
for (let i = 0; i < appStorage.length; i++){ for (let i = 0; i < appStorage.length; i++){
let key = appStorage.key(i); let key = appStorage.key(i);
if (key.startsWith("conversation:")) { if (key.startsWith("conversation:")) {
appStorage.removeItem(key); remove_keys.push(key);
} }
} }
remove_keys.forEach((key)=>appStorage.removeItem(key));
hide_sidebar(); hide_sidebar();
await new_conversation(); await new_conversation();
}; };
@ -274,31 +276,21 @@ const prepare_messages = (messages, filter_last_message=true) => {
} }
let new_messages = []; let new_messages = [];
if (messages) { if (systemPrompt?.value) {
for (i in messages) { new_messages.push({
new_message = messages[i];
// Remove generated images from history
new_message.content = new_message.content.replaceAll(
/<!-- generated images start -->[\s\S]+<!-- generated images end -->/gm,
""
)
delete new_message["provider"];
// Remove regenerated messages
if (!new_message.regenerate) {
new_messages.push(new_message)
}
}
}
// Add system message
system_content = systemPrompt?.value;
if (system_content) {
new_messages.unshift({
"role": "system", "role": "system",
"content": system_content "content": systemPrompt.value
}); });
} }
messages.forEach((new_message) => {
// Include only not regenerated messages
if (!new_message.regenerate) {
// Remove generated images from history
new_message.content = filter_message(new_message.content);
delete new_message.provider;
new_messages.push(new_message)
}
});
return new_messages; return new_messages;
} }
@ -413,8 +405,11 @@ const ask_gpt = async () => {
if (file && !provider) if (file && !provider)
provider = "Bing"; provider = "Bing";
let api_key = null; let api_key = null;
if (provider) if (provider) {
api_key = document.getElementById(`${provider}-api_key`)?.value || null; api_key = document.getElementById(`${provider}-api_key`)?.value || null;
if (api_key == null)
api_key = document.querySelector(`.${provider}-api_key`)?.value || null;
}
await api("conversation", { await api("conversation", {
id: window.token, id: window.token,
conversation_id: window.conversation_id, conversation_id: window.conversation_id,
@ -949,6 +944,7 @@ function count_chars(text) {
} }
function count_words_and_tokens(text, model) { function count_words_and_tokens(text, model) {
text = filter_message(text);
return `(${count_words(text)} words, ${count_chars(text)} chars, ${count_tokens(model, text)} tokens)`; return `(${count_words(text)} words, ${count_chars(text)} chars, ${count_tokens(model, text)} tokens)`;
} }
@ -1277,10 +1273,11 @@ if (SpeechRecognition) {
microLabel.classList.add("recognition"); microLabel.classList.add("recognition");
startValue = messageInput.value; startValue = messageInput.value;
lastDebounceTranscript = ""; lastDebounceTranscript = "";
timeoutHandle = window.setTimeout(may_stop, 8000); timeoutHandle = window.setTimeout(may_stop, 10000);
}; };
recognition.onend = function() { recognition.onend = function() {
microLabel.classList.remove("recognition"); microLabel.classList.remove("recognition");
messageInput.focus();
}; };
recognition.onresult = function(event) { recognition.onresult = function(event) {
if (!event.results) { if (!event.results) {
@ -1301,13 +1298,12 @@ if (SpeechRecognition) {
messageInput.value = `${startValue ? startValue+"\n" : ""}${transcript.trim()}`; messageInput.value = `${startValue ? startValue+"\n" : ""}${transcript.trim()}`;
if (isFinal) { if (isFinal) {
startValue = messageInput.value; startValue = messageInput.value;
messageInput.focus();
} }
messageInput.style.height = messageInput.scrollHeight + "px"; messageInput.style.height = messageInput.scrollHeight + "px";
messageInput.scrollTop = messageInput.scrollHeight; messageInput.scrollTop = messageInput.scrollHeight;
} }
timeoutHandle = window.setTimeout(may_stop, transcript ? 8000 : 5000); timeoutHandle = window.setTimeout(may_stop, transcript ? 10000 : 8000);
}; };
microLabel.addEventListener("click", () => { microLabel.addEventListener("click", () => {