Skip to content

Commit b19cc4b

Browse files
authored
Merge branch 'main' into embed_assistant
2 parents 8749982 + d60cfa3 commit b19cc4b

File tree

20 files changed

+203
-44
lines changed

20 files changed

+203
-44
lines changed

.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ PARQUET_EXPORT_SECRET=#DEPRECATED, use ADMIN_API_SECRET instead
132132

133133
RATE_LIMIT= # /!\ Legacy definition of messages per minute. Use USAGE_LIMITS.messagesPerMinute instead
134134
MESSAGES_BEFORE_LOGIN=# how many messages a user can send in a conversation before having to login. set to 0 to force login right away
135+
PUBLIC_APP_GUEST_MESSAGE=# a message to the guest user. If not set, a default message will be used
135136

136137
APP_BASE="" # base path of the app, e.g. /chat, left blank as default
137138
PUBLIC_APP_NAME=ChatUI # name used as title throughout the app

chart/env/prod.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ envVars:
285285
PUBLIC_APP_COLOR: "yellow"
286286
PUBLIC_APP_DESCRIPTION: "Making the community's best AI chat models available to everyone."
287287
PUBLIC_APP_DISCLAIMER_MESSAGE: "Disclaimer: AI is an area of active research with known problems such as biased generation and misinformation. Do not use this application for high-stakes decisions or advice."
288+
PUBLIC_APP_GUEST_MESSAGE: "You have reached the guest message limit, Sign In with a free Hugging Face account to continue using HuggingChat."
288289
PUBLIC_APP_DATA_SHARING: 0
289290
PUBLIC_APP_DISCLAIMER: 1
290291
PUBLIC_PLAUSIBLE_SCRIPT_URL: "/js/script.js"

