File indexing completed on 2025-01-05 05:18:57
0001 // SPDX-FileCopyrightText: 2023 Loren Burkholder <computersemiexpert@outlook.com> 0002 // SPDX-FileCopyrightText: 2023 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> 0003 // 0004 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 0006 #pragma once 0007 0008 #include "kllmcore_export.h" 0009 #include <QJsonDocument> 0010 0011 #include "KLLMContext.h" 0012 0013 class QNetworkReply; 0014 namespace KLLMCore 0015 { 0016 /** 0017 * @brief The KLLMReply class represents a reply from an LLM. 0018 * 0019 * Requesting a completion from a KLLMInterface will return a KLLMReply. You can use this to track the progress of the LLM's 0020 * reply. 0021 * 0022 * If you want to stream a reply as it is written in real time, connect to contentAdded() and use readResponse() to retrieve 0023 * the new content. If you prefer to wait for the entire reply before displaying anything, connect to finished(), which will 0024 * only be emitted once the reply is complete. 0025 */ 0026 class KLLMCORE_EXPORT KLLMReply : public QObject 0027 { 0028 Q_OBJECT 0029 0030 public: 0031 /** 0032 * @brief Get the current response content. 0033 * 0034 * This function returns what it has recieved of the response so far. Therefore, until finished() is emitted, this 0035 * function may return different values. However, once finished() is emitted, the content is guaranteed to remain 0036 * constant. 0037 * 0038 * @return The content that has been returned so far. 0039 */ 0040 [[nodiscard]] QString readResponse() const; 0041 0042 /** 0043 * @brief Get the context token for this response. 0044 * 0045 * Messages sent by most LLMs have a context identifier that allows you to chain messages into a conversation. To create 0046 * such a conversation, you need to take this context object and set it on the next KLLMRequest in the conversation. 0047 * KLLMInterface::getCompletion() will use that context object to continue the message thread. 0048 * 0049 * @return A context object that refers to this response. 0050 */ 0051 const KLLMContext &context() const; 0052 0053 /** 0054 * @brief Check whether the reply has finished. 0055 * 0056 * If you need to know if the response has finished changing or if the context has been received yet, call this function. 0057 * 0058 * @return Whether the reply has finished. 0059 */ 0060 [[nodiscard]] bool isFinished() const; 0061 0062 protected: 0063 explicit KLLMReply(QNetworkReply *netReply, QObject *parent = nullptr); 0064 0065 friend class KLLMInterface; 0066 0067 Q_SIGNALS: 0068 /** 0069 * @brief Emits when new content has been added to the response. 0070 * 0071 * If you are not streaming the response live, this signal is not of importance to you. However, if you are streaming 0072 * content, when this signal is emitted, you should call readResponse() to update the response that your application 0073 * shows. 0074 */ 0075 void contentAdded(); 0076 0077 /** 0078 * @brief Emits when the LLM has finished returning its response. 0079 * 0080 * After this signal has emitted, the content is guaranteed to not change. At this point, you should call readResponse() 0081 * to get the content and then either take ownership of the KLLMReply or delete it, as automatic reply deletion is not 0082 * implemented yet. 0083 */ 0084 void finished(); 0085 0086 private: 0087 QNetworkReply *const m_reply; 0088 QByteArray m_incompleteTokens; 0089 0090 QList<QJsonDocument> m_tokens; 0091 0092 KLLMContext m_context; 0093 0094 int m_receivedSize = 0; 0095 bool m_finished = false; 0096 }; 0097 }