* @brief Reads and decodes the rcc:/ai/search_index.json blob. */
| 95 | * @brief Reads and decodes the rcc:/ai/search_index.json blob. |
| 96 | */ |
| 97 | void AI::DocSearch::load() |
| 98 | { |
| 99 | QFile f(QStringLiteral(":/ai/search_index.json")); |
| 100 | if (!f.open(QIODevice::ReadOnly)) { |
| 101 | qCWarning(serialStudioAI) << "DocSearch: failed to open search_index.json"; |
| 102 | return; |
| 103 | } |
| 104 | |
| 105 | QJsonParseError err; |
| 106 | const auto doc = QJsonDocument::fromJson(f.readAll(), &err); |
| 107 | if (err.error != QJsonParseError::NoError || !doc.isObject()) { |
| 108 | qCWarning(serialStudioAI) << "DocSearch: invalid index JSON:" << err.errorString(); |
| 109 | return; |
| 110 | } |
| 111 | |
| 112 | const auto root = doc.object(); |
| 113 | m_k1 = SerialStudio::toDouble(root.value(QStringLiteral("k1")), 1.5); |
| 114 | m_b = SerialStudio::toDouble(root.value(QStringLiteral("b")), 0.75); |
| 115 | m_avgdl = SerialStudio::toDouble(root.value(QStringLiteral("avgdl")), 1.0); |
| 116 | |
| 117 | const auto idf = root.value(QStringLiteral("idf")).toObject(); |
| 118 | for (auto it = idf.constBegin(); it != idf.constEnd(); ++it) |
| 119 | m_idf.insert(it.key(), SerialStudio::toDouble(it.value())); |
| 120 | |
| 121 | const auto docs = root.value(QStringLiteral("docs")).toArray(); |
| 122 | m_docs.reserve(docs.size()); |
| 123 | for (const auto& v : docs) { |
| 124 | const auto obj = v.toObject(); |
| 125 | Doc d; |
| 126 | d.id = obj.value(QStringLiteral("id")).toString(); |
| 127 | d.source = obj.value(QStringLiteral("source")).toString(); |
| 128 | d.title = obj.value(QStringLiteral("title")).toString(); |
| 129 | d.body = obj.value(QStringLiteral("body")).toString(); |
| 130 | d.length = obj.value(QStringLiteral("len")).toInt(0); |
| 131 | |
| 132 | const auto tf = obj.value(QStringLiteral("tf")).toObject(); |
| 133 | for (auto it = tf.constBegin(); it != tf.constEnd(); ++it) |
| 134 | d.tf.insert(it.key(), it.value().toInt()); |
| 135 | |
| 136 | m_docs.append(std::move(d)); |
| 137 | } |
| 138 | |
| 139 | m_loaded = true; |
| 140 | qCDebug(serialStudioAI) << "DocSearch: loaded" << m_docs.size() << "chunks"; |
| 141 | } |
| 142 | |
| 143 | /** |
| 144 | * @brief Returns up to k highest-BM25-scoring chunks. |