Skip to content

Commit

Permalink
Version 0.3.3
Browse files Browse the repository at this point in the history
- Add streaming response to chat
- Add stopping chat request and button
  • Loading branch information
Palm1r authored Oct 16, 2024
2 parents bf518b4 + 5b43eb4 commit 40a568e
Show file tree
Hide file tree
Showing 12 changed files with 87 additions and 49 deletions.
2 changes: 1 addition & 1 deletion QodeAssist.json.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"Name" : "QodeAssist",
"Version" : "0.3.2",
"Version" : "0.3.3",
"CompatVersion" : "${IDE_VERSION_COMPAT}",
"Vendor" : "Petr Mironychev",
"Copyright" : "(C) ${IDE_COPYRIGHT_YEAR} Petr Mironychev, (C) ${IDE_COPYRIGHT_YEAR} The Qt Company Ltd",
Expand Down
38 changes: 27 additions & 11 deletions chatview/ChatModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,28 @@ QHash<int, QByteArray> ChatModel::roleNames() const
return roles;
}

void ChatModel::addMessage(const QString &content, ChatRole role, const QString &id)
{
int tokenCount = estimateTokenCount(content);

if (!m_messages.isEmpty() && !id.isEmpty() && m_messages.last().id == id) {
Message &lastMessage = m_messages.last();
int oldTokenCount = lastMessage.tokenCount;
lastMessage.content = content;
lastMessage.tokenCount = tokenCount;
m_totalTokens += (tokenCount - oldTokenCount);
emit dataChanged(index(m_messages.size() - 1), index(m_messages.size() - 1));
} else {
beginInsertRows(QModelIndex(), m_messages.size(), m_messages.size());
m_messages.append({role, content, tokenCount, id});
m_totalTokens += tokenCount;
endInsertRows();
}

trim();
emit totalTokensChanged();
}

QVector<ChatModel::Message> ChatModel::getChatHistory() const
{
return m_messages;
Expand All @@ -92,17 +114,6 @@ int ChatModel::estimateTokenCount(const QString &text) const
return text.length() / 4;
}

void ChatModel::addMessage(const QString &content, ChatRole role)
{
int tokenCount = estimateTokenCount(content);
beginInsertRows(QModelIndex(), m_messages.size(), m_messages.size());
m_messages.append({role, content, tokenCount});
m_totalTokens += tokenCount;
endInsertRows();
trim();
emit totalTokensChanged();
}

void ChatModel::clear()
{
beginResetModel();
Expand Down Expand Up @@ -176,4 +187,9 @@ int ChatModel::tokensThreshold() const
return settings.chatTokensThreshold();
}

QString ChatModel::lastMessageId() const
{
return !m_messages.isEmpty() ? m_messages.last().id : "";
}

} // namespace QodeAssist::Chat
4 changes: 3 additions & 1 deletion chatview/ChatModel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class ChatModel : public QAbstractListModel
ChatRole role;
QString content;
int tokenCount;
QString id;
};

explicit ChatModel(QObject *parent = nullptr);
Expand All @@ -54,7 +55,7 @@ class ChatModel : public QAbstractListModel
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames() const override;

Q_INVOKABLE void addMessage(const QString &content, ChatRole role);
Q_INVOKABLE void addMessage(const QString &content, ChatRole role, const QString &id);
Q_INVOKABLE void clear();
Q_INVOKABLE QList<MessagePart> processMessageContent(const QString &content) const;

Expand All @@ -65,6 +66,7 @@ class ChatModel : public QAbstractListModel
int tokensThreshold() const;

QString currentModel() const;
QString lastMessageId() const;

signals:
void totalTokensChanged();
Expand Down
5 changes: 5 additions & 0 deletions chatview/ChatRootView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ void ChatRootView::copyToClipboard(const QString &text)
QGuiApplication::clipboard()->setText(text);
}

void ChatRootView::cancelRequest()
{
m_clientInterface->cancelRequest();
}

