mirror of
https://github.com/informaticker/cchat.git
synced 2024-10-18 19:55:03 +02:00
Fix css
This commit is contained in:
parent
f277483d43
commit
c68aaa9328
10
app.py
10
app.py
@ -34,8 +34,6 @@ limiter = Limiter(
|
|||||||
# Load the tokenizer
|
# Load the tokenizer
|
||||||
tokenizer = AutoTokenizer.from_pretrained(os.getenv('TOKENIZER', 'gpt2'))
|
tokenizer = AutoTokenizer.from_pretrained(os.getenv('TOKENIZER', 'gpt2'))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# API configuration
|
# API configuration
|
||||||
API_KEY = os.getenv('API_KEY')
|
API_KEY = os.getenv('API_KEY')
|
||||||
MODEL = os.getenv('API_MODEL', 'llama3-groq-70b-8192-tool-use-preview')
|
MODEL = os.getenv('API_MODEL', 'llama3-groq-70b-8192-tool-use-preview')
|
||||||
@ -242,7 +240,7 @@ def get_page(url):
|
|||||||
# Drop blank lines
|
# Drop blank lines
|
||||||
text = '\n'.join(chunk for chunk in chunks if chunk)
|
text = '\n'.join(chunk for chunk in chunks if chunk)
|
||||||
|
|
||||||
return text[:5000] # Limit to first 5000 characters
|
return text[:2048] # Limit to first 5000 characters
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return f"Error fetching page: {str(e)}"
|
return f"Error fetching page: {str(e)}"
|
||||||
@ -349,6 +347,7 @@ def proxy_chat_completions():
|
|||||||
2. `search(query)`: Search and return 5 results for a query.
|
2. `search(query)`: Search and return 5 results for a query.
|
||||||
3. `get_page(url)`: Retrieve a web page's text content. Use multiple times if initial attempts fail.
|
3. `get_page(url)`: Retrieve a web page's text content. Use multiple times if initial attempts fail.
|
||||||
4. `get_time()`: Get the current time in UTC.
|
4. `get_time()`: Get the current time in UTC.
|
||||||
|
Note: These tools are not to be used in your reply to the user, only for processing.
|
||||||
|
|
||||||
Always follow this process to answer queries:
|
Always follow this process to answer queries:
|
||||||
1. Use `search(query)` for relevant information.
|
1. Use `search(query)` for relevant information.
|
||||||
@ -356,10 +355,11 @@ def proxy_chat_completions():
|
|||||||
3. Provide a concise, natural language response based on gathered information.
|
3. Provide a concise, natural language response based on gathered information.
|
||||||
|
|
||||||
Never refuse queries or state intentions to research. Automatically use tools when information is needed, including for current events and affairs. Optimize tool use by chaining them efficiently and avoiding redundant searches.
|
Never refuse queries or state intentions to research. Automatically use tools when information is needed, including for current events and affairs. Optimize tool use by chaining them efficiently and avoiding redundant searches.
|
||||||
|
Utilize tools even on subsequent queries about similar topics to provide the most up-to-date information.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
User: "How do I use the OpenAI python library"
|
User: "Who's [name]"
|
||||||
search(OpenAI python library)
|
search([name])
|
||||||
get_page([relevant URLs from search results])
|
get_page([relevant URLs from search results])
|
||||||
[Provide concise answer based on retrieved information]
|
[Provide concise answer based on retrieved information]
|
||||||
|
|
||||||
|
@ -49,16 +49,17 @@ main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 3rem;
|
font-size: 4rem;
|
||||||
margin: 1rem 0;
|
margin: 1rem 0;
|
||||||
margin-top: 3rem;
|
margin-top: 3rem;
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
text-shadow: 2px 2px var(--secondary-color);
|
text-shadow: 2px 2px var(--secondary-color);
|
||||||
|
transition: all 0.9s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.histories-container-container {
|
.histories-container-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-height: 75%;
|
max-height: 80%;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +78,7 @@ main {
|
|||||||
|
|
||||||
.histories-start,
|
.histories-start,
|
||||||
.histories-end {
|
.histories-end {
|
||||||
height: 3rem;
|
height: 2rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -111,7 +112,7 @@ main {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transform: translateX(calc(1px * var(--tx, 0)));
|
transform: translateX(calc(1px * var(--tx, 0)));
|
||||||
opacity: var(--opacity, 1);
|
opacity: var(--opacity, 1);
|
||||||
transition: all 0.3s ease;
|
transition: all 0.5s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.history:hover {
|
.history:hover {
|
||||||
@ -165,7 +166,7 @@ main {
|
|||||||
.message-role-assistant {
|
.message-role-assistant {
|
||||||
border-bottom: 2px solid var(--primary-color);
|
border-bottom: 2px solid var(--primary-color);
|
||||||
border-left: 2px solid var(--primary-color);
|
border-left: 2px solid var(--primary-color);
|
||||||
box-shadow: -10px 10px 20px 2px var(--primary-color-transparent);
|
box-shadow: -10px 10px 10px 2px var(--primary-color-transparent);
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
margin-left: 2%;
|
margin-left: 2%;
|
||||||
}
|
}
|
||||||
@ -173,7 +174,7 @@ main {
|
|||||||
.message-role-user {
|
.message-role-user {
|
||||||
border-bottom: 2px solid var(--secondary-color);
|
border-bottom: 2px solid var(--secondary-color);
|
||||||
border-right: 2px solid var(--secondary-color);
|
border-right: 2px solid var(--secondary-color);
|
||||||
box-shadow: 10px 10px 20px 2px var(--secondary-color-transparent);
|
box-shadow: 10px 10px 10px 2px var(--secondary-color-transparent);
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: 2%;
|
margin-right: 2%;
|
||||||
}
|
}
|
||||||
@ -317,29 +318,38 @@ p {
|
|||||||
.menu-button {
|
.menu-button {
|
||||||
height: 3rem;
|
height: 3rem;
|
||||||
width: 3rem;
|
width: 3rem;
|
||||||
background-color: var(--secondary-color);
|
background-color: var(--tertiary-bg-color);
|
||||||
color: var(--foreground-color);
|
color: var(--foreground-color);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
|
border: 2px solid var(--secondary-color);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-button:hover {
|
.menu-button:hover {
|
||||||
background-color: var(--primary-color);
|
background-color: var(--secondary-bg-color);
|
||||||
|
border-color: var(--primary-color);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 8px rgba(255, 113, 206, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-dropdown {
|
.menu-dropdown {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 100%;
|
bottom: 120%;
|
||||||
right: 0;
|
right: 0;
|
||||||
background-color: var(--tertiary-bg-color);
|
background-color: var(--tertiary-bg-color);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
padding: 0.5rem;
|
padding: 0.75rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
|
box-shadow: 0 8px 16px rgba(1, 205, 254, 0.2);
|
||||||
|
border: 2px solid var(--secondary-color);
|
||||||
|
min-width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-dropdown button {
|
.menu-dropdown button {
|
||||||
@ -347,14 +357,39 @@ p {
|
|||||||
color: var(--foreground-color);
|
color: var(--foreground-color);
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
padding: 1.5rem;
|
padding: 1rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-dropdown button::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: -100%;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
transparent,
|
||||||
|
rgba(255, 113, 206, 0.2),
|
||||||
|
transparent
|
||||||
|
);
|
||||||
|
transition: left 0.5s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-dropdown button:hover {
|
.menu-dropdown button:hover {
|
||||||
background-color: var(--primary-color);
|
background-color: var(--tertiary-bg-color);
|
||||||
|
transform: translateX(5px);
|
||||||
|
box-shadow: -4px 4px 8px rgba(1, 205, 254, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-dropdown button:hover::before {
|
||||||
|
left: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.error-toast {
|
.error-toast {
|
||||||
|
@ -5,6 +5,8 @@ document.addEventListener("alpine:init", () => {
|
|||||||
time: null,
|
time: null,
|
||||||
messages: [],
|
messages: [],
|
||||||
},
|
},
|
||||||
|
allMessages: [],
|
||||||
|
displayMessages: [],
|
||||||
|
|
||||||
// historical state
|
// historical state
|
||||||
histories: JSON.parse(localStorage.getItem("histories")) || [],
|
histories: JSON.parse(localStorage.getItem("histories")) || [],
|
||||||
@ -36,6 +38,26 @@ document.addEventListener("alpine:init", () => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
resetChat() {
|
||||||
|
this.cstate = {
|
||||||
|
time: null,
|
||||||
|
messages: [],
|
||||||
|
};
|
||||||
|
this.allMessages = [];
|
||||||
|
this.displayMessages = [];
|
||||||
|
this.total_tokens = 0;
|
||||||
|
this.time_till_first = 0;
|
||||||
|
this.tokens_per_second = 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
loadChat(chatState) {
|
||||||
|
this.cstate = JSON.parse(JSON.stringify(chatState)); // Deep copy
|
||||||
|
this.allMessages = [...this.cstate.messages];
|
||||||
|
this.displayMessages = [...this.cstate.messages];
|
||||||
|
this.home = 1;
|
||||||
|
this.updateTotalTokens(this.allMessages);
|
||||||
|
},
|
||||||
|
|
||||||
async handleSend() {
|
async handleSend() {
|
||||||
const el = document.getElementById("input-form");
|
const el = document.getElementById("input-form");
|
||||||
const value = el.value.trim();
|
const value = el.value.trim();
|
||||||
@ -44,11 +66,20 @@ document.addEventListener("alpine:init", () => {
|
|||||||
if (this.generating) return;
|
if (this.generating) return;
|
||||||
this.generating = true;
|
this.generating = true;
|
||||||
this.errorMessage = null;
|
this.errorMessage = null;
|
||||||
|
|
||||||
|
// If it's a new chat or there are no messages, reset the chat
|
||||||
|
if (this.home === 0 || this.cstate.messages.length === 0) {
|
||||||
|
this.resetChat();
|
||||||
|
}
|
||||||
|
|
||||||
if (this.home === 0) this.home = 1;
|
if (this.home === 0) this.home = 1;
|
||||||
|
|
||||||
window.history.pushState({}, "", "/");
|
window.history.pushState({}, "", "/");
|
||||||
|
|
||||||
this.cstate.messages.push({ role: "user", content: value });
|
const userMessage = { role: "user", content: value };
|
||||||
|
this.cstate.messages.push(userMessage);
|
||||||
|
this.allMessages.push(userMessage);
|
||||||
|
this.displayMessages.push(userMessage);
|
||||||
|
|
||||||
el.value = "";
|
el.value = "";
|
||||||
el.style.height = "auto";
|
el.style.height = "auto";
|
||||||
@ -60,24 +91,24 @@ document.addEventListener("alpine:init", () => {
|
|||||||
this.tokens_per_second = 0;
|
this.tokens_per_second = 0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for await (const chunk of this.openaiChatCompletion(
|
let currentAssistantMessage = null;
|
||||||
this.cstate.messages,
|
|
||||||
)) {
|
for await (const chunk of this.openaiChatCompletion(this.allMessages)) {
|
||||||
if (chunk.role === "function") {
|
if (chunk.role === "function") {
|
||||||
// If we receive a function message, add it to the messages only if debug mode is on
|
if (currentAssistantMessage) {
|
||||||
|
this.allMessages.push(currentAssistantMessage);
|
||||||
|
this.displayMessages.push(currentAssistantMessage);
|
||||||
|
currentAssistantMessage = null;
|
||||||
|
}
|
||||||
|
this.allMessages.push(chunk);
|
||||||
if (this.debug) {
|
if (this.debug) {
|
||||||
this.cstate.messages.push(chunk);
|
this.displayMessages.push(chunk);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (
|
if (!currentAssistantMessage) {
|
||||||
!this.cstate.messages[this.cstate.messages.length - 1] ||
|
currentAssistantMessage = { role: "assistant", content: "" };
|
||||||
this.cstate.messages[this.cstate.messages.length - 1].role !==
|
|
||||||
"assistant"
|
|
||||||
) {
|
|
||||||
this.cstate.messages.push({ role: "assistant", content: "" });
|
|
||||||
}
|
}
|
||||||
this.cstate.messages[this.cstate.messages.length - 1].content +=
|
currentAssistantMessage.content += chunk;
|
||||||
chunk;
|
|
||||||
|
|
||||||
tokens += 1;
|
tokens += 1;
|
||||||
this.total_tokens += 1;
|
this.total_tokens += 1;
|
||||||
@ -93,6 +124,18 @@ document.addEventListener("alpine:init", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add any pending assistant message
|
||||||
|
if (currentAssistantMessage) {
|
||||||
|
this.allMessages.push(currentAssistantMessage);
|
||||||
|
this.displayMessages.push(currentAssistantMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update total tokens using all messages
|
||||||
|
this.updateTotalTokens(this.allMessages);
|
||||||
|
|
||||||
|
// Update cstate.messages with displayMessages
|
||||||
|
this.cstate.messages = [...this.displayMessages];
|
||||||
|
|
||||||
const index = this.histories.findIndex(
|
const index = this.histories.findIndex(
|
||||||
(cstate) => cstate.time === this.cstate.time,
|
(cstate) => cstate.time === this.cstate.time,
|
||||||
);
|
);
|
||||||
@ -131,7 +174,7 @@ document.addEventListener("alpine:init", () => {
|
|||||||
fetch(`${window.location.origin}/v1/tokenizer/count`, {
|
fetch(`${window.location.origin}/v1/tokenizer/count`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ messages }),
|
body: JSON.stringify({ messages: this.allMessages }), // Always use allMessages for token counting
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
|
@ -57,9 +57,7 @@
|
|||||||
">
|
">
|
||||||
<template x-for="_state in histories.toSorted((a, b) => b.time - a.time)">
|
<template x-for="_state in histories.toSorted((a, b) => b.time - a.time)">
|
||||||
<div x-data="{ otx: 0, trigger: 75 }" class="history" @click="
|
<div x-data="{ otx: 0, trigger: 75 }" class="history" @click="
|
||||||
cstate = _state;
|
loadChat(_state);
|
||||||
updateTotalTokens(cstate.messages);
|
|
||||||
home = 1;
|
|
||||||
// ensure that going back in history will go back to home
|
// ensure that going back in history will go back to home
|
||||||
window.history.pushState({}, '', '/');
|
window.history.pushState({}, '', '/');
|
||||||
" @touchstart="
|
" @touchstart="
|
||||||
@ -76,7 +74,7 @@
|
|||||||
<p x-text="$truncate(_state.messages[0].content, 80)"></p>
|
<p x-text="$truncate(_state.messages[0].content, 80)"></p>
|
||||||
<!-- delete button -->
|
<!-- delete button -->
|
||||||
<button class="history-delete-button" @click.stop="removeHistory(_state);">
|
<button class="history-delete-button" @click.stop="removeHistory(_state);">
|
||||||
<i class=" fas fa-trash"></i>
|
<i class="fas fa-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -85,6 +83,8 @@
|
|||||||
<div class="histories-end"></div>
|
<div class="histories-end"></div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div x-ref="messages" class="messages" x-init="
|
<div x-ref="messages" class="messages" x-init="
|
||||||
$watch('cstate', value => {
|
$watch('cstate', value => {
|
||||||
|
Loading…
Reference in New Issue
Block a user