Skip to content

AI24-4 raise context limit #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
Mar 26, 2025
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
cc58788
adding context limit and display message
mTumbarello Feb 25, 2025
07565a1
added token length for conversation context
mTumbarello Feb 27, 2025
e5732a3
continuing work on context limit display
mTumbarello Mar 3, 2025
e9a2c12
continuing high token count display feature
mTumbarello Mar 7, 2025
c941b7c
continuing high token count display feature
mTumbarello Mar 10, 2025
eab6189
continuing high token count display feature
mTumbarello Mar 11, 2025
3bbece0
completed token count / context limit feature
mTumbarello Mar 13, 2025
3ea54bd
Merge branch 'AI24-4_Raise_context_limit' into A!24-6_Export_conversa…
mTumbarello Mar 17, 2025
33bc4a2
removed unnecessary logging
mTumbarello Mar 17, 2025
230d2f3
removed old commented code and updated encoder base
mTumbarello Mar 19, 2025
aa7b351
removed message length alert and fixed 'selectedConversation' warning…
mTumbarello Mar 19, 2025
744b33f
added lodash throttle to limit the amount the token count function ge…
mTumbarello Mar 20, 2025
703efae
adding local dev login for govchat dev environment
mTumbarello Mar 24, 2025
45f584a
updating for Entra auth
mTumbarello Mar 25, 2025
9157cba
switched to character count instead of token count
mTumbarello Mar 26, 2025
06cc6db
Fix conversation undefined coalescing
andychase Mar 26, 2025
e128f14
Remove debug console log
andychase Mar 26, 2025
b2740c7
Refactor maxLength in chatinput
andychase Mar 26, 2025
6729ef3
Re-work visual style of too large prompt area
andychase Mar 26, 2025
ceebe0b
Cleanups
andychase Mar 26, 2025
376c5eb
Revert "adding local dev login for govchat dev environment"
andychase Mar 26, 2025
fff3ab4
Remove glitchy conversation color for now
andychase Mar 26, 2025
e51864d
Remove unused import
andychase Mar 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 46 additions & 45 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,45 +1,46 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage
/test-results

# next.js
/.next/
/out/
/dist

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
.idea
pnpm-lock.yaml
.env
manifest.yml

# Sentry Config File
.env.sentry-build-plugin
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage
/test-results

# next.js
/.next/
/out/
/dist

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
.idea
pnpm-lock.yaml
.env
manifest.yml