docs/source/configuration/models/providers/google.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@ MODELS=`[
3333
"type": "vertex",
3434
"project": "abc-xyz",
3535
"location": "europe-west3",
36-
"model": "gemini-1.5-pro-preview-0409", // model-name
37-
36+
"extraBody": {
37+
"model_version": "gemini-1.5-pro-002",
38+
},
3839
// Optional
3940
"safetyThreshold": "BLOCK_MEDIUM_AND_ABOVE",
4041
"apiEndpoint": "", // alternative api endpoint url,

src/lib/components/LoginModal.svelte

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@
2323
{envPublic.PUBLIC_APP_DESCRIPTION}
2424
</p>
2525
<p class="text-balance rounded-xl border bg-white/80 p-2 text-base text-gray-800">
26-
You have reached the guest message limit, <strong class="font-semibold"
27-
>Sign In with a free Hugging Face account</strong
28-
> to continue using HuggingChat.
26+
{envPublic.PUBLIC_APP_GUEST_MESSAGE}
2927
</p>
3028

3129
<form

src/lib/components/ModelCardMetadata.svelte

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22
import CarbonEarth from "~icons/carbon/earth";
33
import CarbonArrowUpRight from "~icons/carbon/arrow-up-right";
44
import BIMeta from "~icons/bi/meta";
5+
import CarbonCode from "~icons/carbon/code";
56
import type { Model } from "$lib/types/Model";
67
7-
export let model: Pick<Model, "name" | "datasetName" | "websiteUrl" | "modelUrl" | "datasetUrl">;
8+
export let model: Pick<
9+
Model,
10+
"name" | "datasetName" | "websiteUrl" | "modelUrl" | "datasetUrl" | "hasInferenceAPI"
11+
>;
812
913
export let variant: "light" | "dark" = "light";
1014
</script>
@@ -35,6 +39,16 @@
3539
<div class="max-sm:hidden">&nbsp;page</div></a
3640
>
3741
{/if}
42+
{#if model.hasInferenceAPI}
43+
<a
44+
href={"https://huggingface.co/playground?modelId=" + model.name}
45+
target="_blank"
46+
rel="noreferrer"
47+
class="flex items-center hover:underline"
48+
><CarbonCode class="mr-1.5 shrink-0 text-xs text-gray-400" />
49+
API
50+
</a>
51+
{/if}
3852
{#if model.websiteUrl}
3953
<a
4054
href={model.websiteUrl}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<script lang="ts">
2+
import { fade } from "svelte/transition";
3+
import { onDestroy } from "svelte";
4+
import IconChevron from "./icons/IconChevron.svelte";
5+
6+
export let scrollNode: HTMLElement;
7+
export { className as class };
8+
9+
let visible = false;
10+
let className = "";
11+
let observer: ResizeObserver | null = null;
12+
13+
$: if (scrollNode) {
14+
destroy();
15+
16+
if (window.ResizeObserver) {
17+
observer = new ResizeObserver(() => {
18+
updateVisibility();
19+
});
20+
observer.observe(scrollNode);
21+
}
22+
scrollNode.addEventListener("scroll", updateVisibility);
23+
}
24+
25+
function updateVisibility() {
26+
if (!scrollNode) return;
27+
visible =
28+
Math.ceil(scrollNode.scrollTop) + 200 < scrollNode.scrollHeight - scrollNode.clientHeight &&
29+
scrollNode.scrollTop > 200;
30+
}
31+
32+
function scrollToPrevious() {
33+
if (!scrollNode) return;
34+
const messages = scrollNode.querySelectorAll('[id^="message-"]');
35+
const scrollTop = scrollNode.scrollTop;
36+
let previousMessage: Element | null = null;
37+
38+
for (let i = messages.length - 1; i >= 0; i--) {
39+
const messageTop =
40+
messages[i].getBoundingClientRect().top +
41+
scrollTop -
42+
scrollNode.getBoundingClientRect().top;
43+
if (messageTop < scrollTop - 1) {
44+
previousMessage = messages[i];
45+
break;
46+
}
47+
}
48+
49+
if (previousMessage) {
50+
previousMessage.scrollIntoView({ behavior: "smooth", block: "start" });
51+
}
52+
}
53+
54+
function destroy() {
55+
observer?.disconnect();
56+
scrollNode?.removeEventListener("scroll", updateVisibility);
57+
}
58+
59+
onDestroy(destroy);
60+
</script>
61+
62+
{#if visible}
63+
<button
64+
transition:fade={{ duration: 150 }}
65+
on:click={scrollToPrevious}
66+
class="btn absolute flex h-[41px] w-[41px] rounded-full border bg-white shadow-md transition-all hover:bg-gray-100 dark:border-gray-600 dark:bg-gray-700 dark:shadow-gray-950 dark:hover:bg-gray-600 {className}"
67+
>
68+
<IconChevron classNames="rotate-180 mt-[2px]" />
69+
</button>
70+
{/if}

src/lib/components/chat/ChatInput.svelte

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script lang="ts">
2-
import { isDesktop } from "$lib/utils/isDesktop";
2+
import { browser } from "$app/environment";
33
import { createEventDispatcher, onMount } from "svelte";
44
55
export let value = "";
@@ -13,25 +13,41 @@
1313
1414
const dispatch = createEventDispatcher<{ submit: void }>();
1515
16+
function isVirtualKeyboard(): boolean {
17+
if (!browser) return false;
18+
19+
// Check for touch capability
20+
if (navigator.maxTouchPoints > 0) return true;
21+
22+
// Check for touch events
23+
if ("ontouchstart" in window) return true;
24+
25+
// Fallback to user agent string check
26+
const userAgent = navigator.userAgent.toLowerCase();
27+
28+
return /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent);
29+
}
30+
1631
$: minHeight = `${1 + minRows * 1.5}em`;
1732
$: maxHeight = maxRows ? `${1 + maxRows * 1.5}em` : `auto`;
1833
1934
function handleKeydown(event: KeyboardEvent) {
20-
// submit on enter
2135
if (event.key === "Enter" && !event.shiftKey && !isCompositionOn) {
2236
event.preventDefault();
23-
// blur to close keyboard on mobile
24-
textareaElement.blur();
25-
// refocus so that user on desktop can start typing without needing to reclick on textarea
26-
if (isDesktop(window)) {
27-
textareaElement.focus();
37+
if (isVirtualKeyboard()) {
38+
// Insert a newline at the cursor position
39+
const start = textareaElement.selectionStart;
40+
const end = textareaElement.selectionEnd;
41+
value = value.substring(0, start) + "\n" + value.substring(end);
42+
textareaElement.selectionStart = textareaElement.selectionEnd = start + 1;
43+
} else {
44+
dispatch("submit");
2845
}
29-
dispatch("submit"); // use a custom event instead of `event.target.form.requestSubmit()` as it does not work on Safari 14
3046
}
3147
}
3248
3349
onMount(() => {
34-
if (isDesktop(window)) {
50+
if (!isVirtualKeyboard()) {
3551
textareaElement.focus();
3652
}
3753
});
@@ -44,7 +60,7 @@
4460
style="min-height: {minHeight}; max-height: {maxHeight}">{(value || " ") + "\n"}</pre>
4561

4662
<textarea
47-
enterkeyhint="send"
63+
enterkeyhint={!isVirtualKeyboard() ? "enter" : "send"}
4864
tabindex="0"
4965
rows="1"
5066
class="scrollbar-custom absolute top-0 m-0 h-full w-full resize-none scroll-p-3 overflow-x-hidden overflow-y-scroll border-0 bg-transparent p-3 outline-none focus:ring-0 focus-visible:ring-0"

src/lib/components/chat/ChatMessage.svelte

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@
230230
{#if message.from === "assistant"}
231231
<div
232232
class="group relative -mb-4 flex items-start justify-start gap-4 pb-4 leading-relaxed"
233+
id="message-assistant-{message.id}"
233234
role="presentation"
234235
on:click={() => (isTapped = !isTapped)}
235236
on:keydown={() => (isTapped = !isTapped)}
@@ -372,6 +373,7 @@
372373
{#if message.from === "user"}
373374
<div
374375
class="group relative w-full items-start justify-start gap-4 max-sm:text-sm"
376+
id="message-user-{message.id}"
375377
role="presentation"
376378
on:click={() => (isTapped = !isTapped)}
377379
on:keydown={() => (isTapped = !isTapped)}

src/lib/components/chat/ChatWindow.svelte

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import AssistantIntroduction from "./AssistantIntroduction.svelte";
2828
import ChatMessage from "./ChatMessage.svelte";
2929
import ScrollToBottomBtn from "../ScrollToBottomBtn.svelte";
30+
import ScrollToPreviousBtn from "../ScrollToPreviousBtn.svelte";
3031
import { browser } from "$app/environment";
3132
import { snapScrollToBottom } from "$lib/actions/snapScrollToBottom";
3233
import SystemPromptModal from "../SystemPromptModal.svelte";
@@ -329,8 +330,14 @@
329330
/>
330331
{/if}
331332
</div>
333+
334+
<ScrollToPreviousBtn
335+
class="fixed right-4 max-md:bottom-[calc(50%+26px)] md:bottom-48 lg:right-10"
336+
scrollNode={chatContainer}
337+
/>
338+
332339
<ScrollToBottomBtn
333-
class="bottom-36 right-4 max-md:hidden lg:right-10"
340+
class="fixed right-4 max-md:bottom-[calc(50%-26px)] md:bottom-36 lg:right-10"
334341
scrollNode={chatContainer}
335342
/>
336343
</div>

src/lib/server/endpoints/cohere/endpointCohere.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export async function endpointCohere(
6262
});
6363

6464
stream = await cohere.chatStream({
65+
forceSingleStep: true,
6566
message: prompt,
6667
rawPrompting: true,
6768
model: model.id ?? model.name,
@@ -82,6 +83,7 @@ export async function endpointCohere(
8283

8384
stream = await cohere
8485
.chatStream({
86+
forceSingleStep: true,
8587
model: model.id ?? model.name,
8688
chatHistory: formattedMessages.slice(0, -1),
8789
message: formattedMessages[formattedMessages.length - 1].message,

0 commit comments

Comments
 (0)