Skip to content

Commit

Permalink
Provide instructions to AI (MediaWiki:Askai-default-instructions)
Browse files Browse the repository at this point in the history
TODO: user should be able to override default instructions.
  • Loading branch information
edwardspec committed Dec 7, 2024
1 parent 86487d8 commit 043d8c9
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 21 deletions.
1 change: 1 addition & 0 deletions extension.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"mobile"
],
"messages": [
"askai-source",
"askai-submit-failed"
],
"dependencies": [
Expand Down
2 changes: 2 additions & 0 deletions i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
"askai-debug-header": "Request was received by DebugService (see $wgAskAIServiceClass), not a real AI service.",
"askai-debug-instructions": "AI has received the following instructions:",
"askai-debug-prompt": "User has asked the following question:",
"askai-default-instructions": "You are a research assistant. The user will provide you with a list of quotes from various historical documents. Your task is to use only the information provided in your reply to the user. Do not use any external information in your reply. Do not hallucinate facts that are not provided in the text below. The format of the source documents will be (Source #) [Page title] followed by the document text. In your replies any time you reference a fact list the source number in parenthesis at the end of the sentence. The user has provided the following source material:",
"askai-desc": "Provides [[Special:AI]], which allows user to make AI queries about content of articles in this wiki.",
"askai-field-pages": "List of wiki pages (and paragraphs in them) to be analyzed by the AI:",
"askai-field-prompt": "Question to ask:",
"askai-field-response": "Response from the AI:",
"askai-openai-failed": "Failed to contact OpenAI: $1",
"askai-openai-not-configured": "Error: OpenAI not configured: apiKey, apiUrl or model are not set.",
"askai-source": "(Source #$1) [$2]",
"askai-submit-failed": "HTTP error when submitting the form: $1",
"askai-unknown-service": "Not configured: incorrect value of $wgAskAIServiceClass.",
"right-askai": "Send queries to Special:AI."
Expand Down
2 changes: 2 additions & 0 deletions i18n/qqq.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
"askai-debug-header": "Header shown before results of Special:AI if the response was provided by DebugService, not real AI.",
"askai-debug-instructions": "Label shown by DebugService before the instructions received by the AI.",
"askai-debug-prompt": "Label shown by DebugService before the question received by the AI.",
"askai-default-instructions": "Text of instructions that will be provided to AI service (before the prompt) if the user hasn't overriden them.",
"askai-desc": "{{desc|name=AskAI|url=https://www.mediawiki.org/wiki/Extension:AskAI}}",
"askai-field-pages": "Label of field for the list of pages/paragraphs.",
"askai-field-prompt": "Label of field for a question to the AI.:",
"askai-field-response": "Label of readonly field that will show the response from the AI.",
"askai-openai-failed": "Error message if HTTP request to OpenAI resulted in an error.",
"askai-openai-not-configured": "Error message if OpenAI API key, etc. are not configured.",
"askai-source": "Name of source document (will be supplied to AI as part of instructions). $1 - index of document (1, 2, 3, etc.), $2 - page name.",
"askai-submit-failed": "Error message if HTTP POST request to Special:AI resulted in an error.",
"askai-unknown-service": "Error message if failed to create an AI service.",
"right-askai": "{{doc-right|askai}}\nAllows to use Special:AI."
Expand Down
5 changes: 4 additions & 1 deletion includes/SpecialAI.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ public function onSubmit( array $data ) {
return Status::newFatal( 'askai-unknown-service' );
}

$response = $ai->query( $data['Prompt'], $data['Extract'] );
$response = $ai->query(
$data['Prompt'],
$this->msg( 'askai-default-instructions' )->plain() . "\n\n" . $data['Extract']
);

$this->getOutput()->disable();
echo Xml::element( 'div', [
Expand Down
36 changes: 16 additions & 20 deletions modules/ext.askai.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ $( function () {
// List of pages isn't useful to the AI (it doesn't know what to do with it),
// we need to retrieve the text of paragraphs (e.g. [[Some page#p6-8]])
// and send this text to AI as a part of instructions (not the user-chosen Prompt).
const promises = $pages.val().split( '\n' ).map( function ( pageName ) {
const promises = $pages.val().split( '\n' ).map( ( pageName ) => {
let title;
try {
title = new mw.Title( pageName );
Expand All @@ -26,10 +26,10 @@ $( function () {

if ( fragment && fragment.match( /^p[0-9\-,]+$/ ) ) {
// Anchor is the list of paragraphs, e.g. "p4", or "p6-8", or "p3,5,7".
fragment.slice( 1 ).split( ',' ).forEach( function ( pair ) {
fragment.slice( 1 ).split( ',' ).forEach( ( pair ) => {
const range = pair.split( '-' ),
start = range[ 0 ],
end = range.length > 1 ? range[ 1 ] : start;
start = parseInt( range[ 0 ] ),
end = parseInt( range.length > 1 ? range[ 1 ] : start );

for ( let idx = start; idx <= end; idx++ ) {
parNumbers.add( idx );
Expand All @@ -39,7 +39,7 @@ $( function () {

const $d = $.Deferred();

$.get( title.getUrl() ).done( function ( html ) {
$.get( title.getUrl() ).done( ( html ) => {
const $paragraphs = $( '<div>' ).append( html ).find( '.mw-parser-output > p' );

let extract;
Expand All @@ -48,7 +48,7 @@ $( function () {
extract = $paragraphs.toArray();
} else {
extract = [];
Array.from( parNumbers ).sort().forEach( function ( idx ) {
[ ...parNumbers ].sort( ( a, b ) => a - b ).forEach( ( idx ) => {
const p = $paragraphs[ idx ];
if ( p ) {
extract.push( p );
Expand All @@ -58,7 +58,7 @@ $( function () {

$d.resolve( {
title: title,
extract: extract.map( function ( p ) {
extract: extract.map( ( p ) => {
return p.innerText.trim();
} ).join( '\n\n' )
} );
Expand All @@ -68,17 +68,13 @@ $( function () {
} );

// Accumulate the results into 1 string.
return Promise.all( promises ).then( function ( pageResults ) {
return pageResults.map( function ( ret, idx ) {
let text = '(Source #' + ( idx + 1 ) + ') [' +
ret.title.getPrefixedText();

if ( ret.title.fragment ) {
text += '#' + ret.title.fragment;
}

text += ']\n\n' + ret.extract;
return text;
return Promise.all( promises ).then( ( pageResults ) => {
return pageResults.filter( ( x ) => x.extract ).map( ( ret, idx ) => {
const fragment = ret.title.fragment;
return mw.msg( 'askai-source',
idx + 1,
ret.title.getPrefixedText() + ( fragment ? '#' + fragment : '' )
) + '\n\n' + ret.extract;
} ).join( '\n\n' );
} );
}
Expand All @@ -88,11 +84,11 @@ $( function () {
wpExtract: extract,
wpPrompt: $prompt.val(),
wpEditToken: token
} ).fail( function ( xhr ) {
} ).fail( ( xhr ) => {
$response.val( mw.msg( 'askai-submit-failed',
xhr.statusText + ' (' + url + ')'
) );
} ).done( function ( ret ) {
} ).done( ( ret ) => {
$response.val( $( '<div>' ).append( ret ).find( '#mw-askai-response' ).text() );
} );
}
Expand Down

0 comments on commit 043d8c9

Please sign in to comment.