# Sentry Config File
.env.sentry-build-plugin
.vs/
99 changes: 96 additions & 3 deletions components/Chat/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {

import { useTranslation } from 'next-i18next';

import { Message } from '@/types/chat';
import { Message, Conversation } from '@/types/chat';
import { Plugin } from '@/types/plugin';
import { Prompt } from '@/types/prompt';

Expand All @@ -28,6 +28,11 @@ import { PluginSelect } from './PluginSelect';
import { PromptList } from './PromptList';
import { VariableModal } from './VariableModal';

import { getTokenLength } from '@/utils/app/tokens';

import { CHARACTERS_PER_TOKEN } from '@/utils/app/const';


interface Props {
onSend: (message: Message, plugin: Plugin | null) => void;
onRegenerate: () => void;
Expand Down Expand Up @@ -62,6 +67,10 @@ export const ChatInput = ({
const [isModalVisible, setIsModalVisible] = useState(false);
const [showPluginSelect, setShowPluginSelect] = useState(false);
const [plugin, setPlugin] = useState<Plugin | null>(null);
const [promptTokenLength, setPromptTokenLength] = useState(0);
//const [contextTokenLength, setContextTokenLength] = useState(0);
const [isHighCharacterCount, setIsHighCharacterCount] = useState(false);
const [isPastCharacterCount, setIsPastCharacterCount] = useState(false);

const promptListRef = useRef<HTMLUListElement | null>(null);

Expand All @@ -71,7 +80,11 @@ export const ChatInput = ({

const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
const value = e.target.value;

//console.log("selectedConversation: " + selectedConversation?.name + " | using model: " + selectedConversation.model.id);

const maxLength = selectedConversation?.model.maxLength;
var tmpTokenCount = selectedConversation.tokenLength !== null ? selectedConversation.tokenLength : 0;

if (maxLength && value.length > maxLength) {
alert(
Expand All @@ -84,9 +97,38 @@ export const ChatInput = ({
}

setContent(value);

// only run the token count every 8 characters since it slows down the display of what's typed
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder what @Scr1ptcat thinks but consider just using the number of characters instead of calculating the tokens. Although the tokens is more accurate; given that this message is more of a warning and also that the server-side token counting may not match this "tiktok token" counting library anyway, I am not sure getting the 100% precise amount is needed.

I think as a heuristic 4 characters per token is used as you noted elsewhere.

Our GFE is quite slow and bogged down so even a little big of lagginess while people are typing would infuriate people I think.

I also think this would simplify the codebase a little bit.

if (value.length % 8 == 0) {
setPromptTokenLength(getTokenLength(value));

tmpTokenCount += promptTokenLength;
//setContextTokenLength(contextTokenLength + promptTokenLength);

//console.log(`token len: ${promptTokenLength} / ${tmpTokenCount} (from ${value.length} chars) of model : ${selectedConversation.model.id} with token limit: ${selectedConversation.model.tokenLimit}
// |||| full model info: ${JSON.stringify(selectedConversation.model)} `);

if (tmpTokenCount > selectedConversation.model.tokenLimit) {
console.log('past token limit');
setIsHighCharacterCount(false);
setIsPastCharacterCount(true);
}
else if (tmpTokenCount > (selectedConversation.model.tokenLimit * .75)) {
console.log('approaching token limit');
setIsHighCharacterCount(true);
setIsPastCharacterCount(false);
}
else {
setIsHighCharacterCount(false);
setIsPastCharacterCount(false);
}

}

updatePromptListVisibility(value);
};


const handleSend = () => {
if (messageIsStreaming) {
return;
Expand All @@ -99,6 +141,7 @@ export const ChatInput = ({

onSend({ role: 'user', content }, plugin);
setContent('');
setPromptTokenLength(0);
setPlugin(null);

if (window.innerWidth < 640 && textareaRef && textareaRef.current) {
Expand Down Expand Up @@ -137,6 +180,7 @@ export const ChatInput = ({
};

const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {

if (showPromptList) {
if (e.key === 'ArrowDown') {
e.preventDefault();
Expand Down Expand Up @@ -168,7 +212,7 @@ export const ChatInput = ({
} else if (e.key === '/' && e.metaKey) {
e.preventDefault();
setShowPluginSelect(!showPluginSelect);
}
}
};

const parseVariables = (content: string) => {
Expand Down Expand Up @@ -223,6 +267,10 @@ export const ChatInput = ({
}
};

const showContextInfo = () => {

}

useEffect(() => {
if (promptListRef.current) {
promptListRef.current.scrollTop = activePromptIndex * 30;
Expand All @@ -239,7 +287,18 @@ export const ChatInput = ({
}
}, [content]);

// Create a synthetic event object to Manually trigger the handleChange function
const event = {
target: {
value: '',
},
} as React.ChangeEvent<HTMLTextAreaElement>;


useEffect(() => {

handleChange(event);

const handleOutsideClick = (e: MouseEvent) => {
if (
promptListRef.current &&
Expand All @@ -256,9 +315,20 @@ export const ChatInput = ({
};
}, []);

useEffect(() => {
handleChange(event);
}, [selectedConversation]);

//useEffect(() => {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider removing commented out code

// console.log(`isHighCharacterCount currently set to: ${isHighCharacterCount}`);
// console.log(`isPastCharacterCount currently set to: ${isPastCharacterCount}`);

//}, [isHighCharacterCount, isPastCharacterCount]);


return (
<div className="absolute bottom-0 left-0 w-full border-transparent bg-gradient-to-b from-transparent via-white to-white pt-6 dark:border-white/20 dark:via-[#343541] dark:to-[#343541] md:pt-2">
<div className="stretch mx-2 mt-4 flex flex-row gap-3 last:mb-2 md:mx-4 md:mt-[52px] md:last:mb-6 lg:mx-auto lg:max-w-3xl">
<div className="stretch mx-2 mt-4 flex flex-row gap-3 last:mb-2 md:mx-4 md:mt-[52px] md:last:mb-12 lg:mx-auto lg:max-w-3xl">
{messageIsStreaming && (
<button
className="absolute top-0 left-0 right-0 mx-auto mb-3 flex w-fit items-center gap-3 rounded border border-neutral-200 bg-white py-2 px-4 text-black hover:opacity-50 dark:border-neutral-600 dark:bg-[#343541] dark:text-white md:mb-0 md:mt-2"
Expand Down Expand Up @@ -358,7 +428,30 @@ export const ChatInput = ({
onClose={() => setIsModalVisible(false)}
/>
)}

</div>

<div className="charLimitDisp">
{isHighCharacterCount && (

<span className="text-orange-500">
approx. characters left in conversation context:
{(selectedConversation.model.tokenLimit * CHARACTERS_PER_TOKEN) - ((selectedConversation?.tokenLength * CHARACTERS_PER_TOKEN) + content?.length)}
</span>
)}

{isPastCharacterCount && (
<span className="text-red-500">
this conversation is past the context limit. approx. characters over:
{ ((selectedConversation?.tokenLength * CHARACTERS_PER_TOKEN) + content?.length) - (selectedConversation.model.tokenLimit * CHARACTERS_PER_TOKEN)}
</span>
)}

{ (isPastCharacterCount || isHighCharacterCount) && (
<span className="helpCircle" title="Once past the context limit, the conversation will no longer produce responses relevant to content before the limit">&nbsp;&nbsp;?&nbsp;&nbsp;</span>
)}
</div>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screenshot 2025-03-17 at 3 06 25 PM

FYI here's how it appears.


</div>
</div>
);
Expand Down
16 changes: 15 additions & 1 deletion components/Chatbar/components/Conversation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const ConversationComponent = ({ conversation }: Props) => {
const [isDeleting, setIsDeleting] = useState(false);
const [isRenaming, setIsRenaming] = useState(false);
const [renameValue, setRenameValue] = useState('');
const [conversationColor, setConversationColor] = useState('text-black'); // possible colors: text-black, text-orange, text-red

const handleEnterDown = (e: KeyboardEvent<HTMLDivElement>) => {
if (e.key === 'Enter') {
Expand Down Expand Up @@ -100,6 +101,19 @@ export const ConversationComponent = ({ conversation }: Props) => {
}
}, [isRenaming, isDeleting]);

useEffect(() => {
if (conversation.id == selectedConversation.id) {
if (selectedConversation.tokenLength > selectedConversation.model.tokenLimit) {
setConversationColor('text-red-500');
} else if (selectedConversation.tokenLength > selectedConversation.model.tokenLimit * .75) {
setConversationColor('text-orange-500');
} else {
setConversationColor('text-black');
}
}
}, [selectedConversation]);


return (
<div className="relative flex items-center">
{isRenaming && selectedConversation?.id === conversation.id ? (
Expand All @@ -118,7 +132,7 @@ export const ConversationComponent = ({ conversation }: Props) => {
</div>
) : (
<button
className={`flex w-full cursor-pointer items-center gap-3 rounded-lg p-3 text-sm text-black transition-colors duration-200 hover:bg-gray-500/10 ${
className={`flex w-full cursor-pointer items-center gap-3 rounded-lg p-3 text-sm ${conversationColor} transition-colors duration-200 hover:bg-gray-500/10 ${
messageIsStreaming ? 'disabled:cursor-not-allowed' : ''
} ${
selectedConversation?.id === conversation.id
Expand Down
7 changes: 4 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions pages/api/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ import tiktokenModel from '@dqbd/tiktoken/encoders/cl100k_base.json';
import { NextApiRequest, NextApiResponse } from 'next';
import { Tiktoken } from '@dqbd/tiktoken';

export const config = {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious about this change!

api: {
bodyParser: {
sizeLimit: '2mb'
}
}
}

const handler = async (req: NextApiRequest, res: NextApiResponse<any>) => {
try {
const { model, messages, key, prompt, temperature } = req.body as ChatBody;
Expand Down
6 changes: 6 additions & 0 deletions pages/home/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ import { HomeInitialState, initialState } from '@/utils/home/home.state';

import { v4 as uuidv4 } from 'uuid';




interface Props {
serverSideApiKeyIsSet: boolean;
serverSidePluginKeysSet: boolean;
Expand Down Expand Up @@ -195,6 +198,7 @@ const Home = ({
prompt: DEFAULT_SYSTEM_PROMPT,
temperature: lastConversation?.temperature ?? DEFAULT_TEMPERATURE,
folderId: null,
tokenLength: 0,
};

const updatedConversations = [...conversations, newConversation];
Expand Down Expand Up @@ -316,8 +320,10 @@ const Home = ({

const selectedConversation = localStorage.getItem('selectedConversation');
if (selectedConversation) {

const parsedSelectedConversation: Conversation =
JSON.parse(selectedConversation);

const cleanedSelectedConversation = cleanSelectedConversation(
parsedSelectedConversation,
);
Expand Down
Loading
Loading