Lección 19: Los pares de voicings
Secciones
Ajustes de lectura
Ninguna voz para este idioma en este navegador.
Más voces
Código y términos técnicos en inglés
Desactivado: la voz de la página lo lee todo, sin pausa entre dos voces.
Ninguna voz para este idioma en este navegador.
Más voces
Más voces: Microsoft Edge ofrece voces naturales en línea, y Windows (Configuración › Hora e idioma › Voz), macOS y Android instalan otras.
La lección 18 le preguntó al chatbot cómo pasar de un acorde al siguiente. Su skill respondió con clases de altura, sin octava ni traste, y la lección se detuvo ante otra vía de GA, una que mueve voicings reales. Esta lección la ejecuta. ga_voice_leading_pair es una herramienta de GaMcpServer, el servidor MCP de GA, cuyas herramientas pueden llamar agentes como Claude Code. Dados dos cifrados, le pide al índice OPTIC-K de la lección 3 15 voicings de cada acorde, mide cada par con una distancia en semitonos y devuelve los cinco pares de menor distancia (CompositionTools.cs líneas 179-268). El chatbot no la llama: sus propias herramientas son otras, y la skill redactada para llamar a esta está en espera (skills-dev/_pending-tools/README.md líneas 19-29).
Todos los enlaces a GA apuntan al commit a826864, el commit fijado del curso, salvo los que nombran otro. CompositionTools.cs es idéntico en el main de GA en f4f5b4a (2026-10-01), pero la búsqueda a la que llama cambió después del commit fijado, como mostró la lección 16. El programa compila el archivo de la herramienta de cada clon de GA en los dos programas del curso y lo apunta al índice de la lección 3: en GaAi, al del commit fijado, y en GaMain, al índice que el código de main escribe a partir del mismo corpus. La salida procede de:
dotnet run --project code/ga-ai/GaAi -c Release -- l19dotnet run --project code/ga-ai/GaMain -c Release -- l19Cómo responde la herramienta
Sección titulada «Cómo responde la herramienta»SearchByChordAsync lee el cifrado con ChordPitchClasses, el lector de la lección 16, lo convierte en un vector de consulta y le pide al índice los voicings más cercanos (líneas 278-298):
private static async Task<SearchOutcome> SearchByChordAsync( string chordSymbol, int limit, string? instrument, CancellationToken ct) { if (!ChordPitchClasses.TryParse(chordSymbol.Trim(), out var rootPc, out var pcs) || rootPc is null) return new([], $"unrecognized chord symbol '{chordSymbol}'");
var structured = new StructuredQuery( ChordSymbol: chordSymbol.Trim(), RootPitchClass: rootPc, PitchClasses: pcs, ModeName: null, Tags: null);
var vec = EncoderShared.Value.Encode(structured); var strategy = GetStrategy(); var hits = string.IsNullOrWhiteSpace(instrument) ? await strategy.SemanticSearchAsync(vec, limit, ct) : await strategy.HybridSearchAsync(vec, new VoicingSearchFilters(VoicingType: instrument), limit, ct);
return new(hits, null); }La consulta no nombra ningún acorde: cuando no se indica instrumento, los candidatos son los voicings cuyos vectores están más cerca de la consulta, toquen lo que toquen. GetStrategy toma la búsqueda de VoicingSearchTool, la herramienta de búsqueda del servidor, leyendo su campo privado Strategy (líneas 300-310). Esa clase encuentra el índice mediante GA_OPTICK_INDEX_PATH o en state/voicings/ (VoicingSearchTool.cs líneas 64-83). El curso compila esa clase a partir del código fuente de GA y la dirige al índice de la lección 3 mediante GA_OPTICK_INDEX_PATH (code/ga-ai/Shared/SearchIndex.cs).
La herramienta mide cada par de candidatos con VoiceLeadingDistance (líneas 312-336):
/// <summary> /// Sum of absolute semitone differences under greedy ascending-pitch matching. /// For voicings of unequal note count, the shorter one pairs against its nearest /// neighbors and the remainder contributes a small per-note penalty (simulating /// "voice appears from silence" / "voice disappears"). This is not a formal /// Hungarian-optimal assignment — it's O(n log n) and produces a ranking good /// enough to surface smooth voice-leadings among candidates. /// </summary> private static double VoiceLeadingDistance(IReadOnlyList<int> midi1, IReadOnlyList<int> midi2) { if (midi1.Count == 0 || midi2.Count == 0) return double.MaxValue;
var a = midi1.OrderBy(n => n).ToArray(); var b = midi2.OrderBy(n => n).ToArray(); var common = Math.Min(a.Length, b.Length);
double sum = 0; for (var i = 0; i < common; i++) sum += Math.Abs(a[i] - b[i]);
// Penalty for unmatched voices (extra notes on either side). var extras = Math.Abs(a.Length - b.Length); sum += extras * 3.0; // soft penalty — 3 semitones per orphan note. return sum; }La distancia ordena las notas MIDI de los dos voicings, las empareja de la más grave hacia arriba, suma las diferencias y cuenta 3 semitonos por cada nota que queda sin pareja. Luego la herramienta ordena los pares por distancia y, en caso de empate, por la suma de sus dos puntuaciones de búsqueda (líneas 224-235).
Los candidatos
Sección titulada «Los candidatos»El programa pide los candidatos de los 14 acordes de los diez prompts de ejemplo de VoiceLeadingSkill (lección 18) y compara cada voicing con el acorde tal como lo escribe un manual, como hizo la lección 16: exact cuando el voicing toca las notas del acorde y ninguna otra, more cuando las toca junto con otras, part cuando solo toca algunas, other en cualquier otro caso. Un acorde de séptima al que solo le falta la quinta justa recibe su propio veredicto, no fifth: los voicings shell omiten la quinta, y un guitarrista los usa para tocar el acorde. El curso da por correctos los veredictos exact y no fifth. El programa cuenta también los voicings exactos de cada acorde en todo el índice:
== The 15 candidates the tool pairs for each chord, at the pin, against the chord a textbook spellschord exact no fifth more part other exact in the index first exact candidateC 10 0 0 5 0 63 rank 1F 15 0 0 0 0 35 rank 1Am 3 0 0 10 2 35 rank 1G7 0 15 0 0 0 49 noneCmaj7 5 3 0 7 0 42 rank 4Dm7 0 5 0 10 0 25 noneG 15 0 0 0 0 35 rank 1Em 15 0 0 0 0 63 rank 1A7 0 2 0 7 6 35 noneFmaj7 0 15 0 0 0 60 noneBm7b5 4 0 0 11 0 25 rank 1D 7 0 0 5 3 27 rank 1A 5 0 0 5 5 21 rank 11C7 1 12 0 2 0 49 rank 15candidates 210: exact 80, no fifth 52, more 0, part 62, other 16- En el commit fijado, 80 de los 210 candidatos son exactos, y a otros 52 solo les falta la quinta. G7, Dm7, A7 y Fmaj7 no reciben ningún voicing exacto entre sus 15, aunque el índice contiene 49, 25, 35 y 60, respectivamente. G7 y Fmaj7 reciben, eso sí, 15 voicings sin la quinta. A recibe su primer voicing exacto en el puesto 11, y C7, en el 15.
- Los demás tocan una parte del acorde, u otras notas. Para C, 5 de los 15 tocan una parte, como el C5 de la tabla siguiente, que no tiene E.
== The 15 candidates the tool pairs for each chord, on main, against the chord a textbook spellschord exact no fifth more part other exact in the index first exact candidateC 15 0 0 0 0 63 rank 1F 15 0 0 0 0 35 rank 1Am 15 0 0 0 0 35 rank 1G7 15 0 0 0 0 49 rank 1Cmaj7 15 0 0 0 0 42 rank 1Dm7 15 0 0 0 0 25 rank 1G 15 0 0 0 0 35 rank 1Em 15 0 0 0 0 63 rank 1A7 15 0 0 0 0 35 rank 1Fmaj7 15 0 0 0 0 60 rank 1Bm7b5 15 0 0 0 0 25 rank 1D 15 0 0 0 0 27 rank 1A 15 0 0 0 0 21 rank 1C7 15 0 0 0 0 49 rank 1candidates 210: exact 210, no fifth 0, more 0, part 0, other 0- En
main, los 210 candidatos son exactos. La herramienta es la misma; la búsqueda a la que llama solo devuelve voicings del acorde pedido, para cada uno de los 14 acordes.
El primer par
Sección titulada «El primer par»Para cada prompt, el programa comprueba los dos voicings del primero de los cinco pares, y cuenta los pares, entre los cinco, cuyos dos voicings son correctos. También busca en todo el índice el par de voicings exactos que menos mueve según la propia distancia de la herramienta, y da el movimiento mínimo de la lección 18, en clases de altura. El programa escribe cada diagrama en el orden de los diagramas de acordes, empezando por la E grave:
== The tool's first pair for each prompt, at the pin, and the smoothest pair of exact voicings in the indexprompt first pair: from to both right smoothest exact pair in the index least in pitch classesC → F 5: x-3-x-0-1-x C5, part x-3-x-2-1-1 F/C, exact 4 of 5 3: x-x-x-0-1-0 → x-x-x-2-1-1 3C → Am 3: x-3-2-x-1-x C + E (Major 3rd), part x-3-2-2-x-x Am/C, exact 0 of 5 2: x-x-x-0-1-0 → x-x-x-2-1-0 2G7 → Cmaj7 3: x-2-3-x-0-3 G7(shell)/B, no fifth x-2-x-0-1-3 C5/B, part 1 of 5 3: x-x-0-0-0-1 → x-3-x-0-0-0 3Dm7 → G7 6: x-3-3-x-3-x Dm7(shell)/C, no fifth x-2-3-x-x-3 G7(shell)/B, no fifth 5 of 5 3: x-x-0-2-1-1 → x-x-0-0-0-1 3C → G 6: x-x-2-0-1-x C/E, exact x-x-0-0-0-3 G/D, exact 4 of 5 3: x-x-2-x-1-3 → x-x-0-x-0-3 3Em → A7 5: 3-x-2-x-0-0 Em/G, exact 3-x-2-2-x-x A5/G, part 0 of 5 4: x-x-2-0-0-3 → x-x-2-2-2-3 4Fmaj7 → Bm7b5 4: 0-0-3-x-x-x Fmaj7(shell)/E, no fifth 1-0-3-x-0-x Bm7b5/F, part 1 of 5 3: x-x-2-2-1-1 → x-x-0-2-0-1 3D → A 4: x-0-x-2-3-x D5, part x-0-x-2-2-0 A, exact 0 of 5 3: x-x-x-2-3-2 → x-x-x-2-2-0 3C7 → F 4: x-3-x-3-1-x Bb + C (Major 2nd), part x-3-x-2-1-1 F/C, exact 4 of 5 4: x-x-2-3-1-3 → x-x-3-2-1-1 4G7 → C 5: x-x-3-0-0-3 G7(shell)/F, no fifth x-x-2-0-1-x C/E, exact 5 of 5 4: x-x-0-0-0-1 → x-x-2-0-1-0 4prompts 10: first pair right on both sides 3, moves more than the smoothest exact pair 8; that pair moves the least in pitch classes 10the first pair for C → F, as the tool returns it: diagram x-1-0-x-3-x → 1-1-2-x-3-x- En el commit fijado, 3 de los 10 primeros pares tocan los dos acordes. C → F parte de
x-3-x-0-1-x, un C5 que toca C y G pero no E. Em → A7 termina en3-x-2-2-x-x, A y E sobre G, sin C♯. - En 8 casos, el primer par mueve más que un par de voicings correctos del índice. C → G recibe dos voicings exactos que mueven 6 semitonos, mientras que
x-x-2-x-1-3→x-x-0-x-0-3mueve 3: ese par no está entre los 15 candidatos de C y de G. - El par exacto que menos mueve alcanza el movimiento mínimo de la lección 18 en los diez prompts. En el corpus de la lección 3, los voicings reales se mueven tan poco como lo permiten las clases de altura.
== The tool's first pair for each prompt, on main, and the smoothest pair of exact voicings in the indexprompt first pair: from to both right smoothest exact pair in the index least in pitch classesC → F 3: x-x-x-0-1-0 C/G, exact x-x-x-2-1-1 F/A, exact 5 of 5 3: x-x-x-0-1-0 → x-x-x-2-1-1 3C → Am 2: x-x-x-0-1-0 C/G, exact x-x-x-2-1-0 Am, exact 5 of 5 2: x-x-x-0-1-0 → x-x-x-2-1-0 2G7 → Cmaj7 3: x-x-0-0-0-1 G7/D, exact x-3-x-0-0-0 Cmaj7, exact 5 of 5 3: x-x-0-0-0-1 → x-3-x-0-0-0 3Dm7 → G7 3: x-x-0-2-1-1 Dm7, exact x-x-0-0-0-1 G7/D, exact 5 of 5 3: x-x-0-2-1-1 → x-x-0-0-0-1 3C → G 3: x-x-2-x-1-3 C/E, exact x-x-0-x-0-3 G/D, exact 5 of 5 3: x-x-2-x-1-3 → x-x-0-x-0-3 3Em → A7 4: x-x-2-0-0-3 Em, exact x-x-2-2-2-3 A7/E, exact 5 of 5 4: x-x-2-0-0-3 → x-x-2-2-2-3 4Fmaj7 → Bm7b5 3: x-x-2-2-1-1 Fmaj7/E, exact x-x-0-2-0-1 Bm7b5/D, exact 5 of 5 3: x-x-2-2-1-1 → x-x-0-2-0-1 3D → A 3: x-x-x-2-3-2 D/A, exact x-x-x-2-2-0 A, exact 5 of 5 3: x-x-x-2-3-2 → x-x-x-2-2-0 3C7 → F 4: x-x-2-3-1-3 C7/E, exact x-x-3-2-1-1 F, exact 5 of 5 4: x-x-2-3-1-3 → x-x-3-2-1-1 4G7 → C 4: x-x-0-0-0-1 G7/D, exact x-x-2-0-1-0 C/E, exact 5 of 5 4: x-x-0-0-0-1 → x-x-2-0-1-0 4prompts 10: first pair right on both sides 10, moves more than the smoothest exact pair 0; that pair moves the least in pitch classes 10the first pair for C → F, as the tool returns it: diagram 0-1-0-x-x-x → 1-1-2-x-x-x- En
main, cada primer par toca los dos acordes, y es el par de voicings exactos que menos mueve en todo el índice. Los cinco pares de cada prompt son correctos. - La herramienta devuelve sus diagramas empezando por la E aguda, también en
main. La última línea da el primer par de C → F tal como lo devuelve la herramienta:0-1-0-x-x-xesx-x-x-0-1-0leído desde la E aguda. El índice escribe primero la cuerda 1 (diferencia 13 de la entrada del 2026-09-14 del diario). Enmain, la skill de voicings pasa esa cadena al orden de los diagramas de acordes antes de responder (ChordVoicingsSkill.cslínea 136 enmain), pero la herramienta devuelve la cadena del índice tal cual (CompositionTools.cslíneas 239-254). Un cliente que lea0-1-0-x-x-xcomo un diagrama de acordes pone los dedos en las cuerdas equivocadas.
Cincuenta candidatos
Sección titulada «Cincuenta candidatos»La descripción de candidatesPerChord promete “Higher = more exhaustive pair search, slower” (más alto = búsqueda de pares más exhaustiva, más lenta) (línea 195). El programa vuelve a preguntar con 50 candidatos por acorde, el máximo que admite la herramienta (línea 203):
== The first pair with 50 candidates per chord, the most the tool allows, at the pinprompt distance from to first pairC → F 3 part part 0-x-2-x-x-0 E (unison) → 1-x-3-x-x-1 F (unison)C → Am 0 part part 0-x-2-x-x-0 E (unison) → 0-x-2-x-x-0 E (unison)G7 → Cmaj7 3 no fifth part x-2-3-x-0-3 G7(shell)/B → x-2-x-0-1-3 C5/BDm7 → G7 3 other part 1-x-3-0-3-x G5/F → 1-x-3-0-x-x F + G (Major 2nd)C → G 0 part part 3-x-x-0-x-3 G (unison) → 3-x-x-0-x-3 G (unison)Em → A7 0 other part x-0-x-0-x-0 A5 → x-0-x-0-x-0 A5Fmaj7 → Bm7b5 1 part other 0-x-3-x-1-x F5/E → 0-x-3-x-0-x E5D → A 2 part part x-0-x-2-3-x D5 → x-0-x-2-x-0 A5C7 → F 4 part exact x-3-x-3-1-x Bb + C (Major 2nd) → x-3-x-2-1-1 F/CG7 → C 2 part part 1-x-x-0-x-3 F + G (Major 2nd) → 3-x-x-0-x-3 G (unison)prompts 10: first pair right on both sides 0- En el commit fijado, ningún primer par toca los dos acordes. C → Am recibe
0-x-2-x-x-0a ambos lados: la cuerda E grave, la cuerda D en el segundo traste y la cuerda E aguda, tres E. E es una nota de los dos acordes, y ninguna voz se mueve. C → G y Em → A7 también reciben el mismo voicing a ambos lados. - La distancia premia el movimiento, no el acorde. Una búsqueda más amplia trae unísonos y quintas vacías, que mueven menos, y la herramienta no comprueba nada de lo que empareja.
== The first pair with 50 candidates per chord, the most the tool allows, on mainprompt distance from to first pairC → F 3 exact exact x-x-x-0-1-0 C/G → x-x-x-2-1-1 F/AC → Am 2 exact exact x-x-x-0-1-0 C/G → x-x-x-2-1-0 AmG7 → Cmaj7 2 more more x-2-2-0-3-1 G7/B → x-2-2-0-1-1 Cmaj7/BDm7 → G7 3 exact exact x-x-0-2-1-1 Dm7 → x-x-0-0-0-1 G7/DC → G 3 exact exact x-x-2-x-1-3 C/E → x-x-0-x-0-3 G/DEm → A7 4 exact exact x-x-2-0-0-3 Em → x-x-2-2-2-3 A7/EFmaj7 → Bm7b5 3 exact exact x-x-2-2-1-1 Fmaj7/E → x-x-0-2-0-1 Bm7b5/DD → A 2 more more x-x-0-2-2-2 Dmaj7 → x-x-0-2-2-0 Aadd11/DC7 → F 4 exact exact x-x-2-3-1-3 C7/E → x-x-3-2-1-1 FG7 → C 4 exact exact x-x-0-0-0-1 G7/D → x-x-2-0-1-0 C/Eprompts 10: first pair right on both sides 8- En
main, el primer par toca los dos acordes en 8 prompts, y en los otros dos toca además otras notas. G7 → Cmaj7 muevex-2-2-0-3-1ax-2-2-0-1-1con 2 semitonos, donde 15 candidatos daban 3: el primero añade E a G7, y el segundo, F a Cmaj7. D → A mueve un Dmaj7 a un A con un D, con 2 en lugar de 3. - Tanto en el commit fijado como en
main, más candidatos sacrifican el acorde a cambio de menos movimiento.
La distancia
Sección titulada «La distancia»La descripción de la herramienta dice que su emparejamiento es “good enough for retrieval ranking, not a formal Hungarian-optimal assignment” (suficiente para ordenar resultados de búsqueda, no una asignación formal óptima según el algoritmo húngaro) (líneas 180-185), y el comentario de documentación dice que un voicing con menos notas “pairs against its nearest neighbors” (se empareja con sus vecinos más cercanos) (líneas 312-319). El programa compara la distancia, en cada par que la herramienta mide para los diez prompts, con el movimiento mínimo entre todas las maneras de emparejar las notas. Cuando el número de notas difiere, el mínimo elige qué notas del voicing con más notas emparejar, y suma los mismos 3 semitonos por cada nota sin pareja:
== The tool's distance on every pair it weighs for the ten prompts, at the pin, against the least motionpairs of equal size 867: the distance is the least over every pairing 867pairs of unequal size 1383: the distance is the least over every choice of notes 593the largest gap, 39 semitones: 0-2-2-0-0-0 Em [40 47 52 55 59 64] → x-x-x-2-2-3 A7(shell) [57 61 67], distance 55, least 16prompts whose first pair would move less with the least over every choice of notes: 0 of 10- Entre voicings con el mismo número de notas, la distancia siempre es la mínima. Emparejar las notas ordenadas es imbatible cuando el coste es la suma de las diferencias: dos voces que se cruzan nunca mueven menos que las mismas dos sin cruzarse. Aquí la descripción subestima el emparejamiento.
- Cuando el número de notas difiere, la herramienta empareja las notas más graves, no las más cercanas, y 593 de 1383 pares reciben el mínimo. De Em
0-2-2-0-0-0al voicing shell de A7x-x-x-2-2-3, la herramienta empareja las tres notas más graves de Em con A, C♯ y G, a una octava o más por encima: 55 semitonos con la penalización. Emparejar las tres más agudas mueve 16. - En estos diez prompts, la distancia más pequeña no cambia. Con el mínimo en su lugar, ningún primer par movería menos, ni en el commit fijado ni en
main.
== The tool's distance on every pair it weighs for the ten prompts, on main, against the least motionpairs of equal size 890: the distance is the least over every pairing 890pairs of unequal size 1360: the distance is the least over every choice of notes 340the largest gap, 39 semitones: x-x-2-x-0-3 Em [52 59 67] → 0-0-2-x-2-3 A7/E [40 45 52 61 67], distance 47, least 8prompts whose first pair would move less with the least over every choice of notes: 0 of 10- En
main, 340 de 1360 pares con distinto número de notas reciben el mínimo, y la mayor diferencia vuelve a ser de 39 semitonos, de un Em de tres notas a un A7 de cinco.
El borrador de skill que la llamaría
Sección titulada «El borrador de skill que la llamaría»skills-dev/_pending-tools/voice-leading/DRAFT.md es una skill del chatbot escrita para llamar a ga_voice_leading_pair (líneas 1-25). Su nombre de archivo la mantiene fuera del chatbot: el cargador de skills solo lee archivos llamados SKILL.md, y el README deja el borrador en espera hasta que la herramienta exista entre las del propio chatbot (README líneas 1-17). El borrador describe una herramienta distinta de la de CompositionTools.cs:
- un argumento
optimize,"minimum_movement"o"common_tones", que la herramienta no recibe, yVoiceMovements,TotalSemitonesyCommonTonesen la respuesta, cuando la herramienta devuelve pares de voicings con una distancia (líneas 31-44); - “a Plücker-line / minimum-displacement solution” (una solución por líneas de Plücker / de desplazamiento mínimo) (línea 29), cuando la herramienta ordena notas MIDI;
- una referencia cruzada a
Common/GA.Business.ML/Agents/Mcp/HarmonyMcpTools.cs(línea 74), un archivo que GA no tiene ni en el commit fijado ni enmain; - un ejemplo de respuesta de Dm7 a G7 que anuncia un movimiento total de 2 semitonos y luego enumera cuatro movimientos de 0, 0, 2 y 1 (líneas 54-60). Suman 3, la distancia del primer par de la herramienta en
mainy el movimiento mínimo de la lección 18.
Hasta dónde llega el curso
Sección titulada «Hasta dónde llega el curso»- El corpus es el de la lección 3, 15.360 voicings en tres trastes, no el índice de producción. Entre más voicings, los candidatos y los pares podrían ser otros (por verificar).
- El programa llama directamente al método de la herramienta, no a través de un cliente MCP y del servidor de GA.
- Los veredictos leen clases de altura. El curso da por correcto un acorde de séptima sin quinta, duplique la nota que duplique, y no juzga ni la digitación ni el registro.
- Solo se comprueba en detalle el primer par. El programa cuenta los pares correctos entre los cinco, pero no mide cómo los reordena el fallo de la distancia.
Comunicado upstream
Sección titulada «Comunicado upstream»- Se comunicaron después de escribir esta lección, en la issue de GA #791: los voicings que la herramienta nunca comprueba, la distancia entre voicings con distinto número de notas, el orden de los diagramas y el borrador de skill en espera.
Ejercicios
Sección titulada «Ejercicios»- Con 50 candidatos, en el commit fijado, la herramienta responde a C → Am con
0-x-2-x-x-0a ambos lados, a 0 semitonos. ¿Qué toca ese voicing, y por qué una distancia de 0 no es aquí ninguna respuesta? - Calcula la distancia de la herramienta de Em
0-2-2-0-0-0, notas MIDI 40 47 52 55 59 64, al voicing shell de A7x-x-x-2-2-3, notas MIDI 57 61 67. ¿Qué emparejamiento mueve 16? - En el commit fijado, a los 15 candidatos de G7 solo les falta la quinta. ¿Qué notas tocan, y cómo llama la lección 16 a un voicing así?
- La herramienta recibe un instrumento, “guitar | bass | ukulele”. ¿Qué responde sobre el índice del curso para “bass”?
Soluciones
- Tres E: la cuerda E grave al aire, la cuerda D en el segundo traste y la cuerda E aguda al aire. E es una nota tanto de C como de A menor, así que el voicing toca una parte de cada uno y ninguno de los dos acordes. La consulta no nombra ningún acorde, y en el commit fijado este voicing está entre los 50 más cercanos a las dos consultas. Emparejado consigo mismo mueve 0, y nada en la herramienta comprueba lo que toca. En
main, el primer par de C → Am con 50 candidatos mueve 2 y toca los dos acordes. - Ordenadas, las tres notas del A7 se emparejan con las tres más graves de Em: 40 → 57 son 17, 47 → 61 son 14 y 52 → 67 son 15, es decir, 46, más 3 por cada una de las tres notas sin pareja: 55. Emparejadas con las tres más agudas, 55 → 57, 59 → 61 y 64 → 67 mueven 2 + 2 + 3 = 7, más 9: 16.
- G, B y F, la fundamental, la tercera y la séptima, nada más: el shell de la lección 16. En la tabla del primer par, los nombres que les da el índice empiezan por “G7(shell)”.
- El error “no voicings retrieved for one or both chords” (no se ha recuperado ningún voicing para uno de los acordes o para los dos) (líneas 214-221): el índice del curso solo contiene voicings de guitarra, así que el filtro no conserva ninguno. Con “guitar”, los primeros pares son los mismos que sin instrumento. Comprobado ejecutando la herramienta del commit fijado, fuera de la salida esperada del curso.
Puntos clave
Sección titulada «Puntos clave»- Ordenar por movimiento solo ordena el movimiento: una herramienta que empareja lo que devuelve una búsqueda tiene que comprobar lo que tocan los voicings, o fiarse de la búsqueda.
- Más candidatos pueden empeorar la respuesta cuando los vecinos más cercanos se alejan del acorde.
- Emparejar las notas ordenadas da el movimiento mínimo entre voicings con el mismo número de notas; cuando ese número difiere, elegir qué notas emparejar es la parte que necesita una búsqueda.
- El orden de la cadena de un diagrama es un contrato: un consumidor del índice lo corrigió, otro lo transmite tal cual.
- Una herramienta que puede llamar un agente no es una herramienta que pueda llamar el chatbot, y un borrador escrito para un registro puede describir una herramienta que no existe en ninguno de los dos.
Fuentes
Sección titulada «Fuentes»- GuitarAlchemist/ga en
a826864:GaMcpServer/Tools/CompositionTools.cs,GaMcpServer/Tools/VoicingSearchTool.cs,skills-dev/_pending-tools/voice-leading/DRAFT.md,skills-dev/_pending-tools/README.md. - GuitarAlchemist/ga en
f4f5b4a: la misma herramienta y los mismos borradores, la búsqueda de la lección 16,Common/GA.Business.ML/Agents/Skills/ChordVoicingsSkill.cs. - Los programas del curso:
code/ga-ai/GaAi/Lesson19.cs,code/ga-ai/GaMain/Program.cs,code/ga-ai/Shared/VoiceLeadingPairProbe.cs,code/ga-ai/Shared/SearchIndex.cs.