Skip to content

Commit dc196c5

Browse files
authored
Merge pull request #34 from jaebrim/main
Implemented env var to disable web grounding option and added type guards to citations
2 parents a455f8f + 62a79de commit dc196c5

File tree

4 files changed

+26
-17
lines changed

4 files changed

+26
-17
lines changed

components/Chat/ChatInput.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export const ChatInput = ({
5555
const { t } = useTranslation('chat');
5656

5757
const {
58-
state: { selectedConversation, messageIsStreaming, prompts },
58+
state: { selectedConversation, messageIsStreaming, prompts, enableWebGrounding },
5959

6060
dispatch: homeDispatch,
6161
} = useContext(HomeContext);
@@ -296,7 +296,7 @@ export const ChatInput = ({
296296
<FileUploadListing uploadFiles={uploadFiles} setUploadFiles={setUploadFiles} onCancelUpload={handleStopConversation} filesLeftToUpload={filesLeftToUpload} />
297297
<div className="relative flex">
298298
<FileUploadButton uploadFiles={uploadFiles} setUploadFiles={setUploadFiles} onCancelUpload={handleStopConversation} />
299-
<EnableGroundingButton enabled={useGrounding} onToggle={() => setUseGrounding(!useGrounding)} />
299+
{enableWebGrounding && <EnableGroundingButton enabled={useGrounding} onToggle={() => setUseGrounding(!useGrounding)} />}
300300

301301
<textarea
302302
ref={textareaRef}

pages/home/home.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,21 +49,23 @@ interface Props {
4949
serverSideApiKeyIsSet: boolean;
5050
serverSidePluginKeysSet: boolean;
5151
defaultModelId: OpenAIModelID;
52+
enableWebGrounding: boolean;
5253
}
5354

5455

5556
const Home = ({
5657
serverSideApiKeyIsSet,
5758
serverSidePluginKeysSet,
5859
defaultModelId,
60+
enableWebGrounding
5961
}: Props) => {
6062
const { t } = useTranslation('chat');
6163
const { getModels } = useApiService();
6264
const { getModelsError } = useErrorService();
6365
const [initialRender, setInitialRender] = useState<boolean>(true);
6466

6567
const contextValue = useCreateReducer<HomeInitialState>({
66-
initialState,
68+
initialState: {...initialState, enableWebGrounding }
6769
});
6870

6971
const {
@@ -414,6 +416,7 @@ export const getServerSideProps: GetServerSideProps = async ({ locale }) => {
414416

415417
const googleApiKey = process.env.GOOGLE_API_KEY;
416418
const googleCSEId = process.env.GOOGLE_CSE_ID;
419+
const enableWebGrounding = (process.env.ENABLE_WEB_GROUNDING ?? 'false').toLowerCase() === 'true';
417420

418421
if (googleApiKey && googleCSEId) {
419422
serverSidePluginKeysSet = true;

utils/home/home.state.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export interface HomeInitialState {
2727
defaultModelId: OpenAIModelID | undefined;
2828
serverSideApiKeyIsSet: boolean;
2929
serverSidePluginKeysSet: boolean;
30+
enableWebGrounding: boolean;
3031
}
3132

3233
export const initialState: HomeInitialState = {
@@ -51,4 +52,5 @@ export const initialState: HomeInitialState = {
5152
defaultModelId: undefined,
5253
serverSideApiKeyIsSet: false,
5354
serverSidePluginKeysSet: false,
55+
enableWebGrounding: false
5456
};

utils/server/index.ts

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ import { ResponseInputItem, ResponseOutputText, ResponseStreamEvent, Tool } from
99
import { Stream } from 'openai/core/streaming';
1010
import { AzureOpenAI } from 'openai';
1111

12+
type Citation = ResponseOutputText.ContainerFileCitation | ResponseOutputText.URLCitation | ResponseOutputText.FileCitation | ResponseOutputText.FilePath;
13+
type CitationWithBounds = ResponseOutputText.ContainerFileCitation | ResponseOutputText.URLCitation;
14+
type CitationWithFileId = ResponseOutputText.FileCitation | ResponseOutputText.FilePath;
15+
1216
export class OpenAIError extends Error {
1317
type: string;
1418
param: string;
@@ -23,12 +27,12 @@ export class OpenAIError extends Error {
2327
}
2428
}
2529

26-
const replaceUrlCitations = (text: string, annotations: any[]) => {
27-
if (annotations) {
28-
const urlCitations = annotations.filter(ann => ann.type === 'url_citation') as ResponseOutputText.URLCitation[];
29-
if (urlCitations.length > 0) {
30-
let result = text.substring(0, urlCitations[0].start_index - 1);
31-
urlCitations.forEach((ann) => {
30+
const replaceCitations = (text: string, annotations: Citation[]) => {
31+
const citations = annotations.filter(ann => ann.type === 'container_file_citation' || ann.type === 'url_citation') as CitationWithBounds[];
32+
if (citations) {
33+
if (citations.length > 0) {
34+
let result = text.substring(0, citations[0].start_index - 1);
35+
citations.forEach((ann) => {
3236
result += `\n\n* ${text.substring(ann.start_index, ann.end_index)}`;
3337
});
3438

@@ -39,10 +43,12 @@ const replaceUrlCitations = (text: string, annotations: any[]) => {
3943
return text;
4044
}
4145

42-
function replaceFileCitations(text: string, annotations?: any[], fileIdNameMap?: Record<string, string>): string {
46+
function replaceFileCitations(text: string, annotations: Citation[], fileIdNameMap?: Record<string, string>): string {
47+
const citations = annotations.filter(ann => ann.type === 'file_citation' || ann.type === 'file_path') as CitationWithFileId[];
48+
4349
//Support "fileciteturn0file12" style citations in GPT-5
4450
if (!fileIdNameMap) return text;
45-
if ((!annotations || annotations.length === 0) && text.indexOf("") == -1) return text;
51+
if ((!citations || citations.length === 0) && text.indexOf("") == -1) return text;
4652
let result = text;
4753
let loopBreaker = 10; // Prevent infinite loops
4854
while (/[\uE200-\uE210]/u.test(result) && --loopBreaker > 0) {
@@ -53,16 +59,14 @@ function replaceFileCitations(text: string, annotations?: any[], fileIdNameMap?:
5359
return "【5:" + p2 + "†" + realFilename + "】";
5460
});
5561
}
56-
if (annotations) {
57-
for (const ann of annotations) {
58-
if (ann.type === 'file_citation' && ann.file_id) {
59-
const citationRegex = /*(.+?)/g;
62+
if (citations) {
63+
for (const ann of citations) {
64+
const citationRegex = /*(.+?)/g;
6065
result = result.replace(citationRegex, (match, filename) => {
6166
const fileId = ann.file_id;
6267
const realFilename = fileIdNameMap[fileId] || filename;
6368
return match.replace(filename, realFilename);
6469
});
65-
}
6670
}
6771
}
6872
return result;
@@ -175,7 +179,7 @@ export const OpenAIStream = async (conversation: Conversation, userName: string,
175179

176180
case 'response.content_part.done':
177181
if (chunk.part.type === 'output_text') {
178-
text = replaceUrlCitations(chunk.part.text, chunk.part.annotations);
182+
text = replaceCitations(chunk.part.text, chunk.part.annotations);
179183
text = replaceFileCitations(text || '', chunk.part.annotations, fileIdNameMap);
180184
}
181185

0 commit comments

Comments
 (0)