11import { getUserConfig } from '../../config/index.mjs'
2- import { getChatSystemPromptBase , pushRecord , setAbortController } from './shared.mjs'
3- import { getConversationPairs } from '../../utils/get-conversation-pairs.mjs'
2+ import { pushRecord , setAbortController } from './shared.mjs'
43import { fetchSSE } from '../../utils/fetch-sse.mjs'
54import { isEmpty } from 'lodash-es'
65
@@ -13,75 +12,69 @@ export async function generateAnswersWithClaudeApi(port, question, session) {
1312 const { controller, messageListener, disconnectListener } = setAbortController ( port )
1413 const config = await getUserConfig ( )
1514
16- const prompt = getConversationPairs (
17- session . conversationRecords . slice ( - config . maxConversationContextLength ) ,
18- false ,
19- )
20- prompt . unshift ( { role : 'Assistant' , content : await getChatSystemPromptBase ( ) } )
21- prompt . push ( { role : 'Human' , content : question } )
15+ let prompt = ''
16+ for ( const record of session . conversationRecords . slice ( - config . maxConversationContextLength ) ) {
17+ prompt += '\n\nHuman: ' + record . question + '\n\nAssistant: ' + record . answer
18+ }
19+ prompt += `\n\nHuman: ${ question } \n\nAssistant:`
2220
2321 let answer = ''
24- await fetchSSE (
25- `https://api.anthropic.com/v1/complete` ,
26- {
27- method : 'POST' ,
28- signal : controller . signal ,
29- headers : {
30- 'Content-Type' : 'application/json' ,
31- 'accept' : 'application/json' ,
32- 'anthropic-version' : '2023-06-01' ,
33- 'x-api-key' : config . claudeApiKey ,
34- } ,
35- body : JSON . stringify ( {
36- model : "claude-2" ,
37- prompt : "\n\nHuman: " + question + "\n\nAssistant:" ,
38- stream : true ,
39- max_tokens_to_sample : config . maxResponseTokenLength ,
40- temperature : config . temperature ,
41- } ) ,
42- onMessage ( message ) {
43- console . debug ( 'sse message' , message ) ;
44-
45- let data ;
46- try {
47- data = JSON . parse ( message ) ;
48- } catch ( error ) {
49- console . debug ( 'json error' , error ) ;
50- return ;
51- }
52-
53- // The Claude v2 API may send metadata fields, handle them here
54- if ( data . conversationId ) session . conversationId = data . conversationId ;
55- if ( data . parentMessageId ) session . parentMessageId = data . parentMessageId ;
56-
57- // In Claude's case, the "completion" key holds the text
58- if ( data . completion ) {
59- answer += data . completion ;
60- port . postMessage ( { answer : answer , done : false , session : null } ) ;
61- }
62-
63- // Check if the message indicates that Claude is done
64- if ( data . stop_reason === 'stop_sequence' ) {
65- pushRecord ( session , question , answer ) ;
66- console . debug ( 'conversation history' , { content : session . conversationRecords } ) ;
67- port . postMessage ( { answer : null , done : true , session : session } ) ;
68- }
69- } ,
70- async onStart ( ) { } ,
71- async onEnd ( ) {
72- port . postMessage ( { done : true } )
73- port . onMessage . removeListener ( messageListener )
74- port . onDisconnect . removeListener ( disconnectListener )
75- } ,
76- async onError ( resp ) {
77- port . onMessage . removeListener ( messageListener )
78- port . onDisconnect . removeListener ( disconnectListener )
79- if ( resp instanceof Error ) throw resp
80- const error = await resp . json ( ) . catch ( ( ) => ( { } ) )
81- throw new Error (
82- ! isEmpty ( error ) ? JSON . stringify ( error ) : `${ resp . status } ${ resp . statusText } ` ,
83- )
84- } ,
22+ await fetchSSE ( `https://api.anthropic.com/v1/complete` , {
23+ method : 'POST' ,
24+ signal : controller . signal ,
25+ headers : {
26+ 'Content-Type' : 'application/json' ,
27+ accept : 'application/json' ,
28+ 'anthropic-version' : '2023-06-01' ,
29+ 'x-api-key' : config . claudeApiKey ,
8530 } ,
86- )
31+ body : JSON . stringify ( {
32+ model : 'claude-2' ,
33+ prompt : prompt ,
34+ stream : true ,
35+ max_tokens_to_sample : config . maxResponseTokenLength ,
36+ temperature : config . temperature ,
37+ } ) ,
38+ onMessage ( message ) {
39+ console . debug ( 'sse message' , message )
40+
41+ let data
42+ try {
43+ data = JSON . parse ( message )
44+ } catch ( error ) {
45+ console . debug ( 'json error' , error )
46+ return
47+ }
48+
49+ // The Claude v2 API may send metadata fields, handle them here
50+ if ( data . conversationId ) session . conversationId = data . conversationId
51+ if ( data . parentMessageId ) session . parentMessageId = data . parentMessageId
52+
53+ // In Claude's case, the "completion" key holds the text
54+ if ( data . completion ) {
55+ answer += data . completion
56+ port . postMessage ( { answer : answer , done : false , session : null } )
57+ }
58+
59+ // Check if the message indicates that Claude is done
60+ if ( data . stop_reason === 'stop_sequence' ) {
61+ pushRecord ( session , question , answer )
62+ console . debug ( 'conversation history' , { content : session . conversationRecords } )
63+ port . postMessage ( { answer : null , done : true , session : session } )
64+ }
65+ } ,
66+ async onStart ( ) { } ,
67+ async onEnd ( ) {
68+ port . postMessage ( { done : true } )
69+ port . onMessage . removeListener ( messageListener )
70+ port . onDisconnect . removeListener ( disconnectListener )
71+ } ,
72+ async onError ( resp ) {
73+ port . onMessage . removeListener ( messageListener )
74+ port . onDisconnect . removeListener ( disconnectListener )
75+ if ( resp instanceof Error ) throw resp
76+ const error = await resp . json ( ) . catch ( ( ) => ( { } ) )
77+ throw new Error ( ! isEmpty ( error ) ? JSON . stringify ( error ) : `${ resp . status } ${ resp . statusText } ` )
78+ } ,
79+ } )
8780}
0 commit comments