% MDS 03/03/02 % Simple dialogue % data structures % context: % % cx(Questions, % Proposals, % History, % KB) % % history: % % last(utterance, % analysis, % prior context) %%%%%%%%%%%%%%%%%%%%% % COMMENT OUT FOR SWI member(E, [E|_]). member(E, [_|L]) :- member(E,L). % SETUP questions(cx(Q,_,_,_), Q). proposals(cx(_,P,_,_), P). history(cx(_,_,H,_), H). shared(cx(_,_,_,K), K). initial_context( cx([], [], [], KB) ) :- initial_kb( KB ). talk :- initial_context(C), react(C). hear(U) :- write( 'A: ' ), read( U ). utter(U) :- write( 'B: ' ), write( U ), write( '.' ), nl. % RATIONALITY - a perception, deliberation, action cycle. react(C) :- shared(C, K), member(over, K), !. react(C) :- print_status(C), hear(U), interpretations(U, C, C2L), deliberate( U, C, C2L, G, CM ), force_to_debug(U, U2), act(G, CM, U2, C2), !, print_status(CM), utter(U2), react(C2). % INTERPRETATION means finding the least cost % matches against the context for the utterances % you find. interpretations( U, C, C2 ) :- findall(i(W,Cm), interpret(U, C, Cm, W), Ls), min(Ls, W), findall(Cm, member(i(W,Cm), Ls), C2). interpret( U, C, C2, W ) :- possible_utterance(U, P, _A, C, C2, W), solve(P, C). % DELIBERATION means incrementing the state of % the conversation to respond to your obligations % and goals as best you can. deliberate( _, _, [CL], G, Cm ) :- !, update(CL, G, Cm). deliberate( U, cx(Q, P, H, KB), [], [h(not_understood(U,H))], cx(Q, P, last(U, [], cx(Q, P, H, KB)), KB) ) :- !. deliberate( _, _, Is, _, _) :- write('Incomplete definition:\n'), write('No way to deal with interpretations\n'), write(Is), write('.\n'), !, fail. % ACTION means finding the least cost utterance % that achieves your goals unambiguously. act( G, C, U, C2 ) :- findall(i(W, (U, C2)), generate(G, C, U, C2, W), Ls), min(Ls, W), member(i(W, (U, C2)), Ls). act( G, C, _, _ ) :- write('Warning: No way to achieve goal\n '), print(G), write(' in context:\n'), print_error(C), !, fail. generate( G, C, U, C2, W ) :- possible_utterance(U, P, A, C, C2, W), solve(G, C2), solve(P, C), call(A), interpretations(U, C, [C2]). % COMPUTATIONAL RESOURCES % % SOLVE CONSTRAINTS ON THE CONTEXT solve([], _). solve([C | Cs], Cxt) :- match(C, Cxt), solve(Cs, Cxt). match( q(C), Cxt ) :- questions(Cxt, Qs), member(C, Qs). match( p(C), Cxt ) :- proposals(Cxt, Pls), member(Ps, Pls), member(C, Ps). match( h(C), Cxt ) :- history(Cxt, last(_,HL,HC)), (member(C, HL) ; match( h(C), HC)). match( s(C), Cxt ) :- shared(Cxt, Ss), member(C, Ss). match( x(C), _ ) :- call(C). match( \+(P), Cxt) :- \+ match(P, Cxt). % MIN min([], 0). min([ i(W,_) | R ], Z) :- min(W, R, Z). min(W, [], W). min(W, [i(W2,_)|R], Z) :- W > W2 -> min(W2, R, Z) ; min(W, R, Z). % DATA RESOURCES % % POSSIBLE UTTERANCES possible_utterance([i,dont,understand], [], true, cx(Q, P, last(U, I, cx(Q2, P2, H2, K2)), K), cx(Q2, P2, last([i,dont,understand], [not_understood(U, H2)], cx(Q, P, last(U, I, cx(Q2, P2, H2, K2)), K)), K2), 10). possible_utterance([ok], [], true, cx([Q1|Q], [[P1]|P], H, KB), cx(Q, P, last(ok, [ok:P1], cx([Q1|Q], [P1|P], H, KB)), [P1|KB]), 1) :- \+ \+ (Q1 = P1). possible_utterance([], [], true, C, C, 0). possible_utterance([goodbye], [], true, cx([over], [[over]], H, KB), cx([], [], last(goodbye, [], cx([over], [over], H, KB)), [over|KB]), 0). possible_utterance([goodbye], [], true, cx([], [], H, KB), cx([over], [[over]], last(goodbye, [], cx([], [], H, KB)), KB), 2). possible_utterance([lets,build,a,shelf], [x(building(A,K)), x(kind(K,shelf))], goal(A), cx(Q,P,H,KB), cx([goal(A)|Q],[[goal(A)] | P], last([lets,build,a,shelf], [build:A, shelf:K], cx(Q,P,H,KB)), KB), 3). possible_utterance([what,should,we,do], [s(goal(G))], needinfo(method(G,_)), cx(Q, P, H, KB), cx([method(G,_) | Q], [[]|P], last([what,should,we,do], [should:G], cx(Q, P, H, KB)), KB), 3). possible_utterance([use,pine,boards], [q(method(G,_)), x(using(A,K)), x(kind(K,boards)), \+ s(bad(method(G,A)))], method(G,A), cx(Q, [[]|P], H, KB), cx(Q, [[method(G,A)]|P], last([use,pine,boards], [use:A, boards:K], cx(Q,[[]|P],H,KB)), KB), 3). possible_utterance([use,plywood], [q(method(G,_)), x(using(A,K)), x(kind(K,plywood)), \+ s(bad(method(G,A)))], method(G,A), cx(Q, [[]|P], H, KB), cx(Q, [[method(G,A)]|P], last([use,plywood], [use:A, plywood:K], cx(Q,P,H,KB)), KB), 3). possible_utterance([that,wont,work], [], bad(method(G,A)), cx(Q, [[method(G,A)] | P], H, KB), cx(Q, [[]|P], last([that,wont,work], [that:A], cx(Q, [[method(G,A)] | P], H, KB)), [bad(method(G,A))|KB]), 3). possible_utterance([you,can,say,L], [], findall(U, generate([], cx(Q, P, H, KB), U, _, _), L), cx([whatnow(Hx,V) | Q], [[]|P], H, KB), cx(Q, P, last([you,can,say,L], [], cx([whatnow(Hx,V) | Q], [[]|P], H, KB)), [whatnow(Hx,L) | KB]), 0). possible_utterance([what,can,i,say], [], needinfo(whatnow(H,L)), cx(Q, P, H, KB), cx([whatnow(H,L) | Q], [[]|P], last([what,can,i,say], [], cx(Q,P,H,KB)), KB), 10). % UPDATES update( cx(Q,[[P]|Ps],H,K), [s(P)], cx(Q,[[P]|Ps],H,K) ) :- \+ bad(P). update( cx(Q,[[P]|Ps],H,K), [s(bad(P))], cx(Q,[[P]|Ps],H,K) ) :- bad(P). update( cx([Q|Qs], [[]|Ps], H, K), [p(P)], cx([Q|Qs], [[]|Ps], H, K) ) :- findall(P, P=Q, [P]). update( cx([Q|Qs], [[]|Ps], H, K), [s(P)], cx([Q|Qs], [[]|Ps], H, K) ) :- findall(P, P=Q, [P]). update( cx([], [], H, K), [p(goal(A))], cx([], [], H, K) ) :- goal(A), \+ member(goal(A),K). update( cx([], [], H, K), [q(A)], cx([], [], H, K) ) :- needinfo(A), \+ member(A,K). update( cx([], [], H, K), [], cx([], [], H, K) ). update( C, _, _ ) :- write('Error: no rule to update context\n'), print_error(C), !, fail. % INITIAL KNOWLEDGE BASE initial_kb([]). % STATIC UNCONTROVERSIAL SHARED BACKGROUND building(building_shelf_action, shelf_kind). using(building_shelf_with_pine_action, pine_board_kind). using(building_shelf_with_plywood_action, plywood_kind). kind(shelf_kind, shelf). kind(pine_board_kind, boards). kind(plywood_kind, plywood). method(building_shelf_action, building_shelf_with_pine_action). method(building_shelf_action, building_shelf_with_plywood_action). % SHUT UP ERROR MESSAGES. :- dynamic(goal/1). :- dynamic(needinfo/1). :- dynamic(bad/1). goal(building_shelf_action). needinfo(method(building_shelf_action,_)). bad(method(building_shelf_action,building_shelf_with_plywood_action)). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % DEBUGGABILITY :- dynamic(state_info/1). :- dynamic(error_info/1). :- dynamic(debug_response/2). error_info(last). error_info(questions). error_info(kb). state(Q) :- member(Q, [last,questions,history,kb]), !, assert(state_info(Q)). state(_) :- write('No such options: choose from\n'), write([last,questions,history,kb]). nostate(Q) :- member(Q, [last,questions,history,kb]), !, retractall(state_info(Q)). nostate(_) :- write('No such options: choose from\n'), write([last,questions,history,kb]). error(Q) :- member(Q, [last,questions,history,kb]), !, assert(error_info(Q)). error(_) :- write('No such options: choose from\n'), write([last,questions,history,kb]). noerror(Q) :- member(Q, [last,questions,history,kb]), !, retractall(error_info(Q)). noerror(_) :- write('No such options: choose from\n'), write([last,questions,history,kb]). print_question_status([], []) :- !, write('no (other) questions being considered.\n'). print_question_status([Q|Qs], [[]|Ps]) :- !, write('need to answer question '), print(Q), write('? ...then\n'), print_question_status(Qs, Ps). print_question_status([Q|Qs], [[P]|Ps]) :- !, write('considering '), print(P), write('\n as resolution of '), print(Q), write('? ...then\n'), print_question_status(Qs, Ps). print_question_status([Q|Qs], [P|Ps]) :- write('Data structure error: bad proposal '), print(P), write(' for question '), print(Q), write('. then\n'), print_question_status(Qs, Ps). print_question_status(Q, []) :- write('Data structure error: extra questions '), print(Q), write('.\n'). print_question_status([], P) :- write('Data structure error: extra proposals '), print(P), write('.\n'). print_history(last(U, R, cx(_, _, H2, _))) :- !, print_history(H2), print(U), write(' understood as '), print(R), write('.\n'). print_history([]) :- !. print_history(H) :- write('Data structure error: history '), print(H), write('\nshould have format last(U, R, Context).\n'). print_top_history(last(U, R, _)) :- !, write('Just understood utterance '), print(U), write('\n with reference '), print(R), write('.\n'). print_top_history([]) :- !. print_top_history(D) :- write('Data structure error: history '), print(D), write('\nshould take the form last(U, R, C)\n'). print_kb([]). print_kb([H|R]) :- print(H), write('.\n'), print_kb(R). print_status(cx(Q, P, H, KB)) :- (state_info(last) -> print_top_history(H) ; true), (state_info(questions) -> print_question_status(Q, P) ; true), (state_info(history) -> write('Discourse history:\n'), print_history(H) ; true), (state_info(kb) -> write('Knowledge base:\n'), print_kb(KB) ; true). print_error(cx(Q, P, H, KB)) :- (error_info(last) -> print_top_history(H) ; true), (error_info(questions) -> print_question_status(Q, P) ; true), (error_info(history) -> write('Discourse history:\n'), print_history(H) ; true), (error_info(kb) -> write('Knowledge base:\n'), print_kb(KB) ; true). force_to_debug(U, U2) :- debug_response(U, U2), !. force_to_debug(_, _).