Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Conexión con bases de datos (https://www.clubdelphi.com/foros/forumdisplay.php?f=2)
-   -   Resumen (https://www.clubdelphi.com/foros/showthread.php?t=60475)

Abuelo7 24-09-2008 13:24:25

Mas problemas con Tablas
 
Hola amigos.

Como aclaración os diré lo que intento hacer.
Un programa de IA de conversación que esta programado en Clipper, estoy pasándolo a Delphi.
No tengo el fuente del programa, pero sí tengo las BD y Tablas que utiliza.
Lo que son frases exactas con sus respuestas ya lo he solucionado. Trabajo con 4 tablas, 2 de preguntas y 2 de respuestas.

Ahora bien, hay algo que no sé como solucionar. Es lo siguiente:

Hay 1 Tabla con palabras-clave y un código.
Otra Tabla con código y respuesta.

Ejemplo.- Si le digo 'estoy enfermo', busca en frases exactas y no la encuentra. Entonces descompone la frase en palabras y encuentra en 1 Tabla la palabra 'estoy' con código 8 en este caso. Busca en la Tabla de respuestas el código 8 y encuentra entre varias respuestas '¿cuanto tiempo has estado *'

Aquí es donde tengo los problemas.
1.-Aceptar la palabra 'enfermo' en la entrada de frase aunque no la tenga en ninguna Tabla.

2.-Parece ser que el asterisco a continuación de la frase de respuesta es para colocar la palabra que no ha encontrado en la frase de entrada, en este caso 'enfermo'. Por ello contesta 'cuanto tiempo has estado enfermo'.

Como puedo hacerlo para solventar estos 2 puntos?

Gracias y perdonar el rollo.

Saludos
Manuel

coso 24-09-2008 13:34:15

hola, lo que podrias hacer es que si no encuentra dicha palabra, insertarla automaticamente, y luego proceder como estabas haciendo. Lo malo sera si se tiene que asociar algo mas a la palabra en cuestion (que seria lo mas probable) porque desde la frase de entrada poca informacion más puedes sacar. saludos.

Caro 24-09-2008 14:00:08

Hola Manuel

Cita:

Empezado por Abuelo7 (Mensaje 315932)
Hay 1 Tabla con palabras-clave y un código.
Otra Tabla con código y respuesta.

Ejemplo.- Si le digo 'estoy enfermo', busca en frases exactas y no la encuentra. Entonces descompone la frase en palabras y encuentra en 1 Tabla la palabra 'estoy' con código 8 en este caso. Busca en la Tabla de respuestas el código 8 y encuentra entre varias respuestas '¿cuanto tiempo has estado *'

Según el otro hilo, esta parte ya esta, verdad. Ahora para esta parte

Cita:

Empezado por Abuelo7 (Mensaje 315932)
Aquí es donde tengo los problemas.
1.-Aceptar la palabra 'enfermo' en la entrada de frase aunque no la tenga en ninguna Tabla.

2.-Parece ser que el asterisco a continuación de la frase de respuesta es para colocar la palabra que no ha encontrado en la frase de entrada, en este caso 'enfermo'. Por ello contesta 'cuanto tiempo has estado enfermo'.

Para separar en palabras supongo que sigues usando el StringList, te pongo un ejemplo, suponiendo que la primera palabra sea la palabra clave.

Código Delphi [-]
var
 sl : TStringList;
 Cadena, respuesta, pregunta : String;
begin
 sl := TStringList.Create;
 sl.Delimiter := #32;
 sl.DelimitedText := Edit1.Text; // Edit1, es donde se ha introducido la pregunta
 //La respuesta que obtines de tabla si encuentra
 respuesta := 'cuanto tiempo has estado *';

 pregunta := sl[0]; //Obtenemos la primera palabra
 sl.Delete(0); //Si esta como palabra clave entonces borramos de nuestro StringList
 
 //Obtenemos todo lo demas que no sea pregunta
 Cadena := '';
 for i:=0 to sl.Count-1 do
  Cadena := Cadena+sl[i];  
 
 // y lo reemplazamos donde encuentra el *
 respuesta := StringReplace(respuesta,'*',Cadena,[rfIgnorecase,rfReplaceAll]);
 showmessage(respuesta);
end;

pero tienes que ver todos los casos que se pueden dar, aquí estamos suponiendo que la primera palabra es nuestra palabra clave que esta en la Tabla1, pero que pasa si la palabra "estoy" no esta al principio y esta en otro lugar o si encuentra mas de una palabra clave :confused:.

Saluditos

Abuelo7 24-09-2008 19:23:06

Hola amiga Caro.
He probado el código que me has pasado y funciona perfectamente.

Ahora bien, tengo dudas de como insertarlo en el código que tengo.

Te lo paso.

Código Delphi [-]
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
  var
        sl : TStringList;
        Cadena, respuesta, pregunta : String;
         i : Integer;

begin
  // si no es la tecla que buscamos, salimos y listo ;-)
  if Key <> #13 then Exit;


  // abrimos tablas
  Table1.Open;
  Table2.Open;
  Table3.Open;
  Table4.Open;


  // ponemos el código en un bloque try..finally para asegurarnos de que pase lo que pase éstas se cierren
  try
    // si localizamos lo buscado en Tabla1 y su resultado en Tabla2, lo añadimos al Memo1
    // Este if funciona debido a que SOLO se evaluará la segunda condición si la primera
    // se cumple (por eso de ser un AND) y si la primera se cumple, ya estamos posicionados
    // en el registro buscado (o al menos eso dice la teoría, no lo he probado xD)
      Memo1.Lines.Add(Edit1.Text);

    if (Table1.Locate('palabra', Edit1.Text, [loCaseInsensitive])) and
       (Table2.Locate('NUMERO', Table1.fieldByName('NUMERO').AsString, [loCaseInsensitive])) then

        Memo1.Lines.Add(Table2.fieldByName('RESPUESTA').AsString)
    else
    If (Table3.Locate('palabra',Edit1.Text,[loCaseInsensitive])) and
       (Table4.Locate('NUMERO',Table3.fieldByName('NUMERO').AsString,[loCaseInsensitive])) then
       Memo1.Lines.Add(Table4.fieldByName('RESPUESTA').AsString)
    else
    if Edit1.Text='adios' then
    Memo1.Lines.Add('Hasta la próxima')
    else
        Memo1.Lines.Add('No entiendo la frase.Podría explicármelo de otra forma?');
  finally
    Table1.Close;
    Table2.Close;
    Table3.Close;
    Table4.Close;
    Edit1.Text :='';
  end;
end;


end.

Gracias
Saludos

Caro 24-09-2008 19:44:56

Hola de nuevo Manuel, en tu codigo quedaría mas o menos así.

Código Delphi [-]
var
 sl : TStringList;
 Cadena, respuesta, pregunta : String;
 i : Integer;
begin
 // si no es la tecla que buscamos, salimos y listo ;-)
 if Key <> #13 then Exit;
 // abrimos tablas
 Table1.Open;
 Table2.Open;
 Table3.Open;
 Table4.Open;
 
 sl := TStringList.Create;
 sl.Delimiter := #32;
 sl.DelimitedText := Edit1.Text;
 pregunta := sl[0];
 
 try
  Memo1.Lines.Add(Edit1.Text);
  if (Table1.Locate('palabra', pregunta, [loCaseInsensitive])) and
     (Table2.Locate('NUMERO', Table1.fieldByName('NUMERO').AsString, [loCaseInsensitive])) then
   begin
    sl.Delete(0);
    //Suponiendo que tu campo de la tabla2 se llma respuesta
    respuesta := Table2.fieldByName('RESPUESTA').AsString;
 
    Cadena := '';
    for i:=0 to sl.Count-1 do
     Cadena := Cadena+sl[i];
    respuesta := StringReplace(respuesta,'*',Cadena,[rfIgnorecase,rfReplaceAll]);
    showmessage(respuesta);
   end
  else
   If (Table3.Locate('palabra',Edit1.Text,[loCaseInsensitive])) and
    Memo1.Lines.Add('Hasta la próxima')
   else
    Memo1.Lines.Add('No entiendo la frase.Podría explicármelo de otra forma?');
 finally
  Table1.Close;
  Table2.Close;
  Table3.Close;
  Table4.Close;
 end;
end;

Conste que solo es si la primera palabra es la que se esta buscando en la tabla de preguntas, debes analizar para todos los casos que dije, pero como ejemplo y para que veas como funciona te servira.

Saluditos

Abuelo7 24-09-2008 20:02:56

Hola Caro.
Muchas gracias.

Probaré como me dices.

Como podrás observar en mi código, lo que hace es buscar frases exactas en la tabla1 y en la tabla3 y las respuestas están en tabla2 y tabla4, respectivamente.

Mi idea es si no encuentra la frase exacta, separar las palabras de la frase y buscar dichas palabras una por una, buscando la palabra clave.

Saludos

Caro 24-09-2008 20:36:37

Cita:

Empezado por Abuelo7 (Mensaje 316060)
Mi idea es si no encuentra la frase exacta, separar las palabras de la frase y buscar dichas palabras una por una, buscando la palabra clave.

Para esta parte podrías hacer algo así:

Código Delphi [-]
 .......................
 sl := TStringList.Create;
 sl.Delimiter := #32;
 sl.DelimitedText := Edit1.Text;
 //Añadimos el contenido completo del Edit en nuestra primera posición
 // del StringList para que sea el primero en compararse
 sl.Insert(0,Edit1.Text);

 try
  Memo1.Lines.Add(Edit1.Text);
  indice := -1;
  Recorremos hasta que encuentre
  Repeat
   Inc(Indice);   
  Until Not (Table1.Locate('palabra', sl[Indice], [loCaseInsensitive])) and (Indice//

   if Indice>=0 then //si fuera -1 es porque no ha encontrado
   begin
    if (Table2.Locate('NUMERO', Table1.fieldByName('NUMERO').AsString, [loCaseInsensitive])) then
     begin
      sl.Delete(Indice); //borramos la palabra clave de sl
      respuesta := Table2.fieldByName('RESPUESTA').AsString;
      
      Cadena := '';
      for i:=0 to sl.Count-1 do
       Cadena := Cadena+sl[i];
      respuesta := StringReplace(respuesta,'*',Cadena,[rfIgnorecase,rfReplaceAll]);
      showmessage(respuesta);
     end;
   end;

Saluditos

Abuelo7 24-09-2008 21:36:11

Hola Caro.
Gracias, mañana lo pruebo y te digo como me vá.

Una cosa.

Si a tí o a alguien le interesa el programa que tengo hecho en Clipper, os lo puedo pasar para que veais. Es estupendo como funciona.

Como no sé si aquí se pueden pasar links, y lo tengo colgado en rapidshare, si interesa mandarme un privado y os paso el link.

Gracias una vez más

Saludos.

Manuel

Caro 25-09-2008 03:58:56

Cita:

Empezado por Abuelo7 (Mensaje 316110)
Si a tí o a alguien le interesa el programa que tengo hecho en Clipper, os lo puedo pasar para que veais. Es estupendo como funciona.

Como no sé si aquí se pueden pasar links, y lo tengo colgado en rapidshare, si interesa mandarme un privado y os paso el link.

Si quieres puedes poner el link para descargar en este mismo hilo Manuel ;).

Saluditos

Abuelo7 25-09-2008 10:36:56

Hola Caro.

Te adjunto el link al programa Zebal.

Verás que están las tablas que utiliza. Tengo que depurarlas porque hay algunas frases y respuestas que son un poco bestias y fuera de lugar.

Ya me comentaras que te parece.

http://rapidshare.com/files/133851694/Zebal3.rar

Saludos

Manuel

Abuelo7 25-09-2008 11:50:43

Hola amiga Caro.

Podrías revisarme este código. Me dá una respuesta que no concuerda y además me repite en el Memo el Edit1 al final de la respuesta.
Código Delphi [-]
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
var
        sl : TStringList;
        Cadena, respuesta, pregunta : String;
        i : Integer;
         Indice : Integer;
begin
        If Key <> #13 then Exit;
        Table1.Open;
        Table2.Open;
        sl := TStringList.Create;
        sl.Delimiter := #32;
        sl.DelimitedText := Edit1.Text;
        sl.Insert(0,Edit1.Text);
try
        Memo1.Lines.Add(Edit1.Text);
        Indice := -1;
        Repeat
                Inc(Indice);
        Until Not (Table1.Locate('PALABRA', sl[Indice],[loCaseInsensitive]));
        if Indice>=0 then
begin
        if (Table2.Locate('NUMERO', Table1.fieldByName('NUMERO').AsString, [loCaseInsensitive])) then
begin
        sl.Delete(Indice);
        respuesta := Table2.fieldByName('RESPUESTA').AsString;
        Cadena := '';
        for i:=0 to sl.Count-1 do
        Cadena := Cadena+sl[i];
        respuesta :=StringReplace(respuesta,'*',Cadena,[rfIgnorecase,rfReplaceAll]);
        Memo1.Lines.Add(respuesta);
        end;

        Table1.Close;
        Table2.Close;
        Edit1.Text := '';
        end;
        finally
        end;

end;


end.

Gracias.

Caro 25-09-2008 15:37:43

Hola de nuevo Manuel, ayer lo hice a la rapida el codigo y no me he dado cuenta que no funcionaba bien, mejor utiliza un for así si hubiera mas de una palabra clave despues lo vas acumulando.

Código Delphi [-]
try
   Memo1.Lines.Add(Edit1.Text);
   Indice := -1;
   For i := 0 to sl.Count-1 do
    begin
      if (Table1.Locate('PALABRA', sl[i],[loCaseInsensitive]) then
        begin
          Indice := i;
          break;
        end;
    end;//for

    if Indice>=0 then
     begin
        if (Table2.Locate('NUMERO', Table1.fieldByName('NUMERO').AsString, [loCaseInsensitive])) then
begin
        sl.Delete(Indice);
        if Indice<>0 then //Si no fuera el texto completo
         sl.Delete(0);

        respuesta := Table2.fieldByName('RESPUESTA').AsString;
        Cadena := '';
        for i:=0 to sl.Count-1 do
        Cadena := Cadena+sl[i];
        respuesta :=StringReplace(respuesta,'*',Cadena,[rfIgnorecase,rfReplaceAll]);
        Memo1.Lines.Add(respuesta);
        end;

        Table1.Close;
        Table2.Close;
        Edit1.Text := '';
        end;
        finally
        end;

Saluditos

Abuelo7 25-09-2008 18:28:26

Hola Caro.

Has bajado el programa Zebal ?

Que Tal?

Saludos

Manuel

Abuelo7 25-09-2008 20:02:56

Hola otra vez Caro.

He estado probando el último código pero hay algo que no marcha.No localizo donde está el fallo.

Cuando me dá la respuesta, me aparece la respuesta+elEdit1+la última palabra.

Frase ejemplo:

estoy mal respuesta: cuanto hace que estas estoymalmal.

Código Delphi [-]
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
var
        sl : TStringList;
        Cadena, respuesta, pregunta : String;
        i : Integer;
         Indice : Integer;
begin
        If Key <> #13 then Exit;
        Table1.Open;
        Table2.Open;
        sl := TStringList.Create;
        sl.Delimiter := #32;
        sl.DelimitedText := Edit1.Text;
        sl.Insert(1,Edit1.Text);
try
        Memo1.Lines.Add(Edit1.Text);
        Indice := -1;
        for i := 0 to sl.Count-1 do
begin
        If (Table1.Locate('PALABRA', sl[i],[loCaseInsensitive]))then
begin
        Indice := i;
        break;
        end;
        end;
        if Indice>=0 then
begin
        if (Table2.Locate('NUMERO',Table1.fieldByName('NUMERO').AsString, [loCaseInsensitive])) then
begin
        sl.Delete(Indice);
        if Indice<>0 then
        sl.Delete(0);
        respuesta := Table2.fieldByName('RESPUESTA').AsString;
        Cadena := '';
        for i:=0 to sl.Count-1 do
        Cadena := Cadena+sl[i];
        respuesta :=StringReplace(respuesta ,'*',Cadena,[rfReplaceAll,rfIgnoreCase]);
        Memo1.Lines.Add(respuesta);
        end;

        Table1.Close;
        Table2.Close;
        Edit1.Text := '';
        end;
        finally
        end;

end;


end.

Saludos

Caro 26-09-2008 04:42:41

Cita:

Empezado por Abuelo7 (Mensaje 316307)
Has bajado el programa Zebal ?

Que Tal?

Hola Manuel si lo he bajado gracias, pero no lo he podido ver, yo creo el fin de semana tratare de verlo.

Sobre la parte que no te funciona, en el primer codigo recorriendo las palabras para hacer la búsqueda, no se estaba controlando de eliminar la frase completa ya que con el sl.Insert(0, Edit1.Text) lo insertabamos al principio para que haga la busqueda primero por la frase completa y luego por las palabras separadas, al encontrar en un indice que no sea el 0 osea que no sea la frase completa teníamos que eliminar lo que se tenía en el indice 0 para luego pasar recien lo que quedaba a la respuesta, es por eso que he aumentado

Código Delphi [-]
    .....................
    //Eliminamos la palabra que se encuentra en Indice osea la que ha encontrado en la busqueda
    sl.Delete(Indice); 
 
   //Si el Indice no fuera el 0 osea la frase completa,
   // eliminamos esa frase completa, para que no nos repita en la respuesta
    if Indice<>0 then
      sl.Delete(0);
 
    respuesta := Table2.fieldByName('RESPUESTA').AsString;
   ....................


En tu codigo en la parte del Insert le has puesto que se inserte en la posicion 1, cambialo por 0, ya que estamos preguntando por esa posición 0 si fuera frase completa.

Código Delphi [-]
  //Con esto insertamos en la primera posición de nuestra lista
 sl.Insert(0,Edit1.Text);

Saluditos

Abuelo7 28-09-2008 10:19:32

Hola Caro.

Después de las últimas modificaciones he intentado ampliarlo a 4 Tablas.
Esto es la 1 con respuestas en la 2 y la 3 con respuestas en la 4.
En principio no me funciona, debe haber algo que se me escapa.
Asimismo he encontrado un fallo en la búsqueda de frases completas.
el ejemplo que me ha salio es el siguiente:
Hay una frase que es 'quien eres' que tiene una respuesta.
Hay otra frase que es 'quien eres tu' que tiene una respuesta.
Cuando introduces esta última frase te dá la respuesta de la primera.
Parece ser que no busca las 3 palabras de la frase, lo que hace es que cuando las 2 primeras palabras tienen una respuesta, no busca mas.

Te paso el código con las 4 Tablas para que le des un vistazo.

No sé como agradecerte lo que estás haciendo por mi proyecto.
Ten por seguro que cuando esté finalizado, si vivo para contarlo, voy a hacer una mención especial a tí y lógicamente a todos los que habéis tenido la paciencia de atenderme y ayudarme.

Código Delphi [-]

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
  var
        sl : TStringList;
        Cadena, respuesta, pregunta : String;
         i : Integer;
         Indice : Integer;

begin
  // si no es la tecla que buscamos, salimos y listo ;-)
  if Key <> #13 then Exit;


  // abrimos tablas
  Table1.Open;
  Table2.Open;
  Table3.Open;
  Table4.Open;

  sl :=TStringList.Create;
  sl.Delimiter := #32;
  sl.DelimitedText := Edit1.Text;
  sl.Insert(0,Edit1.Text);


  // ponemos el código en un bloque try..finally para asegurarnos de que pase lo que pase éstas se cierren
  try
    // si localizamos lo buscado en Tabla1 y su resultado en Tabla2, lo añadimos al Memo1
    // Este if funciona debido a que SOLO se evaluará la segunda condición si la primera
    // se cumple (por eso de ser un AND) y si la primera se cumple, ya estamos posicionados
    // en el registro buscado (o al menos eso dice la teoría, no lo he probado xD)
      Memo1.Lines.Add(Edit1.Text);
      Indice := -1;
      for i := 0 to sl.Count-1 do
begin
    if (Table1.Locate('palabra', sl[i], [loCaseInsensitive])) then
begin
        Indice := i;
        break;
        end;
        end;
        If Indice>=0 then
begin
       if (Table2.Locate('NUMERO', Table1.fieldByName('NUMERO').AsString, [loCaseInsensitive])) then
begin
        sl.Delete(Indice);
        if Indice<>0 then
        sl.Delete(0);

        respuesta :=Table2.fieldByName('RESPUESTA').AsString;
        Cadena :='';
        for i := 0 to sl.Count-1 do
        Cadena := Cadena+sl[i];
        respuesta :=StringReplace(respuesta,'*',Cadena,[rfReplaceAll,rfIgnoreCase]);
        Memo1.Lines.Add(respuesta);
        end;
 begin

    If (Table3.Locate('palabra',sl[i],[loCaseInsensitive])) then
        begin
        Indice := i;
        break;
        end;
        end;
        If Indice>=0 then
    begin
       if (Table4.Locate('NUMERO',Table3.fieldByName('NUMERO').AsString,[loCaseInsensitive])) then
       begin
        sl.Delete(Indice);
        if Indice<>0 then
        sl.Delete(0);
        respuesta :=Table4.fieldByName('RESPUESTA').AsString;
        Cadena :='';
        for i := 0 to sl.Count-1 do
        Cadena := Cadena+sl[i];
        respuesta :=StringReplace(respuesta,'*',Cadena,[rfReplaceAll,rfIgnoreCase]);
        Memo1.Lines.Add(respuesta);
        end
       Memo1.Lines.Add(Table4.fieldByName('RESPUESTA').AsString)
    end
    else
    if Edit1.Text='adios' then
    Memo1.Lines.Add('Hasta la próxima')
    else
        Memo1.Lines.Add('No entiendo la frase.Podría explicármelo de otra forma?');
  end;

    Table1.Close;
    Table2.Close;
    Table3.Close;
    Table4.Close;
    Edit1.Text :='';
  end;
  finally
end;

 end;
end.

Caro 30-09-2008 16:17:30

Cita:

Empezado por Abuelo7 (Mensaje 316815)
Después de las últimas modificaciones he intentado ampliarlo a 4 Tablas.
Esto es la 1 con respuestas en la 2 y la 3 con respuestas en la 4.

No te endiendo muy bien, porque buscas en las demas tablas no sería mejor que guardaras todas las respuestas en una sola tabla y todas las preguntas en otra tabla, si es necesario mas tablas, ¿cual es la estructura de tus tablas y como deseas hacer la búsqueda?

Cita:

Empezado por Abuelo7 (Mensaje 316815)
Asimismo he encontrado un fallo en la búsqueda de frases completas.
el ejemplo que me ha salio es el siguiente:
Hay una frase que es 'quien eres' que tiene una respuesta.
Hay otra frase que es 'quien eres tu' que tiene una respuesta.
Cuando introduces esta última frase te dá la respuesta de la primera.
Parece ser que no busca las 3 palabras de la frase, lo que hace es que cuando las 2 primeras palabras tienen una respuesta, no busca mas.

De la forma en que te he puesto debería hacer la busqueda primero por "quien eres tu" y luego por "quien" despues por eres "eres" y despues por "tu", ese fallo te sale desde lo ultimo que te pase o con tus cambios.

Saluditos

Abuelo7 30-09-2008 18:15:41

Hola Caro.
El motivo de utilizar 4 tablas es que he aprovechado las que lleva el Zebal.
Los fallos se me producen después de los cambios que he hecho para utilizar las 4 Tablas.
Respecto al fallo hay lo siguiente:
En la tabla 1 está la pregunta 'quien eres' y la respuesta en la 2.
En la tabla 3 está la pregunta 'quien eres tu' y la respuesta en la 4.

Yo creía que primero buscaba la frase completa 'quien eres tu' y después 'quien eres' y después 'quien'.

No obstante creo que yo, al intentar adaptar las 4 tablas ha sido cuando lo he estropeado.

Perdona y gracias

Saludos.

Manuel

Abuelo7 03-10-2008 11:27:45

Resumen
 
1 Archivos Adjunto(s)
Amiga Caro.

Te adjunto el Resumen de que te hablé.

Saludos

Manuel


La franja horaria es GMT +2. Ahora son las 15:19:35.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi