forked from defog-ai/sql-eval
-
Notifications
You must be signed in to change notification settings - Fork 0
/
anthropic.py
137 lines (124 loc) · 4.43 KB
/
anthropic.py
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
131
132
133
134
135
136
137
import time
from typing import Dict, List
from func_timeout import FunctionTimedOut, func_timeout
from anthropic import Anthropic
import os
from query_generators.query_generator import QueryGenerator
from utils.pruning import prune_metadata_str
anthropic = Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))
class AnthropicQueryGenerator(QueryGenerator):
"""
Query generator that uses Anthropic's models
Models available: claude-2, claude-instant-1
"""
def __init__(
self,
db_creds: Dict[str, str],
db_name: str,
model: str,
prompt_file: str,
timeout: int,
use_public_data: bool,
verbose: bool,
**kwargs,
):
self.db_creds = db_creds
self.db_name = db_name
self.model = model
self.prompt_file = prompt_file
self.use_public_data = use_public_data
self.timeout = timeout
self.verbose = verbose
def get_completion(
self,
model,
prompt,
max_tokens=600,
temperature=0,
stop=["```", ";"],
logit_bias={},
):
"""Get Anthropic chat completion for a given prompt and model"""
generated_text = ""
try:
completion = anthropic.completions.create(
model=model,
prompt=prompt,
max_tokens_to_sample=max_tokens,
temperature=temperature,
stop_sequences=stop,
)
generated_text = completion.completion
except Exception as e:
if self.verbose:
print(type(e), e)
return generated_text
@staticmethod
def count_tokens(prompt: str = "") -> int:
"""
This function counts the number of tokens used in a prompt
model: the model used to generate the prompt. can be one of the following: gpt-3.5-turbo-0613, gpt-4-0613, text-davinci-003
messages: (only for OpenAI chat models) a list of messages to be used as a prompt. Each message is a dict with two keys: role and content
prompt: (only for text-davinci-003 model) a string to be used as a prompt
"""
num_tokens = anthropic.count_tokens(prompt)
return num_tokens
def generate_query(
self, question: str, instructions: str, k_shot_prompt: str
) -> dict:
start_time = time.time()
self.err = ""
self.query = ""
self.reason = ""
with open(self.prompt_file) as file:
model_prompt = file.read()
# Check that Human and Assistant prompts are in the prompt file
if "Human:" not in model_prompt:
raise ValueError("Invalid prompt file. Please use prompt_anthropic.md")
question_instructions = question + " " + instructions
prompt = model_prompt.format(
user_question=question,
table_metadata_string=prune_metadata_str(
question_instructions, self.db_name, self.use_public_data
),
instructions=instructions,
k_shot_prompt=k_shot_prompt,
)
function_to_run = self.get_completion
package = prompt
try:
self.completion = func_timeout(
self.timeout,
function_to_run,
args=(
self.model,
package,
400,
0,
["```", ";"],
),
)
results = self.completion
self.query = results.split("```sql")[-1].split(";")[0].split("```")[0]
self.reason = "-"
except FunctionTimedOut:
if self.verbose:
print("generating query timed out")
self.err = "QUERY GENERATION TIMEOUT"
except Exception as e:
if self.verbose:
print(f"Error while generating query: {type(e)}, {e})")
self.query = ""
self.reason = ""
if isinstance(e, KeyError):
self.err = f"QUERY GENERATION ERROR: {type(e)}, {e}, Completion: {self.completion}"
else:
self.err = f"QUERY GENERATION ERROR: {type(e)}, {e}"
tokens_used = self.count_tokens(prompt=prompt)
return {
"query": self.query,
"reason": self.reason,
"err": self.err,
"latency_seconds": time.time() - start_time,
"tokens_used": tokens_used,
}