Skip to content

Commit 50e9491

Browse files
committed
use plain text for get model answer
1 parent 2701036 commit 50e9491

File tree

4 files changed

+48
-122
lines changed

4 files changed

+48
-122
lines changed

app/api/openai/route.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { type NextRequest, NextResponse } from "next/server"
22
import { createOpenAI } from '@ai-sdk/openai'
3-
import { LanguageModel, streamObject } from 'ai'
3+
import {LanguageModel, streamObject, streamText} from 'ai'
44
import { z } from 'zod'
55

66
// Define the schema for the Question object
@@ -71,9 +71,13 @@ export async function POST(req: NextRequest) {
7171
}
7272

7373
// Update system prompt to reflect we're using structured data
74-
const enhancedSystemPrompt = systemPrompt
75-
? `${systemPrompt}\n\nIMPORTANT: Return a valid structured object according to the provided schema. DO NOT use markdown formatting such as code blocks with backticks (\`\`\`). The response must be pure, parseable JSON without any markdown formatting or extra text surrounding it. Ensure all special characters in strings are properly escaped according to JSON standards.`
76-
: "IMPORTANT: Return a valid structured object according to the provided schema. DO NOT use markdown formatting such as code blocks with backticks (```). The response must be pure, parseable JSON without any markdown formatting or extra text surrounding it. Ensure all special characters in strings are properly escaped according to JSON standards.";
74+
const enhancedSystemPrompt = requestType === "modelAnswerText"
75+
? systemPrompt ?
76+
`${systemPrompt}\n\nIMPORTANT: Format your response as pure markdown. DO NOT wrap your entire response in markdown code blocks with \`\`\`markdown tags. The output should be directly renderable as markdown.`
77+
: "Format your response as pure markdown. DO NOT wrap your entire response in markdown code blocks with ```markdown tags. The output should be directly renderable as markdown."
78+
: systemPrompt
79+
? `${systemPrompt}\n\nIMPORTANT: Return a valid structured object according to the provided schema. DO NOT use markdown formatting such as code blocks with backticks (\`\`\`). The response must be pure, parseable JSON without any markdown formatting or extra text surrounding it. Ensure all special characters in strings are properly escaped according to JSON standards.`
80+
: "IMPORTANT: Return a valid structured object according to the provided schema. DO NOT use markdown formatting such as code blocks with backticks (```). The response must be pure, parseable JSON without any markdown formatting or extra text surrounding it. Ensure all special characters in strings are properly escaped according to JSON standards.";
7781

7882
const messages = [
7983
{ role: "system" as const, content: enhancedSystemPrompt },
@@ -97,6 +101,14 @@ export async function POST(req: NextRequest) {
97101
mode: "json",
98102
});
99103
streamResult = result.textStream;
104+
} else if (requestType === "modelAnswerText") {
105+
// For text/markdown response, use the raw completion without schema validation
106+
const result = await streamText({
107+
model: completion as LanguageModel,
108+
messages,
109+
temperature: 0.7,
110+
});
111+
streamResult = result.textStream;
100112
} else if (requestType === "evaluation") {
101113
const result = await streamObject({
102114
model: completion as LanguageModel,

app/page.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,8 +433,7 @@ export default function Page() {
433433
// Once streaming is complete, try to parse the final answer
434434
try {
435435
if (answer) {
436-
const parsed = JSON.parse(jsonrepair(answer))
437-
setParsedAnswer(parsed)
436+
setParsedAnswer(answer)
438437
}
439438
} catch (e) {
440439
// Keep using the raw answer if parsing fails

components/answer-display.tsx

Lines changed: 1 addition & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -70,88 +70,7 @@ export default function AnswerDisplay({
7070
}
7171

7272

73-
74-
// Use parsed answer if available, otherwise fall back to the original answer
75-
let displayAnswer = parsedAnswer ? preprocessCodeInAnswer(parsedAnswer) : answer
76-
77-
78-
// If we're getting string data but couldn't parse it
79-
if (typeof displayAnswer === "string") {
80-
return (
81-
<Card className="mb-6 shadow-sm border border-gray-200 dark:border-gray-800 bg-white dark:bg-[#2c2c2e] rounded-xl">
82-
<CardContent className="p-6">
83-
<div className="flex items-center justify-between mb-4">
84-
<h3 className="text-lg font-medium">{t("answer.modalTitle")}</h3>
85-
<div className="flex items-center space-x-2">
86-
<Badge variant="outline" className="bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400 border-blue-200 dark:border-blue-800">
87-
AI
88-
</Badge>
89-
{onRetry && (
90-
<Button variant="ghost" size="icon" onClick={onRetry} className="h-8 w-8" title={t("answer.regenerate")}>
91-
<Loader2 className={`h-4 w-4 ${isStreaming ? 'animate-spin' : ''}`} />
92-
</Button>
93-
)}
94-
{onEdit && (
95-
<Button variant="ghost" size="icon" onClick={onEdit} className="h-8 w-8" title={t("answer.editAnswer")}>
96-
<Edit className="h-4 w-4" />
97-
</Button>
98-
)}
99-
{onClose && (
100-
<Button variant="ghost" size="icon" onClick={onClose} className="h-8 w-8" title={t("answer.closeAnswer")}>
101-
<X className="h-4 w-4" />
102-
</Button>
103-
)}
104-
</div>
105-
</div>
106-
<div className="p-4">
107-
<div className="mb-4 p-2 bg-yellow-100 dark:bg-yellow-900/30 text-yellow-800 dark:text-yellow-200 rounded-md">
108-
<p>{t("answer.processFailure")}</p>
109-
</div>
110-
<div className="prose dark:prose-invert max-w-none">
111-
<div className="markdown-content">
112-
<ReactMarkdown
113-
components={{
114-
code({node, className, children, ...props}: any) {
115-
const match = /language-(\w+)/.exec(className || '')
116-
const inline = !match
117-
118-
if (!inline) {
119-
// Format code using our utility function
120-
const { code, language: detectedLanguage } = formatCodeBlock(String(children));
121-
// Use either the detected language or the one from className
122-
const langToUse = match ? match[1] : detectedLanguage;
123-
124-
return (
125-
<SyntaxHighlighter
126-
style={githubGist}
127-
language={langToUse}
128-
PreTag="div"
129-
{...props}
130-
>
131-
{code}
132-
</SyntaxHighlighter>
133-
);
134-
} else {
135-
return (
136-
<code className={className} {...props}>
137-
{children}
138-
</code>
139-
);
140-
}
141-
}
142-
}}
143-
>
144-
{displayAnswer}
145-
</ReactMarkdown>
146-
</div>
147-
</div>
148-
</div>
149-
</CardContent>
150-
</Card>
151-
)
152-
}
153-
154-
const answerContent = getProcessedContent(displayAnswer, language);
73+
const answerContent = answer;
15574

15675
return (
15776
<Card className="mb-6 shadow-sm border border-gray-200 dark:border-gray-800 bg-white dark:bg-[#2c2c2e] rounded-xl">

lib/api.ts

Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,14 @@ export async function evaluateAnswer(
181181
}
182182
}
183183

184+
// Function to clean markdown response by removing unnecessary markdown code block tags
185+
function cleanMarkdownResponse(response: string): string {
186+
// Remove ```markdown at start and ``` at end if they exist
187+
return response
188+
.replace(/^```(markdown|md)?\s*\n/i, '') // Remove opening markdown tag
189+
.replace(/\n```\s*$/i, ''); // Remove closing tag
190+
}
191+
184192
export async function getModelAnswer(question: any, language: string, onStream?: (chunk: string) => void, codeLanguage?: string) {
185193
// Use custom system prompt if available
186194
const customSystemPrompt = getCustomSystemPrompt('answer');
@@ -189,32 +197,28 @@ export async function getModelAnswer(question: any, language: string, onStream?:
189197
Your answer should be clear, efficient, and follow best practices.
190198
If it's a coding question, include well-commented code.
191199
If it's a conceptual question, provide a comprehensive explanation.
192-
Return your answer in both English and Chinese.
193-
194-
IMPORTANT: Return pure, parseable JSON without any markdown formatting. DO NOT wrap your response in code blocks with backticks (\`\`\`json or any other format).
195-
The response MUST be directly parseable as JSON without any cleanup needed.
196-
Ensure all special characters in strings are properly escaped according to JSON standards.
197200
198-
When including code examples in your answer, make sure to properly escape them as JSON strings.
199-
For example, if you need to include a code snippet with backticks, escape them properly in the JSON.${codeLanguage ? `\n\nIf code is required in the answer, prefer to use ${codeLanguage} programming language unless the question specifically requires a different language.` : ''}`;
201+
IMPORTANT: You should format your response as markdown text. Use markdown features like **bold**, *italic*, code blocks with \`\`\` for code examples, and other formatting to make your answer clear and readable.
202+
When including code examples, use proper markdown code blocks with language specification, e.g. \`\`\`javascript.
203+
DO NOT wrap your entire response in a markdown code block. Your response should be pure markdown without outer \`\`\`markdown tags.
204+
${codeLanguage ? `\n\nIf code is required in the answer, prefer to use ${codeLanguage} programming language unless the question specifically requires a different language.` : ''}`;
200205

201206
const questionTitle = question.translations[language]?.title || question.translations.en.title
202207
const questionDescription = question.translations[language]?.description || question.translations.en.description
203208

209+
// Determine language for the output
210+
const outputLanguage = language === 'zh' ? 'Chinese' : 'English';
211+
const languageComment = language === 'zh' ? '请用中文回答' : 'Please answer in English';
212+
204213
const prompt = `
205214
Question: ${questionTitle}
206215
Description: ${questionDescription}
207216
${question.testCases ? `Test Cases: ${JSON.stringify(question.testCases)}` : ""}
208217
${codeLanguage ? `\nPreferred Code Language: ${codeLanguage}\n` : ""}
209218
210-
Provide a model answer to this question in both English and Chinese.
211-
Format your response as a JSON object with this structure:
212-
{
213-
"answer": {
214-
"en": "Your English answer here",
215-
"zh": "Your Chinese answer here"
216-
}
217-
}
219+
${languageComment}. Provide a model answer to this question in ${outputLanguage}.
220+
Format your response as markdown text with appropriate formatting.
221+
IMPORTANT: DO NOT wrap your entire response in a markdown code block with \`\`\`markdown tags. Just provide the raw markdown content.
218222
`
219223

220224
try {
@@ -223,31 +227,23 @@ export async function getModelAnswer(question: any, language: string, onStream?:
223227
// If we have a streaming handler, use it
224228
if (onStream) {
225229
finalResult = await callOpenAI(prompt, systemPrompt, (chunk) => {
226-
onStream(chunk);
227-
}, "modelAnswer")
230+
// Clean the markdown tags from each chunk before sending to stream handler
231+
onStream((chunk));
232+
}, "modelAnswerText")
228233
} else {
229-
finalResult = await callOpenAI(prompt, systemPrompt, undefined, "modelAnswer")
230-
// Encode code blocks in the complete response
231-
finalResult = processAnswerWithRegexImproved(finalResult);
234+
finalResult = await callOpenAI(prompt, systemPrompt, undefined, "modelAnswerText")
232235
}
233236

234-
let cleanedResult;
235-
try {
236-
cleanedResult = processAnswerWithRegexImproved(finalResult)
237-
return JSON.parse(jsonrepair(cleanedResult));
238-
} catch (error) {
239-
console.warn("Could not parse model answer as JSON, returning raw text");
240-
return { answer: { en: finalResult, zh: finalResult } };
241-
}
237+
// Return the raw markdown text directly
238+
return finalResult
242239
} catch (error) {
243240
console.error("Error getting model answer:", error)
244241
// Return a fallback answer if API call fails
245-
return {
246-
answer: {
247-
en: "We couldn't generate a model answer due to an error. Please check your OpenAI API settings.",
248-
zh: "由于错误,我们无法生成模型答案。请检查您的 OpenAI API 设置。",
249-
},
250-
}
242+
const fallbackMessage = language === 'zh'
243+
? "由于错误,我们无法生成模型答案。请检查您的 OpenAI API 设置。"
244+
: "We couldn't generate a model answer due to an error. Please check your OpenAI API settings.";
245+
246+
return fallbackMessage;
251247
}
252248
}
253249

0 commit comments

Comments
 (0)