-
-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathllamathinkingsectionparser.cpp
More file actions
112 lines (90 loc) · 3.61 KB
/
llamathinkingsectionparser.cpp
File metadata and controls
112 lines (90 loc) · 3.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include "llamathinkingsectionparser.h"
#include "llamatr.h"
#include "llamatypes.h"
namespace LlamaCpp {
QString ThinkingSectionParser::m_startToken = "<think>";
QString ThinkingSectionParser::m_endToken = "</think>";
QString ThinkingSectionParser::startToken()
{
return m_startToken;
}
QString ThinkingSectionParser::endToken()
{
return m_endToken;
}
QPair<QString, QString> ThinkingSectionParser::parseThinkingSection(const QString &text)
{
int startIdx = text.indexOf(m_startToken);
int endIdx = text.indexOf(m_endToken);
if (startIdx != -1 && endIdx != -1 && startIdx + m_startToken.length() < endIdx) {
QString thinkingContent = text.mid(startIdx + m_startToken.length(),
endIdx - startIdx - m_startToken.length());
QString restContent = text.mid(endIdx + m_endToken.length());
return {thinkingContent, restContent};
} else if (startIdx != -1 && endIdx == -1) {
QString thinkingContent = text.mid(startIdx + m_startToken.length());
return {thinkingContent, {}};
}
return {{}, text};
}
bool ThinkingSectionParser::hasThinkingSection(const QString &text)
{
int startIdx = text.indexOf(m_startToken);
int endIdx = text.indexOf(m_endToken);
return (startIdx != -1 && endIdx != -1 && startIdx < endIdx)
|| (startIdx != -1 && endIdx == -1);
}
QString ThinkingSectionParser::formatThinkingHtml(const QString &content, bool isFinished)
{
QString statusIcon;
QString label;
if (isFinished) {
statusIcon = "<span style=\"font-family: heroicons_outline;\">Q</span>";
label = Tr::tr("Thought Process");
} else {
statusIcon = "<img src=\"spinner://tool\" style=\"vertical-align: middle;\"/>";
label = Tr::tr("Thinking");
}
return QStringLiteral("<details><summary>%1 %2</summary>\n\n%3\n</details>\n")
.arg(statusIcon, label, content);
}
QString ThinkingSectionParser::replaceThinkingSections(const QString &src, bool completed)
{
if (src.isEmpty())
return {};
QString out;
int currentPos = 0;
while (currentPos < src.length()) {
int startIdx = src.indexOf(m_startToken, currentPos);
// If no more thinking sections, append the rest of the text and exit
if (startIdx == -1) {
out.append(src.mid(currentPos));
break;
}
// Append everything from the current position up to the start token
out.append(src.mid(currentPos, startIdx - currentPos));
// Look for the end token starting from the end of the start token
int contentStart = startIdx + m_startToken.length();
int endIdx = src.indexOf(m_endToken, contentStart);
if (endIdx != -1) {
// Fully formed block <think>...</think>
QString thinkingContent = src.mid(contentStart, endIdx - contentStart);
out.append(formatThinkingHtml(thinkingContent, true));
// Move cursor past the end token
currentPos = endIdx + m_endToken.length();
// Add a separator if there is more text coming
if (currentPos < src.length()) {
out.append("\n\n");
}
} else {
// Open-ended block <think>... (streaming)
// Note: We treat the rest of the string as the thinking content
QString thinkingContent = src.mid(contentStart);
out.append(formatThinkingHtml(thinkingContent, false));
// Since this block consumes the rest of the string, we are done
currentPos = src.length();
}
}
return out;
}
} // namespace LlamaCpp