¿No te encanta leer los mensajes de compromiso de los demás? ¿No? Pues a mí sí, y mientras leía un mensaje de confirmación muy perspicaz, me di cuenta de todo el contenido sin explotar que hay en varios registros de Git (suponiendo que los desarrolladores a los que sigues escriban mensajes útiles, claro). Así que, ¿no sería genial si pudieras hacer preguntas a un repositorio? Veamos cómo se puede lograr esto haciendo RAG con Couchbase Shell.
TL;DR
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# with bash, extract your commit history to json source git-log-json.sh && git-log-json > commitlog.json # with cbsh, create scope, collection and collection Primary Index scopes create gitlog; cb-env scope gitlog;collections create commits; cb-env collection commits; query "CREATE PRIMARY INDEX ON `default`:`cbsh`.`gitlog`.`commits`" # Import the doc in selected collection open commitlog.json | wrap content | insert id { |it| echo $it.content.commitHash } | doc upsert # Enrich the document with default model query "SELECT c.*, meta().id as id, c.subject || ' ' || c.body as text FROM `commits` as c" | wrap content| vector enrich-doc text | doc upsert # Create a Vector Index vector create-index --similarity-metric dot_product commits textVector 1536 # Run RAG vector enrich-text "gemini" | vector search commits textVector --neighbors 20| select id |doc get| select content | reject -i content.textVector | par-each {|x| to json} | wrap content| ask "when and in which commit was gemini llm support added" |
Configuración de Couchbase Shell
El paso inicial es instalar y configurar cbsh. Voy a utilizar mi instancia de Capella. Para obtener la configuración puede ir a Conectar de su cluster Capella y seleccione Shell de Couchbase. Esta es la configuración en [[cluster]]. Para configurar el modelo, eche un vistazo a lo que hay bajo [[llm]]. Yo he elegido OpenAI pero hay otros. Es necesario definir el modelo utilizado para la incrustación (que es lo que convierte el texto en un vector) y uno para el Chat. Este toma la pregunta y algún contexto adicional para responder a la pregunta. Y por supuesto necesitarás una clave API.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
version = 1 [[llm]] identifier = "OpenAI" provider = "OpenAI" embed_model = "text-embedding-3-small" chat_model = "gpt-3.5-turbo" api_key = "sk-proj-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" [[cluster]] identifier = "capella" connstr = "couchbases://cb.xxxxxxx.cloud.couchbase.com" user-display-name = "Laurent Doguin" username = "USER" password = "PASSWORD" default-bucket = "cbsh" default-scope = "gitlog" |
También necesitas Git instalado, entonces deberías estar todo listo.
Importar el registro de confirmaciones de Git
El primer paso es obtener todos los commits del repo en JSON. Siendo perezoso y viejo, y por viejo me refiero a no estar acostumbrado a preguntarle a una IA, busqué esto en Google, encontré una serie de Gists, que enlazaban a otras Gists, y finalmente me decidí por en este.
Lo descargué, lo busqué, entré en mi repositorio local git de couchbase-shell y lo llamé.
|
1 |
source git-log-json.sh && git-log-json > commitlog.json |
Pero, en beneficio del lector que se pregunte si he tomado la decisión correcta, preguntemos al modelo configurado. Cbsh tiene un pregunte a que le permite hacer esto:
|
1 2 3 4 5 6 |
👤 Laurent Doguin 🏠 capella in ☁️ cbsh.gitlog.commits > ask "get the full commits in json for a git repo" To get the full commits in a Git repository as JSON, you can use the following command: git log --pretty=format:'{%n "commit": "%H",%n "author": "%an <%ae>",%n "date": "%ad",%n "message": "%f"%n},' --date=iso --reverse --all > commits.json |
Este comando mostrará cada confirmación en el repositorio como un objeto JSON con el hash de la confirmación, el nombre y el correo electrónico del autor, la fecha y el mensaje de la confirmación. El comando --todos garantiza la inclusión de todas las ramas. En --reverse muestra las confirmaciones en orden cronológico inverso. Por último, la salida se redirige a un archivo commits.json archivo.
Asegúrate de ejecutar este comando en el directorio raíz del repositorio Git del que quieres obtener los commits.
Y resulta que no funciona nada más sacarlo de la caja (chocante, lo sé). Y no tenía toda la información que necesitaba, como la parte del cuerpo del mensaje. Por supuesto que podríamos pasar tiempo afinando esto, pero es muy específico, con un montón de casos extremos.
En cualquier caso ahora tengo una lista de commits en formato JSON:
|
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 |
[ { .... }, { "author": { "name": "Michael Nitschinger", "email": "michael@nitschinger.at", "date": "Thu, 20 Feb 2020 21:29:20 +0100", "dateISO8601": "2020-02-20T21:29:20+01:00" }, "body": "", "commitHash": "7a0d269fffd10045a63d40ca460deba944531890", "commitHashAbbreviated": "7a0d269", "committer": { "name": "Michael Nitschinger", "email": "michael@nitschinger.at", "date": "Thu, 20 Feb 2020 21:29:20 +0100", "dateISO8601": "2020-02-20T21:29:20+01:00" }, "encoding": "", "notes": "", "parent": "", "parentAbbreviated": "", "refs": "", "signature": { "key": "A6BCCB72D65B0D0F", "signer": "", "verificationFlag": "E" }, "subject": "Initial commit", "subjectSanitized": "Initial-commit", "tree": "3db442f3ef0438de58f72235e2658e5368a6752b", "treeAbbreviated": "3db442f" }] |
¿Qué puedes hacer con un array de objetos JSON? Puedes importarlo a través del Capella UI o puedes importarlos con Couchbase Shell. Primero creo el array alcance y colección y seleccionarlos con cb-env, luego crear el índice SQL++.
|
1 |
scopes create gitlog; cb-env scope gitlog; collections create commits; cb-env collection commits; query "CREATE PRIMARY INDEX ON `default`:`cbsh`.`gitlog`.`commits`" |
Dado que cbsh se basa en Nushell, el archivo JSON resultante puede abrirse fácilmente, convertirse en un marco de datos, transformarse en un documento Couchbase e insertarse de este modo:
|
1 2 3 4 5 6 7 8 |
👤 Laurent Doguin 🏠 capella in ☁️ cbsh.gitlog.commits > open commitlog.json |wrap content | insert id { |it| echo $it.content.commitHash }| doc upsert ╭───┬───────────┬─────────┬────────┬──────────┬─────────╮ │ # │ processed │ success │ failed │ failures │ cluster │ ├───┼───────────┼─────────┼────────┼──────────┼─────────┤ │ 0 │ 660 │ 660 │ 0 │ │ capella │ │ ╰───┴───────────┴─────────┴────────┴──────────┴─────────╯ |
Consigamos algunos documentos para ver cómo funcionaba:
|
1 2 3 4 5 6 7 |
👤 Laurent Doguin 🏠 capella in ☁️ cbsh.gitlog.commits > query "SELECT subject, body FROM `commits` LIMIT 1" ╭───┬──────────────┬──────┬─────────╮ │ # │ subject │ body │ cluster │ ├───┼──────────────┼──────┼─────────┤ │ 0 │ Bump Nushell │ │ capella │ ╰───┴──────────────┴──────┴─────────╯ |
Así que este es el contenido que podríamos utilizar para el GAR. Es hora de enriquecer estos documentos.
Enriquecer el documento con un modelo de IA
Para enriquecer el doc necesitas tener un modelo configurado. Aquí estoy usando OpenAI y el enriquecer-doc comando cbsh:
|
1 2 3 4 5 6 7 8 |
👤 Laurent Doguin 🏠 capella in ☁️ cbsh.gitlog.commits > query "SELECT c.*, meta().id as id, c.subject || ' ' || c.body as text FROM `commits` as c" | wrap content| vector enrich-doc text | doc upsert Embedding batch 1/1 ╭───┬───────────┬─────────┬────────┬──────────┬─────────╮ │ # │ processed │ success │ failed │ failures │ cluster │ ├───┼───────────┼─────────┼────────┼──────────┼─────────┤ │ 0 │ 61 │ 61 │ 0 │ │ capella │ ╰───┴───────────┴─────────┴────────┴──────────┴─────────╯ |
La cláusula SELECT devolverá un objeto JSON con el contenido del doc, y campos adicionales id y texto. El texto es el asunto y el cuerpo unidos en una cadena. El objeto se envuelve en un objeto de contenido y se da al vector enriquecer-doc con texto como parámetro, ya que es el campo que se transformará en un vector. Ahora debería haber un textVector en cada documento.
Búsqueda vectorial
Con el fin de buscar a través de estos vectores, tenemos que crear un índice de búsqueda de vectores. Se puede hacer a través de la API o la interfaz de usuario para algo personalizable. Aquí estoy feliz con las opciones por defecto así que uso cbsh en su lugar:
|
1 2 |
👤 Laurent Doguin 🏠 capella in ☁️ cbsh.gitlog.commits > vector create-index --similarity-metric dot_product commits textVector 1536 |
El índice creado utilizará punto_producto como algoritmo de similitud, la dimensionalidad del vector será 1536, el nombre del índice es escriba a y el campo indexado es textVector. El cubo, el ámbito y la colección son los seleccionados a través de cb-env.
Para probar la búsqueda vectorial, hay que convertir la consulta de búsqueda en un vector, y luego enviarlo a la búsqueda:
|
1 2 3 4 5 6 7 8 9 10 |
👤 Laurent Doguin 🏠 capella in ☁️ cbsh.gitlog.commits > vector enrich-text "TLS support" | vector search commits textVector Embedding batch 1/1 ╭───┬──────────────────────────────────────────┬────────────┬─────────╮ │ # │ id │ score │ cluster │ ├───┼──────────────────────────────────────────┼────────────┼─────────┤ │ 0 │ f2c1f124269884c88ab3925c7c5a8914298a2fbc │ 0.37283808 │ capella │ │ 1 │ da28adf7adbe910cd06c960d9c25d7316d666d1c │ 0.33915368 │ capella │ │ 2 │ f0f82353e7c060030cc2511ffab1edbcc263d099 │ 0.3294143 │ capella │ ╰───┴──────────────────────────────────────────┴────────────┴─────────╯ |
Por defecto devuelve 3 filas. Vamos a ampliarlo para ver el contenido del documento. Voy a añadir rechazar -i textVector para eliminar el campo vectorial, porque nadie necesita un campo de 1536 líneas en la salida de su terminal:
Pregunte a su repositorio Git
A partir de aquí tienes todos los commits de un repositorio Git almacenados en Couchbase, enriquecidos con un modelo de IA, y todo indexado y consultable. Lo último que hay que hacer es llamar al modelo para ejecutar una consulta con RAG. Comienza convirtiendo una pregunta en un vector, lo canaliza a una búsqueda vectorial, obtiene el documento completo a partir de los IDs de retorno, selecciona el objeto de contenido sin el campo vectorial, convierte cada objeto en un doc JSON (de esta forma podemos enviar el contenido y sus metadatos estructurados), envuelve el jsonText en una tabla y, por último, canalizarlo a la pregunte a mando:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
👤 Laurent Doguin 🏠 capella in ☁️ cbsh.gitlog.commits > vector enrich-text "gemini" | vector search commits textVector --neighbors 10| select id |doc get| select content | reject -i content.textVector | par-each {|x| to json} | wrap content| ask "when and in which commit was gemini llm support added" Embedding batch 1/1 Gemini LLM support was added in the commit with the subject "Add support for Gemini llm". This commit was authored by Jack Westwood on May 15, 2024, with the commit hash "3da9b4a3532ab4f432428319361909cc14a035af". 👤 Laurent Doguin 🏠 capella in ☁️ cbsh.gitlog.commits > git show 3da9b4a3532ab4f432428319361909cc14a035af commit 3da9b4a3532ab4f432428319361909cc14a035af Author: Jack Westwood <jack.westwood@couchbase.com> Date: Wed May 15 15:40:13 2024 +0100 Add support for Gemini llm .... |
Preguntando al LLM cuándo se introdujo el soporte Gemini. Obtenemos una fecha y un hash de confirmación. Entonces es fácil de verificar usando git show. Aquí hay un poco de repetición, así que puedes declarar una variable para tu pregunta y reutilizarla:
|
1 2 3 4 |
👤 Laurent Doguin 🏠 capella in ☁️ cbsh.gitlog.commits > let question = "why was the client crate rewritten? "; vector enrich-text $question | vector search commits textVector --neighbors 10| select id |doc get| select content | reject -i content.textVector | par-each {|x| to json} | wrap content| ask $question Embedding batch 1/1 The client crate was rewritten to address issues such as inconsistency, difficulty in usage, and code organization. The rewrite split the client into key-value (kv) and HTTP clients, each consuming a common HTTP handler. This separation into multiple clients and files improved code organization and made the clients easier to understand and use. Additionally, various improvements were made to the HTTP handler, errors, and runtime instantiation within the client crate to enhance overall functionality and performance. The rewrite effort aimed to streamline the client crate, making it more robust, maintainable, and user-friendly. |
Y ahora todos sabemos por qué hubo que reescribir la caja cliente. Puede que no responda a tus propias preguntas, ¡pero ahora ya sabes cómo obtener respuestas de cualquier repositorio!
-
- Empieza con Capella gratis
- Lea nuestro Guía de incrustaciones LLM
- Leer más de mis blogs de desarrolladores sobre búsqueda vectorial y más
- Pruebe Shell de Couchbase hoy
Muy bueno. Sería interesante incluir el changelog completo, para darle más contexto al LLM.
Sí, yo también estaba pensando en Github PR. Muchas posibilidades.