-
Notifications
You must be signed in to change notification settings - Fork 3
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
Changes from 9 commits
cc58788
07565a1
e5732a3
e9a2c12
c941b7c
eab6189
3bbece0
3ea54bd
33bc4a2
230d2f3
aa7b351
744b33f
703efae
45f584a
9157cba
06cc6db
e128f14
b2740c7
6729ef3
ceebe0b
376c5eb
fff3ab4
e51864d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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'; | ||
|
||
|
@@ -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; | ||
|
@@ -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); | ||
|
||
|
@@ -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( | ||
|
@@ -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 | ||
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; | ||
|
@@ -99,6 +141,7 @@ export const ChatInput = ({ | |
|
||
onSend({ role: 'user', content }, plugin); | ||
setContent(''); | ||
setPromptTokenLength(0); | ||
setPlugin(null); | ||
|
||
if (window.innerWidth < 640 && textareaRef && textareaRef.current) { | ||
|
@@ -137,6 +180,7 @@ export const ChatInput = ({ | |
}; | ||
|
||
const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => { | ||
|
||
if (showPromptList) { | ||
if (e.key === 'ArrowDown') { | ||
e.preventDefault(); | ||
|
@@ -168,7 +212,7 @@ export const ChatInput = ({ | |
} else if (e.key === '/' && e.metaKey) { | ||
e.preventDefault(); | ||
setShowPluginSelect(!showPluginSelect); | ||
} | ||
} | ||
}; | ||
|
||
const parseVariables = (content: string) => { | ||
|
@@ -223,6 +267,10 @@ export const ChatInput = ({ | |
} | ||
}; | ||
|
||
const showContextInfo = () => { | ||
|
||
} | ||
|
||
useEffect(() => { | ||
if (promptListRef.current) { | ||
promptListRef.current.scrollTop = activePromptIndex * 30; | ||
|
@@ -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 && | ||
|
@@ -256,9 +315,20 @@ export const ChatInput = ({ | |
}; | ||
}, []); | ||
|
||
useEffect(() => { | ||
handleChange(event); | ||
}, [selectedConversation]); | ||
|
||
//useEffect(() => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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" | ||
|
@@ -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"> ? </span> | ||
)} | ||
</div> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
</div> | ||
</div> | ||
); | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 = { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; | ||
|
There was a problem hiding this comment.
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.