-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #20 from AthenaFoundation/thread_based_tcp_sockets
Thread-based TCP sockets
- Loading branch information
Showing
14 changed files
with
868 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import sys | ||
import socket | ||
import sys | ||
import json | ||
from utils import * | ||
|
||
def extract_response(sock): | ||
chunks = [] | ||
while True: | ||
chunk = sock.recv(40960) | ||
if not chunk: # Connection closed by server | ||
break | ||
chunks.append(chunk) | ||
return b''.join(chunks).decode('utf-8') | ||
|
||
|
||
# Note: send_request_to_server_simple should only be used if the corresponding server uses readAllSimple. | ||
|
||
def send_request_to_server_simple(request: str, port=10000) -> str: | ||
server_address = 'localhost' | ||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: | ||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | ||
sock.settimeout(4) # Set a 5-second timeout for demonstration | ||
try: | ||
sock.connect((server_address, port)) | ||
sock.sendall(request.encode('utf-8')) | ||
sock.sendall(''.encode('utf-8')) | ||
sock.shutdown(socket.SHUT_WR) | ||
return extract_response(sock) | ||
except socket.timeout: | ||
print("Connection timed out.") | ||
return "" | ||
except Exception as e: | ||
print(f"An error occurred: {e}") | ||
return "" | ||
|
||
# The default implementation of send_request_to_server encodes the size of the | ||
# Athena payload into the first 4 bytes of the request (thus allowing payloads up to 4GB). | ||
# This must be used in conjunction with readAll on the server side, which first extracts | ||
# the leading 4 bytes of the client's request, transforms those into the integer value N | ||
# they represent, and then reads exactly N bytes from the connection. | ||
|
||
def send_request_to_server(request: str, port=10000) -> str: | ||
server_address = 'localhost' | ||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: | ||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | ||
sock.settimeout(4) | ||
try: | ||
sock.connect((server_address, port)) | ||
# Send length as 4-byte integer first | ||
request_bytes = request.encode('utf-8') | ||
length = len(request_bytes) | ||
sock.sendall(length.to_bytes(4, byteorder='big')) | ||
sock.sendall(request_bytes) | ||
sock.shutdown(socket.SHUT_WR) | ||
return extract_response(sock) | ||
except socket.timeout: | ||
print("Connection timed out.") | ||
return "" | ||
except Exception as e: | ||
print(f"An error occurred: {e}") | ||
return "" | ||
|
||
def spaces(i): | ||
if i < 1: | ||
return "" | ||
else: | ||
return " " + spaces(i-1) | ||
|
||
def checkProof(line): | ||
# | ||
# This function takes a string representing a line from a .jsonl file like gpt_and_english_proofs_230.jsonl | ||
# and checks whether or not the formal proof that can be found in that line is valid. If it is, it returns | ||
# a pair of the form (True,<theorem>), where the string <theorem> is a formula representing the conclusion of the proof. | ||
# If the proof is not valid, then the result is a pair of the form (False,<error message>), where the string <error message> | ||
# provides more detail on where exactly the proof went wrong, and what exactly was wrong (a syntax error, a logic error, and if | ||
# so, the type of error, etc.). | ||
# | ||
D = json.loads(line) | ||
premises = D['premises'] | ||
goal = D['goal'] | ||
assumes = '\n'.join([spaces(index) + "assume premise-" + str(index+1) + " := " + premises[index] for index in range(len(premises))]) | ||
proof = assumes + "\nconclude " + goal + "\n" + D['ndlProof'] | ||
athena_response = send_request_to_server(proof) | ||
athena_response_lower = athena_response.lower() | ||
if 'error' in athena_response_lower or 'failed' in athena_response_lower: | ||
return (False,athena_response) | ||
else: | ||
return (True,athena_response) | ||
|
||
def checkAll(file): | ||
# | ||
# This function works with an entire jsonl file like gpt_and_english_proofs_230.jsonl. It basically | ||
# iterates the single-line function checkProof over all the contents of the jsonl file. The result | ||
# is a list of pairs (boolean_flag,<details>), as produced by checkProof, one for each line in the jsonl file. | ||
# | ||
L = getLines(file) | ||
R = [] | ||
send_request_to_server('declare A, B, C, D, E, F, G, H, J, I, K: Boolean') | ||
for i in range(len(L)): | ||
print("About to work on proof #" + str(i)) | ||
response = checkProof(L[i]) | ||
R.append(response) | ||
return R | ||
|
||
# Example use (where file is a path like "../data/gpt_generated_athena_and_english_proofs_raw_data_230.ath"): | ||
# R = checkAll(file) | ||
# This will give all successful/valid proofs: | ||
# T = [r for r in R if r[0]] | ||
# And this will give all incorrect proofs: | ||
# F = [r for r in R if not(r[0])] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
mlton @MLton gc-summary -- -output athena -verbose 1 -default-ann 'allowFFI true' -drop-pass deepFlatten -codegen native athena.mlb |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
mlton @MLton gc-summary -- -output athena -verbose 1 -default-ann 'allowFFI true' -drop-pass deepFlatten athena.mlb |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,55 @@ | ||
val _ = Athena.main("",CommandLine.arguments()) | ||
(*============================================================================================================ | ||
Assuming that the executable produced by running make_athena_binary_for_linux or make_athena_binary_for_mac | ||
is named "athena", you can run the system in a number of ways: | ||
./athena -> Start the Athena REPL | ||
./athena foo.ath -> Load foo.ath first and then start the Athena REPL | ||
./athena foo.ath quit -> Load foo.ath and then quit | ||
./athena -port <number> -> Start an Athena TCP server running on port <number> | ||
./athena -port <number> -file foo.ath -> Load foo.ath first and then start an Athena TCP server on port <number> | ||
============================================================================================================*) | ||
|
||
|
||
fun mlton_main(arg0,args) = | ||
let fun M(file_name_option:string option,quit_after) = | ||
(print("\nWelcome to Athena!\n"); | ||
print("\nType an expression or deduction at the\nprompt below, "); | ||
print("and press Enter to evaluate it.\n"); | ||
print("\nTo exit Athena, type \"quit\" at the prompt\nand press Enter.\n"); | ||
if quit_after then | ||
Athena.runWithStarterFileAndQuit(file_name_option) | ||
else | ||
Athena.runWithStarterFile(file_name_option); | ||
OS.Process.success) | ||
(** | ||
val i = initializeXSB() | ||
**) | ||
in | ||
(case args of | ||
[] => M(NONE,false) | ||
| [file_name] => M(SOME(file_name),false) | ||
| [arg_1,arg_2] => if arg_1 = "-port" orelse arg_1 = "--port" then | ||
let val port_num_opt = Int.fromString(arg_2) | ||
in | ||
(case port_num_opt of | ||
SOME(port_num) => (Thread.spawn(fn () => AthenaServer.startServer(port_num,NONE)); Thread.run(); OS.Process.success) | ||
| _ => (print("\nInvalid port number."); OS.Process.failure)) | ||
end | ||
else M(SOME(arg_1),true) | ||
| [arg_1,arg_2,arg_3,arg_4] => | ||
if (arg_1 = "-port" orelse arg_1 = "--port") andalso (arg_3 = "--file" orelse arg_3 = "-file") then | ||
let val port_num_opt = Int.fromString(arg_2) | ||
val starter_file = arg_4 | ||
in | ||
(case port_num_opt of | ||
SOME(port_num) => (Thread.spawn(fn () => AthenaServer.startServer(port_num,SOME(starter_file))); Thread.run(); OS.Process.success) | ||
| _ => (print("\nInvalid port number."); OS.Process.failure)) | ||
end | ||
else | ||
M(SOME(arg_1),true) | ||
| file_name::(_::_) => M(SOME(file_name),true)) | ||
end | ||
|
||
val _ = mlton_main("",CommandLine.arguments()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.