void ChatRootView::generateColors()
{
QColor baseColor = backgroundColor();
Expand Down
1 change: 1 addition & 0 deletions chatview/ChatRootView.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class ChatRootView : public QQuickItem
public slots:
void sendMessage(const QString &message) const;
void copyToClipboard(const QString &text);
void cancelRequest();

signals:
void chatModelChanged();
Expand Down
32 changes: 20 additions & 12 deletions chatview/ClientInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ ClientInterface::ClientInterface(ChatModel *chatModel, QObject *parent)
connect(m_requestHandler,
&LLMCore::RequestHandler::completionReceived,
this,
[this](const QString &completion, const QJsonObject &, bool isComplete) {
handleLLMResponse(completion, isComplete);
[this](const QString &completion, const QJsonObject &request, bool isComplete) {
handleLLMResponse(completion, request, isComplete);
});

connect(m_requestHandler,
Expand All @@ -56,6 +56,8 @@ ClientInterface::~ClientInterface() = default;

void ClientInterface::sendMessage(const QString &message)
{
cancelRequest();

LOG_MESSAGE("Sending message: " + message);
LOG_MESSAGE("chatProvider " + Settings::generalSettings().chatLlmProviders.stringValue());
LOG_MESSAGE("chatTemplate " + Settings::generalSettings().chatPrompts.stringValue());
Expand All @@ -74,6 +76,9 @@ void ClientInterface::sendMessage(const QString &message)
providerRequest["stream"] = true;
providerRequest["messages"] = m_chatModel->prepareMessagesForRequest(context);

if (!chatTemplate || !chatProvider) {
LOG_MESSAGE("Check settings, provider or template are not set");
}
chatTemplate->prepareRequest(providerRequest, context);
chatProvider->prepareRequest(providerRequest, LLMCore::RequestType::Chat);

Expand All @@ -89,28 +94,31 @@ void ClientInterface::sendMessage(const QString &message)
QJsonObject request;
request["id"] = QUuid::createUuid().toString();

m_accumulatedResponse.clear();
m_chatModel->addMessage(message, ChatModel::ChatRole::User);
m_chatModel->addMessage(message, ChatModel::ChatRole::User, "");
m_requestHandler->sendLLMRequest(config, request);
}

void ClientInterface::clearMessages()
{
m_chatModel->clear();
m_accumulatedResponse.clear();
LOG_MESSAGE("Chat history cleared");
}

void ClientInterface::handleLLMResponse(const QString &response, bool isComplete)
void ClientInterface::cancelRequest()
{
auto id = m_chatModel->lastMessageId();
m_requestHandler->cancelRequest(id);
}

void ClientInterface::handleLLMResponse(const QString &response,
const QJsonObject &request,
bool isComplete)
{
m_accumulatedResponse += response;
QString messageId = request["id"].toString();
m_chatModel->addMessage(response.trimmed(), ChatModel::ChatRole::Assistant, messageId);

if (isComplete) {
LOG_MESSAGE("Message completed. Final response: " + m_accumulatedResponse);
emit messageReceived(m_accumulatedResponse.trimmed());

m_chatModel->addMessage(m_accumulatedResponse.trimmed(), ChatModel::ChatRole::Assistant);
m_accumulatedResponse.clear();
LOG_MESSAGE("Message completed. Final response for message " + messageId + ": " + response);
}
}

Expand Down
5 changes: 2 additions & 3 deletions chatview/ClientInterface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,15 @@ class ClientInterface : public QObject

void sendMessage(const QString &message);
void clearMessages();
void cancelRequest();

signals:
void messageReceived(const QString &message);
void errorOccurred(const QString &error);

private:
void handleLLMResponse(const QString &response, bool isComplete);
void handleLLMResponse(const QString &response, const QJsonObject &request, bool isComplete);

LLMCore::RequestHandler *m_requestHandler;
QString m_accumulatedResponse;
ChatModel *m_chatModel;
};

Expand Down
9 changes: 9 additions & 0 deletions chatview/qml/RootItem.qml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,15 @@ ChatRootView {
text: qsTr("Send")
onClicked: sendChatMessage()
}

Button {
id: stopButton

Layout.alignment: Qt.AlignBottom
text: qsTr("Stop")
onClicked: root.cancelRequest()
}

Button {
id: clearButton

Expand Down
10 changes: 6 additions & 4 deletions llmcore/PromptTemplateManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ void PromptTemplateManager::setCurrentFimTemplate(const QString &name)
PromptTemplate *PromptTemplateManager::getCurrentFimTemplate()
{
if (m_currentFimTemplate == nullptr) {
LOG_MESSAGE("Current fim provider is null");
return nullptr;
LOG_MESSAGE("Current fim provider is null, return first");
return m_fimTemplates.first();
}

return m_currentFimTemplate;
Expand All @@ -63,8 +63,10 @@ void PromptTemplateManager::setCurrentChatTemplate(const QString &name)

PromptTemplate *PromptTemplateManager::getCurrentChatTemplate()
{
if (m_currentChatTemplate == nullptr)
LOG_MESSAGE("Current chat provider is null");
if (m_currentChatTemplate == nullptr) {
LOG_MESSAGE("Current chat provider is null, return first");
return m_chatTemplates.first();
}

return m_currentChatTemplate;
}
Expand Down
8 changes: 4 additions & 4 deletions llmcore/ProvidersManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ Provider *ProvidersManager::setCurrentChatProvider(const QString &name)
Provider *ProvidersManager::getCurrentFimProvider()
{
if (m_currentFimProvider == nullptr) {
LOG_MESSAGE("Current fim provider is null");
return nullptr;
LOG_MESSAGE("Current fim provider is null, return first");
return m_providers.first();
}

return m_currentFimProvider;
Expand All @@ -66,8 +66,8 @@ Provider *ProvidersManager::getCurrentFimProvider()
Provider *ProvidersManager::getCurrentChatProvider()
{
if (m_currentChatProvider == nullptr) {
LOG_MESSAGE("Current chat provider is null");
return nullptr;
LOG_MESSAGE("Current chat provider is null, return first");
return m_providers.first();
}

return m_currentChatProvider;
Expand Down
20 changes: 8 additions & 12 deletions llmcore/RequestHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,22 +80,18 @@ void RequestHandler::handleLLMResponse(QNetworkReply *reply,
&& processSingleLineCompletion(reply, request, accumulatedResponse, config)) {
return;
}
}

if (isComplete || reply->isFinished()) {
if (isComplete) {
if (config.requestType == RequestType::Fim) {
auto cleanedCompletion = removeStopWords(accumulatedResponse,
config.promptTemplate->stopWords());
emit completionReceived(cleanedCompletion, request, true);
} else {
emit completionReceived(accumulatedResponse, request, true);
}
} else {
emit completionReceived(accumulatedResponse, request, false);
auto cleanedCompletion = removeStopWords(accumulatedResponse,
config.promptTemplate->stopWords());
emit completionReceived(cleanedCompletion, request, true);
}
m_accumulatedResponses.remove(reply);
} else if (config.requestType == RequestType::Chat) {
emit completionReceived(accumulatedResponse, request, isComplete);
}

if (isComplete)
m_accumulatedResponses.remove(reply);
}

bool RequestHandler::cancelRequest(const QString &id)
Expand Down
2 changes: 1 addition & 1 deletion settings/GeneralSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ GeneralSettings::GeneralSettings()
chatTokensThreshold.setToolTip(Tr::tr("Maximum number of tokens in chat history. When "
"exceeded, oldest messages will be removed."));
chatTokensThreshold.setRange(1000, 16000);
chatTokensThreshold.setDefaultValue(4000);
chatTokensThreshold.setDefaultValue(8000);

loadProviders();
loadPrompts();
Expand Down

0 comments on commit 40a568e

Please sign in to comment.