-
Notifications
You must be signed in to change notification settings - Fork 3
/
DocumentationAgent.ts
130 lines (92 loc) · 3.35 KB
/
DocumentationAgent.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import { writeFileSync, mkdirSync } from 'fs';
import { OpenAI } from 'langchain/llms/openai';
import { PromptTemplate } from 'langchain/prompts';
export class DocumentationAgent {
private model = new OpenAI({
modelName: 'gpt-4',
temperature: 0.0,
maxTokens: -1,
});
private promptTemplate = new PromptTemplate({
template: `You are a developer.
Your goal is to write the technical API documentation for an API route.
You will be given the route entrypoint and the code of all the user functions involved.
Entrypoint:
{entrypointCode}
User functions:
{userFunctions}
Follow this template:
filename: <actionName>-todos.md
## METHOD /api/path
<description>
### Request
The request should be a JSON object with the following properties:
- \`<property1>\` (<type>, <required|optional>): <description>
- \`<property2>\` (<type>, <required|optional>): <description>
Example with CURL:
\`\`\`bash
<curl command>
\`\`\`
### Response
<description of the result and response format>
Example:
\`\`\`json
<JSON response example>
\`\`\`
### Error
<description of the error response format>
<description of possible errors>
- \`<error1>\`: <description>
- \`<error2>\`: <description>
Example:
\`\`\`json
<example of error response format>
\`\`\``,
inputVariables: ['entrypointCode', 'userFunctions']
});
private debug: boolean = true;
private promptCount = 0;
private entrypointCode: string;
private userFunctions: string[];
private docDir = './examples/fastify/doc'
/**
* Contains the filepath (index 0) and the documentation content (index 1)
*/
public output: string[] = [];
constructor (entrypointCode: string, userFunctions: string[]) {
this.entrypointCode = entrypointCode;
this.userFunctions = userFunctions;
if (this.debug) {
mkdirSync('./prompts/', { recursive: true });
}
mkdirSync(this.docDir, { recursive: true });
}
async run () {
console.log('DocumentationAgent: start documenting entrypoint');
const prompt = await this.promptTemplate.format({
entrypointCode: this.entrypointCode,
userFunctions: this.userFunctions.join('\n\n')
});
const response = await this.model.call(prompt);
if (this.debug) {
writeFileSync(`./prompts/documentation-${this.promptCount++}.txt`, prompt + '\n==================================================================================\n' + response);
}
const { filename, documentation } = this.parseResponse(response);
const filepath = `${this.docDir}/${filename.endsWith('.md') ? filename : filename + '.md'}`;
console.log(`DocumentationAgent: write documentation to ${filepath}`);
writeFileSync(`${filepath}`, documentation);
this.output.push(`${filepath}`);
this.output.push(documentation);
}
private parseResponse(text: string) {
const filenamePattern = /filename:\s*(.*?)\.md\s*\n/;
const match = text.match(filenamePattern);
if (match) {
const filename = match[1].trim();
// Remove the line containing the filename
const documentation = text.replace(filenamePattern, '');
return { filename, documentation };
}
throw new Error('DocumentationAgent: could not parse response, filename not found')
}
}