-
Notifications
You must be signed in to change notification settings - Fork 0
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
fix: chat streaming and loading states (WIP) #247
Closed
Closed
Changes from all commits
Commits
Show all changes
49 commits
Select commit
Hold shift + click to select a range
41dea5a
Update body.ts
hannah-bethclark c1e52e2
Merge main
stefl 9c027ed
fix: chat streaming and loading states
stefl 72aae68
Remove number of patches from extractPatches
stefl 9f8a7b2
Remove console log
stefl 924f8e1
Merge branch 'main' into fix/stream_status
stefl f377197
Use a new approach to manage the chat state
stefl 50fbead
Merge remote-tracking branch 'origin/main' into fix/stream_status
stefl ece8d33
Use a new approach for adding the stream status to the chat
stefl b4e864c
Behaviour improvements for streaming and scrolling
stefl bf7d7f1
Linting
stefl e4eeb53
Linting and small fixes
stefl 8ecd5ba
Adjust the prompt structure and Continue action so that we generate f…
stefl bf34d8c
Ensure text is brief
stefl a762ae3
Merge remote-tracking branch 'origin/hannah-bethclark-patch-1' into f…
stefl 66bb244
Romans update
stefl 20ca3c0
Stop it picking a basedOn
stefl ac3df73
Try to make it not pick a basedOn
stefl b093f55
Continue trying to stop it doing basedOn and respond correctly
stefl a3aa37d
basedOn and learning outcomes in one
stefl 0c198da
Try even harder for basedOn
stefl 9c2bf1f
Make it clearer how to check for basedOn
stefl d8c7a7b
More basedOn
stefl 75916b4
Add placeholders
stefl 2a8f82d
Try putting the user prompting rules at the end
stefl 109956c
Lint / test fixes
stefl 5a4a03d
Fix patch enqueuer test
stefl b501fe9
Regenerate CSP snapshot tests
stefl 668246b
Fix Aila bug with categorisation and successful romans mobile test
stefl 7efc429
CSP snapshot
stefl 3653437
Mock the categoriser in test
stefl 76ed651
Catch and rethrow if there is an openai stream error
stefl 0753fde
More definition in the LLM message schema. Ask for intent on which se…
stefl 4f7438d
Ask the LLM to plan what it will edit and return what it edited
stefl 1d939e2
cycles is not a valid section ref
stefl b65c48e
Merge branch 'main' into fix/stream_status
stefl 7bd8d2e
Add .gitattributes file to hide e2e fixtures in github diffs
stefl e754518
Hide generated JSON fixtures
stefl 2fd8a10
Hide more recordings
stefl 8cf62ed
Merge branch 'main' into fix/stream_status
stefl 28e2306
Merge branch 'main' into fix/stream_status
stefl db05b35
Merge remote-tracking branch 'origin/main' into fix/stream_status
stefl a9c294c
Merge branch 'main' into fix/stream_status
stefl 87b2de6
Merge branch 'main' into fix/stream_status
stefl 244d4db
Fix merge issue, add extra logging
stefl 62a0ed8
Add extra logging
stefl 1cb69f4
Merge branch 'fix/stream_status' of https://github.com/oaknational/oa…
stefl b591254
More logging
stefl b55bd3d
Fix lesson plan keys detection
stefl File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,42 @@ | ||
import { useMemo, useEffect } from "react"; | ||
|
||
import type { LessonPlanKeys } from "@oakai/aila/src/protocol/schema"; | ||
import { aiLogger } from "@oakai/logger"; | ||
import type { Message } from "ai"; | ||
|
||
import { allSectionsInOrder } from "../../../../../lib/lessonPlan/sectionsInOrder"; | ||
|
||
const log = aiLogger("chat"); | ||
|
||
function findStreamingSections(message: Message | undefined): { | ||
streamingSections: LessonPlanKeys[]; | ||
streamingSection: LessonPlanKeys | undefined; | ||
content: string | undefined; | ||
} { | ||
if (!message?.content) { | ||
return { | ||
streamingSections: [], | ||
streamingSection: undefined, | ||
content: undefined, | ||
}; | ||
} | ||
log.info("Parsing message content", message.content); | ||
const { content } = message; | ||
const regex = /"path":"\/([^/"]*)/g; | ||
const pathMatches = | ||
content | ||
.match(regex) | ||
?.map((match) => match.replace(/"path":"\//, "").replace(/"$/, "")) ?? []; | ||
|
||
const streamingSections: LessonPlanKeys[] = pathMatches.filter( | ||
(i): i is string => | ||
typeof i === "string" && allSectionsInOrder.includes(i as LessonPlanKeys), | ||
) as LessonPlanKeys[]; | ||
const streamingSection: LessonPlanKeys | undefined = | ||
streamingSections[streamingSections.length - 1]; | ||
return { streamingSections, streamingSection, content }; | ||
} | ||
|
||
export type AilaStreamingStatus = | ||
| "Loading" | ||
| "RequestMade" | ||
|
@@ -18,36 +50,50 @@ export const useAilaStreamingStatus = ({ | |
}: { | ||
isLoading: boolean; | ||
messages: Message[]; | ||
}): AilaStreamingStatus => { | ||
const ailaStreamingStatus = useMemo<AilaStreamingStatus>(() => { | ||
const moderationStart = "MODERATION_START"; | ||
const chatStart = "CHAT_START"; | ||
if (messages.length === 0) return "Idle"; | ||
}): { | ||
status: AilaStreamingStatus; | ||
streamingSection: LessonPlanKeys | undefined; | ||
streamingSections: LessonPlanKeys[] | undefined; | ||
} => { | ||
const { status, streamingSection, streamingSections } = useMemo(() => { | ||
const moderationStart = `MODERATION_START`; | ||
const chatStart = `CHAT_START`; | ||
if (messages.length === 0) | ||
return { | ||
status: "Idle" as AilaStreamingStatus, | ||
streamingSection: undefined, | ||
}; | ||
const lastMessage = messages[messages.length - 1]; | ||
|
||
let status: AilaStreamingStatus = "Idle"; | ||
log.info("Find streaming sections", lastMessage); | ||
const { streamingSections, streamingSection, content } = | ||
findStreamingSections(lastMessage); | ||
|
||
if (isLoading) { | ||
if (!lastMessage) return "Loading"; | ||
const { content } = lastMessage; | ||
if (lastMessage.role === "user") { | ||
return "RequestMade"; | ||
} else if (content.includes(moderationStart)) { | ||
return "Moderating"; | ||
} else if ( | ||
content.includes('"type":"prompt"') || | ||
content.includes('\\"type\\":\\"prompt\\"') | ||
) { | ||
return "StreamingChatResponse"; | ||
} else if (content.includes(chatStart)) { | ||
return "StreamingLessonPlan"; | ||
if (!lastMessage || !content) { | ||
status = "Loading"; | ||
} else { | ||
if (lastMessage.role === "user") { | ||
status = "RequestMade"; | ||
} else if (content.includes(moderationStart)) { | ||
status = "Moderating"; | ||
} else if (content.includes(`"type":"text"`)) { | ||
status = "StreamingChatResponse"; | ||
} else if (content.includes(chatStart)) { | ||
status = "StreamingLessonPlan"; | ||
} else { | ||
status = "Loading"; | ||
} | ||
} | ||
return "Loading"; | ||
} | ||
return "Idle"; | ||
|
||
return { status, streamingSections, streamingSection }; | ||
}, [isLoading, messages]); | ||
|
||
useEffect(() => { | ||
log.info("ailaStreamingStatus set:", ailaStreamingStatus); | ||
}, [ailaStreamingStatus]); | ||
log.info("ailaStreamingStatus set:", status); | ||
}, [status]); | ||
|
||
return ailaStreamingStatus; | ||
return { status, streamingSection, streamingSections }; | ||
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. Adds the slug of the section that is streaming, as well as all sections that have or are streaming |
||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 think this could be extracted to a
getStatus
function that returns status, rather than needing to set and modify the status variable. Then the streamingSection(s) logic can be independent