La pregunta no es la consulta
Reescribir una consulta es cambiar una pregunta antes de buscar con ella, para que la búsqueda encuentre más. Importa porque la gente escribe preguntas cortas, vagas o en dos partes, y un índice solo conoce las palabras que contiene.
«Cómo recupero mi dinero» no comparte ninguna palabra con la página que dice «reembolso». «¿Y cuántos?» solo comparte la «y», una palabra que no sirve de nada para buscar.
Al final de esta lección
Nota
Puedo reescribir una pregunta para que encuentre más y comprobar con fuentes conocidas que la reescritura ayudó.
Palabras clave
| Palabra | Qué significa |
|---|---|
| Consulta | el texto que la búsqueda recibe de verdad |
| Ampliación | añadir palabras relacionadas a una consulta |
| Descomposición | dividir una pregunta en preguntas más pequeñas |
| Pregunta de seguimiento | una pregunta que solo se entiende con la conversación |
| Sinónimo | otra palabra para la misma idea |
| Fuente conocida | la página que debe encontrar una pregunta de prueba |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Ampliar añade las palabras que usa la página
Una página sobre reembolsos dice «reembolso». Una persona dice «recuperar mi dinero». La ampliación añade palabras relacionadas a la consulta: «mi dinero» pasa a «mi dinero reembolso devolver». Una tabla de sinónimos lo hace. Un modelo también puede sugerirlos.
Conserva las palabras originales y añade más. Una ampliación que sustituye las palabras de la persona puede perder la única palabra exacta que importaba.
Una pregunta en dos partes son dos búsquedas
Toma «Estás cerrado el domingo y puedo devolver un paquete». Una sola búsqueda devuelve la página que mejor encaja con una mitad. La otra mitad se pierde.
La descomposición divide la pregunta donde dice «y» y busca cada trozo. Después se fusionan las listas, con la fusión de la lección 1.
Un seguimiento necesita la conversación
«¿Y cuántos?» no significa nada solo. Únelo a la pregunta anterior, «puedo devolver un paquete», o haz que un modelo escriba una pregunta que se entienda sola.
No envíes nunca toda la conversación: las consultas largas se desvían. Añade solo la última pregunta, y solo cuando la nueva es corta.
Un error frecuente
Advertencia
Mucha gente cree que una reescritura siempre ayuda. Un sinónimo puede llevar a la página equivocada y un historial largo puede desviar la consulta. Guarda un conjunto de preguntas de prueba con fuentes conocidas y cuenta los aciertos antes y después de cada cambio.
Escribe el ayudante del modelo, parte 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' '// Los tokens de una respuesta, o null si no trae ninguno.' 'function count(data, name) {' ' return data.usage && typeof data.usage[name] === \"number\" ? data.usage[name] : null;' '}' > model.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el ayudante del modelo, parte 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function ask(messages, sample, max) {' ' try {' ' const res = await fetch(base + \"/v1/chat/completions\", {' ' method: \"POST\",' ' headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' ' body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 100 }),' ' signal: AbortSignal.timeout(30000),' ' });' ' if (res.ok === false) throw new Error(\"estado \" + res.status);' ' const d = await res.json();' ' return { text: d.choices[0].message.content, inTokens: count(d, \"prompt_tokens\"), outTokens: count(d, \"completion_tokens\"), recorded: false };' ' } catch (error) {' ' console.log(\"Muestra grabada: ningún modelo respondió (\" + error.message + \").\");' ' return { text: sample, inTokens: null, outTokens: null, recorded: true };' ' }' '}' 'module.exports = { ask };' >> model.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el reescritor, parte 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'const docs = {' ' hours: \"la tienda abre a las nueve el sábado y cierra a la una\",' ' sunday: \"la tienda está cerrada el domingo\",' ' returns: \"puedes devolver un paquete en treinta días y recibir un reembolso\",' ' delivery: \"el envío tarda tres días y cuesta cuatro euros\",' '};' 'const synonyms = { dinero: [\"reembolso\", \"devolver\"] };' > rewrite1.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el reescritor, parte 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function stem(w) { return w.length > 3 && w.endsWith(\"s\") ? w.slice(0, -1) : w; }' 'function words(t) { return t.toLowerCase().replace(/[?¿,]/g, \"\").split(\" \").map(stem); }' 'function best(q) {' ' const w = words(q);' ' let id = \"nada\", top = 0;' ' Object.keys(docs).forEach(function (k) {' ' const n = words(docs[k]).filter(function (x) { return w.includes(x); }).length;' ' if (n > top) { top = n; id = k; }' ' });' ' return id;' '}' 'function expand(q) {' ' const extra = [];' ' q.toLowerCase().split(\" \").forEach(function (w) {' ' (synonyms[w] || []).forEach(function (s) { extra.push(s); });' ' });' ' return q + \" \" + extra.join(\" \");' '}' >> rewrite1.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el reescritor, parte 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const cases = [' ' { q: \"a qué hora abre la tienda el sábado\", want: \"hours\" },' ' { q: \"cómo recupero mi dinero\", want: \"returns\" },' ' { q: \"cuántos días tarda el envío\", want: \"delivery\" },' '];' 'let plain = 0, wider = 0;' 'cases.forEach(function (c) {' ' const a = best(c.q), b = best(expand(c.q));' ' if (a === c.want) plain++;' ' if (b === c.want) wider++;' ' console.log(c.q + \" | simple: \" + a + \" | ampliada: \" + b);' '});' 'console.log(\"aciertos simple:\", plain, \"ampliada:\", wider, \"de\", cases.length);' >> rewrite1.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el reescritor, parte 4
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const two = \"estás cerrado el domingo y puedo devolver un paquete\";' 'console.log(\"la pregunta entera encuentra:\", best(two));' 'console.log(\"la pregunta dividida encuentra:\", two.split(\" y \").map(best).join(\" + \"));' 'async function main() {' ' const text = \"Antes: puedo devolver un paquete. Ahora: cuántos días tengo. Reescribe la última pregunta para que se entienda sola. Responde solo con la pregunta.\";' ' const reply = await ask([{ role: \"user\", content: text }], \"¿Cuántos días tengo para devolver un paquete?\", 40);' ' console.log(\"reescrita:\", reply.text.trim());' ' console.log(\"encuentra:\", best(reply.text));' '}' 'main();' >> rewrite1.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Ejecuta y cuenta los aciertos
docker exec -w /home/node/project agent node rewrite1.jsSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Esto es un sustituto
El buscador cuenta las palabras compartidas en cuatro páginas. Un sistema real busca en un índice real. La única llamada al modelo reescribe un seguimiento, y el programa usa una reescritura grabada cuando ningún modelo responde.
El método no cambia con el tamaño: cambiar la consulta y contar los aciertos sobre fuentes conocidas.
Lo que imprime el Run
| Pregunta | Simple encuentra | Ampliada encuentra |
|---|---|---|
| a qué hora abre la tienda el sábado | hours | hours |
| cómo recupero mi dinero | nada | returns |
| cuántos días tarda el envío | delivery | delivery |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.