From 9bd7dbb17b80bcae2bb23d44ac9001dc8b0e8e04 Mon Sep 17 00:00:00 2001 From: Yingbei Date: Mon, 18 Mar 2024 18:21:33 -0700 Subject: [PATCH] a first working version integrated tree_sitter with python parser code --- Makefile | 10 +- examples/server/python-parser.hpp | 126 ++ examples/server/tree_sitter/libtree-sitter.a | Bin 0 -> 232784 bytes .../server/tree_sitter/tree-sitter-python | 1 + examples/server/tree_sitter/tree_sitter/api.h | 1262 +++++++++++++++++ examples/server/utils.hpp | 13 +- test_llamacpp.ipynb | 147 +- 7 files changed, 1540 insertions(+), 19 deletions(-) create mode 100644 examples/server/python-parser.hpp create mode 100644 examples/server/tree_sitter/libtree-sitter.a create mode 160000 examples/server/tree_sitter/tree-sitter-python create mode 100644 examples/server/tree_sitter/tree_sitter/api.h diff --git a/Makefile b/Makefile index c8fd3f5c5..60f81870c 100644 --- a/Makefile +++ b/Makefile @@ -669,6 +669,12 @@ clean: rm -vrf *.o tests/*.o *.so *.a *.dll benchmark-matmult common/build-info.cpp *.dot $(COV_TARGETS) $(BUILD_TARGETS) $(TEST_TARGETS) find examples pocs -type f -name "*.o" -delete +scanner.o: examples/server/tree_sitter/tree-sitter-python/src/scanner.c + $(CC) $(CFLAGS) -c $< -o $@ + +parser.o: examples/server/tree_sitter/tree-sitter-python/src/parser.c + $(CC) $(CFLAGS) -c $< -o $@ + # # Examples # @@ -735,8 +741,8 @@ save-load-state: examples/save-load-state/save-load-state.cpp ggml.o llama.o $(C $(CXX) $(CXXFLAGS) -c $< -o $(call GET_OBJ_FILE, $<) $(CXX) $(CXXFLAGS) $(filter-out %.h $<,$^) $(call GET_OBJ_FILE, $<) -o $@ $(LDFLAGS) -server: examples/server/server.cpp examples/server/utils.hpp examples/server/httplib.h examples/server/json.hpp examples/server/index.html.hpp examples/server/index.js.hpp examples/server/completion.js.hpp common/stb_image.h ggml.o llama.o $(COMMON_DEPS) grammar-parser.o $(OBJS) - $(CXX) $(CXXFLAGS) -c $< -o $(call GET_OBJ_FILE, $<) +server: examples/server/server.cpp examples/server/utils.hpp examples/server/python-parser.hpp examples/server/tree_sitter/libtree-sitter.a examples/server/httplib.h examples/server/json.hpp examples/server/index.html.hpp examples/server/index.js.hpp examples/server/completion.js.hpp common/stb_image.h ggml.o llama.o scanner.o parser.o $(COMMON_DEPS) grammar-parser.o $(OBJS) + $(CXX) $(CXXFLAGS) -c $< -I examples/server/tree_sitter -o $(call GET_OBJ_FILE, $<) $(CXX) $(CXXFLAGS) $(filter-out %.h %.hpp $<,$^) -Iexamples/server $(call GET_OBJ_FILE, $<) -o $@ $(LDFLAGS) $(LWINSOCK2) gguf: examples/gguf/gguf.cpp ggml.o $(OBJS) diff --git a/examples/server/python-parser.hpp b/examples/server/python-parser.hpp new file mode 100644 index 000000000..83d70f219 --- /dev/null +++ b/examples/server/python-parser.hpp @@ -0,0 +1,126 @@ +#include +#include +#include +#include +#include +#include "json.hpp" // Include the JSON library + +extern "C" TSLanguage *tree_sitter_python(); + +using json = nlohmann::json; // Use an alias for easier access + + +static json parseValue(const std::string& content) { + // Check for numerical value + if (!content.empty() && std::all_of(content.begin(), content.end(), ::isdigit)) { + return std::stoi(content); + } + // Check for boolean + if (content == "True" || content == "true") { + return true; + } else if (content == "False" || content == "false") { + return false; + } + if ((content.size() >= 2 && content.front() == '"' && content.back() == '"') || + (content.size() >= 2 && content.front() == '\'' && content.back() == '\'')) { + return content.substr(1, content.size() - 2); + } + // TODO: for array, dict, object, function, should further add logic to parse them recursively. + return content; +} + + +// Recursive function to parse and create JSON for the outer function calls +static void parseFunctionCalls(const TSNode& node, std::vector& calls, const char* source_code, uint32_t indent = 0) { + auto type = ts_node_type(node); + + printf("type: %s\n", type); + // Only interested in call_expression nodes at the outermost level + if (strcmp(type, "call") == 0) { + + json call = { + {"name", ""}, + {"args", json::array()}, + {"kwargs", json::object()} + }; + + TSNode functionNode = ts_node_child(node, 0); // The function name node + TSNode argumentsNode = ts_node_child(node, 1); // The arguments node + + // Extract the function name + call["name"] = std::string(source_code + ts_node_start_byte(functionNode), ts_node_end_byte(functionNode) - ts_node_start_byte(functionNode)); + + // Loop through the arguments + unsigned int numArgs = ts_node_named_child_count(argumentsNode); + for (unsigned int i = 0; i < numArgs; ++i) { + TSNode argNode = ts_node_named_child(argumentsNode, i); + const char* argType = ts_node_type(argNode); + + // Check if the argument is a positional argument or a keyword argument + if (strcmp(argType, "argument") == 0 || strcmp(argType, "positional_arguments") == 0 || strcmp(argType, "string") == 0 || strcmp(argType, "integer") == 0 || strcmp(argType, "true") == 0 || strcmp(argType, "false") == 0) { + // For simplification, we treat the entire content as the argument + std::string value = std::string(source_code + ts_node_start_byte(argNode), ts_node_end_byte(argNode) - ts_node_start_byte(argNode)); + call["args"].push_back(parseValue(value)); + } else if (strcmp(argType, "keyword_argument") == 0) { + // Extract keyword and value for keyword arguments + TSNode keyNode = ts_node_child(argNode, 0); // The key of the kwarg + TSNode valueNode = ts_node_child(argNode, 2); // The value of the kwarg, 1 is the symbol `=` + + // if this is 0 then it's a string/integer/boolean, simply parse it + // unsigned int numValueNodeChild = ts_node_named_child_count(valueNode); + // TODO: if numValueNodeChild != 0 then it's an array/list/object?/function. Need to do something more. However for now we assume this will not happen. + + std::string key = std::string(source_code + ts_node_start_byte(keyNode), ts_node_end_byte(keyNode) - ts_node_start_byte(keyNode)); + std::string value = std::string(source_code + ts_node_start_byte(valueNode), ts_node_end_byte(valueNode) - ts_node_start_byte(valueNode)); + call["kwargs"][key] = parseValue(value); + } + } + + calls.push_back(call); + return; // Stop recursion to only process outer function calls + } + + // Recurse through all children for other node types + unsigned int numChildren = ts_node_child_count(node); + for (unsigned int i = 0; i < numChildren; ++i) { + TSNode child = ts_node_child(node, i); + parseFunctionCalls(child, calls, source_code, indent+1); + } +} + +static std::vector parsePythonFunctionCalls(std::string source_string) { + std::vector calls; + std::string delimiter = "<>"; + std::string source_code; + printf("source_string: %s\n", source_string.c_str()); + size_t startPos = source_string.find(delimiter); + if (startPos != std::string::npos) { + source_code = source_string.substr(startPos + delimiter.length()); + } else { + printf("no functions\n"); + return calls; + } + TSParser *parser = ts_parser_new(); + ts_parser_set_language(parser, tree_sitter_python()); + const char* source_code_cstr = source_code.c_str(); + TSTree *tree = ts_parser_parse_string(parser, nullptr, source_code_cstr, source_code.length()); + TSNode root_node = ts_tree_root_node(tree); + + bool has_errors = ts_node_has_error(root_node); + + if (has_errors) { + // probably a regular string + printf("has errors\n"); + return calls; + } + + parseFunctionCalls(root_node, calls, source_code_cstr, 0); + + // Output the parsed calls + + ts_tree_delete(tree); + ts_parser_delete(parser); + printf("calls: %s\n", json(calls).dump().c_str()); + return calls; +} + diff --git a/examples/server/tree_sitter/libtree-sitter.a b/examples/server/tree_sitter/libtree-sitter.a new file mode 100644 index 0000000000000000000000000000000000000000..330f5a4051bae52f942d0c58193bac28bfc44f0d GIT binary patch literal 232784 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 TzKm9CVXymzf%y`1w{`-;+?wuiFT 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ⅅ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 literal 0 HcmV?d00001 diff --git a/examples/server/tree_sitter/tree-sitter-python b/examples/server/tree_sitter/tree-sitter-python new file mode 160000 index 000000000..b8a4c6412 --- /dev/null +++ b/examples/server/tree_sitter/tree-sitter-python @@ -0,0 +1 @@ +Subproject commit b8a4c64121ba66b460cb878e934e3157ecbfb124 diff --git a/examples/server/tree_sitter/tree_sitter/api.h b/examples/server/tree_sitter/tree_sitter/api.h new file mode 100644 index 000000000..69c65fab6 --- /dev/null +++ b/examples/server/tree_sitter/tree_sitter/api.h @@ -0,0 +1,1262 @@ +#ifndef TREE_SITTER_API_H_ +#define TREE_SITTER_API_H_ + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC visibility push(default) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/****************************/ +/* Section - ABI Versioning */ +/****************************/ + +/** + * The latest ABI version that is supported by the current version of the + * library. When Languages are generated by the Tree-sitter CLI, they are + * assigned an ABI version number that corresponds to the current CLI version. + * The Tree-sitter library is generally backwards-compatible with languages + * generated using older CLI versions, but is not forwards-compatible. + */ +#define TREE_SITTER_LANGUAGE_VERSION 14 + +/** + * The earliest ABI version that is supported by the current version of the + * library. + */ +#define TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION 13 + +/*******************/ +/* Section - Types */ +/*******************/ + +typedef uint16_t TSStateId; +typedef uint16_t TSSymbol; +typedef uint16_t TSFieldId; +typedef struct TSLanguage TSLanguage; +typedef struct TSParser TSParser; +typedef struct TSTree TSTree; +typedef struct TSQuery TSQuery; +typedef struct TSQueryCursor TSQueryCursor; +typedef struct TSLookaheadIterator TSLookaheadIterator; + +typedef enum TSInputEncoding { + TSInputEncodingUTF8, + TSInputEncodingUTF16, +} TSInputEncoding; + +typedef enum TSSymbolType { + TSSymbolTypeRegular, + TSSymbolTypeAnonymous, + TSSymbolTypeAuxiliary, +} TSSymbolType; + +typedef struct TSPoint { + uint32_t row; + uint32_t column; +} TSPoint; + +typedef struct TSRange { + TSPoint start_point; + TSPoint end_point; + uint32_t start_byte; + uint32_t end_byte; +} TSRange; + +typedef struct TSInput { + void *payload; + const char *(*read)(void *payload, uint32_t byte_index, TSPoint position, uint32_t *bytes_read); + TSInputEncoding encoding; +} TSInput; + +typedef enum TSLogType { + TSLogTypeParse, + TSLogTypeLex, +} TSLogType; + +typedef struct TSLogger { + void *payload; + void (*log)(void *payload, TSLogType log_type, const char *buffer); +} TSLogger; + +typedef struct TSInputEdit { + uint32_t start_byte; + uint32_t old_end_byte; + uint32_t new_end_byte; + TSPoint start_point; + TSPoint old_end_point; + TSPoint new_end_point; +} TSInputEdit; + +typedef struct TSNode { + uint32_t context[4]; + const void *id; + const TSTree *tree; +} TSNode; + +typedef struct TSTreeCursor { + const void *tree; + const void *id; + uint32_t context[2]; +} TSTreeCursor; + +typedef struct TSQueryCapture { + TSNode node; + uint32_t index; +} TSQueryCapture; + +typedef enum TSQuantifier { + TSQuantifierZero = 0, // must match the array initialization value + TSQuantifierZeroOrOne, + TSQuantifierZeroOrMore, + TSQuantifierOne, + TSQuantifierOneOrMore, +} TSQuantifier; + +typedef struct TSQueryMatch { + uint32_t id; + uint16_t pattern_index; + uint16_t capture_count; + const TSQueryCapture *captures; +} TSQueryMatch; + +typedef enum TSQueryPredicateStepType { + TSQueryPredicateStepTypeDone, + TSQueryPredicateStepTypeCapture, + TSQueryPredicateStepTypeString, +} TSQueryPredicateStepType; + +typedef struct TSQueryPredicateStep { + TSQueryPredicateStepType type; + uint32_t value_id; +} TSQueryPredicateStep; + +typedef enum TSQueryError { + TSQueryErrorNone = 0, + TSQueryErrorSyntax, + TSQueryErrorNodeType, + TSQueryErrorField, + TSQueryErrorCapture, + TSQueryErrorStructure, + TSQueryErrorLanguage, +} TSQueryError; + +/********************/ +/* Section - Parser */ +/********************/ + +/** + * Create a new parser. + */ +TSParser *ts_parser_new(void); + +/** + * Delete the parser, freeing all of the memory that it used. + */ +void ts_parser_delete(TSParser *self); + +/** + * Get the parser's current language. + */ +const TSLanguage *ts_parser_language(const TSParser *self); + +/** + * Set the language that the parser should use for parsing. + * + * Returns a boolean indicating whether or not the language was successfully + * assigned. True means assignment succeeded. False means there was a version + * mismatch: the language was generated with an incompatible version of the + * Tree-sitter CLI. Check the language's version using [`ts_language_version`] + * and compare it to this library's [`TREE_SITTER_LANGUAGE_VERSION`] and + * [`TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION`] constants. + */ +bool ts_parser_set_language(TSParser *self, const TSLanguage *language); + +/** + * Set the ranges of text that the parser should include when parsing. + * + * By default, the parser will always include entire documents. This function + * allows you to parse only a *portion* of a document but still return a syntax + * tree whose ranges match up with the document as a whole. You can also pass + * multiple disjoint ranges. + * + * The second and third parameters specify the location and length of an array + * of ranges. The parser does *not* take ownership of these ranges; it copies + * the data, so it doesn't matter how these ranges are allocated. + * + * If `count` is zero, then the entire document will be parsed. Otherwise, + * the given ranges must be ordered from earliest to latest in the document, + * and they must not overlap. That is, the following must hold for all: + * + * `i < count - 1`: `ranges[i].end_byte <= ranges[i + 1].start_byte` + * + * If this requirement is not satisfied, the operation will fail, the ranges + * will not be assigned, and this function will return `false`. On success, + * this function returns `true` + */ +bool ts_parser_set_included_ranges( + TSParser *self, + const TSRange *ranges, + uint32_t count +); + +/** + * Get the ranges of text that the parser will include when parsing. + * + * The returned pointer is owned by the parser. The caller should not free it + * or write to it. The length of the array will be written to the given + * `count` pointer. + */ +const TSRange *ts_parser_included_ranges( + const TSParser *self, + uint32_t *count +); + +/** + * Use the parser to parse some source code and create a syntax tree. + * + * If you are parsing this document for the first time, pass `NULL` for the + * `old_tree` parameter. Otherwise, if you have already parsed an earlier + * version of this document and the document has since been edited, pass the + * previous syntax tree so that the unchanged parts of it can be reused. + * This will save time and memory. For this to work correctly, you must have + * already edited the old syntax tree using the [`ts_tree_edit`] function in a + * way that exactly matches the source code changes. + * + * The [`TSInput`] parameter lets you specify how to read the text. It has the + * following three fields: + * 1. [`read`]: A function to retrieve a chunk of text at a given byte offset + * and (row, column) position. The function should return a pointer to the + * text and write its length to the [`bytes_read`] pointer. The parser does + * not take ownership of this buffer; it just borrows it until it has + * finished reading it. The function should write a zero value to the + * [`bytes_read`] pointer to indicate the end of the document. + * 2. [`payload`]: An arbitrary pointer that will be passed to each invocation + * of the [`read`] function. + * 3. [`encoding`]: An indication of how the text is encoded. Either + * `TSInputEncodingUTF8` or `TSInputEncodingUTF16`. + * + * This function returns a syntax tree on success, and `NULL` on failure. There + * are three possible reasons for failure: + * 1. The parser does not have a language assigned. Check for this using the + [`ts_parser_language`] function. + * 2. Parsing was cancelled due to a timeout that was set by an earlier call to + * the [`ts_parser_set_timeout_micros`] function. You can resume parsing from + * where the parser left out by calling [`ts_parser_parse`] again with the + * same arguments. Or you can start parsing from scratch by first calling + * [`ts_parser_reset`]. + * 3. Parsing was cancelled using a cancellation flag that was set by an + * earlier call to [`ts_parser_set_cancellation_flag`]. You can resume parsing + * from where the parser left out by calling [`ts_parser_parse`] again with + * the same arguments. + * + * [`read`]: TSInput::read + * [`payload`]: TSInput::payload + * [`encoding`]: TSInput::encoding + * [`bytes_read`]: TSInput::read + */ +TSTree *ts_parser_parse( + TSParser *self, + const TSTree *old_tree, + TSInput input +); + +/** + * Use the parser to parse some source code stored in one contiguous buffer. + * The first two parameters are the same as in the [`ts_parser_parse`] function + * above. The second two parameters indicate the location of the buffer and its + * length in bytes. + */ +TSTree *ts_parser_parse_string( + TSParser *self, + const TSTree *old_tree, + const char *string, + uint32_t length +); + +/** + * Use the parser to parse some source code stored in one contiguous buffer with + * a given encoding. The first four parameters work the same as in the + * [`ts_parser_parse_string`] method above. The final parameter indicates whether + * the text is encoded as UTF8 or UTF16. + */ +TSTree *ts_parser_parse_string_encoding( + TSParser *self, + const TSTree *old_tree, + const char *string, + uint32_t length, + TSInputEncoding encoding +); + +/** + * Instruct the parser to start the next parse from the beginning. + * + * If the parser previously failed because of a timeout or a cancellation, then + * by default, it will resume where it left off on the next call to + * [`ts_parser_parse`] or other parsing functions. If you don't want to resume, + * and instead intend to use this parser to parse some other document, you must + * call [`ts_parser_reset`] first. + */ +void ts_parser_reset(TSParser *self); + +/** + * Set the maximum duration in microseconds that parsing should be allowed to + * take before halting. + * + * If parsing takes longer than this, it will halt early, returning NULL. + * See [`ts_parser_parse`] for more information. + */ +void ts_parser_set_timeout_micros(TSParser *self, uint64_t timeout_micros); + +/** + * Get the duration in microseconds that parsing is allowed to take. + */ +uint64_t ts_parser_timeout_micros(const TSParser *self); + +/** + * Set the parser's current cancellation flag pointer. + * + * If a non-null pointer is assigned, then the parser will periodically read + * from this pointer during parsing. If it reads a non-zero value, it will + * halt early, returning NULL. See [`ts_parser_parse`] for more information. + */ +void ts_parser_set_cancellation_flag(TSParser *self, const size_t *flag); + +/** + * Get the parser's current cancellation flag pointer. + */ +const size_t *ts_parser_cancellation_flag(const TSParser *self); + +/** + * Set the logger that a parser should use during parsing. + * + * The parser does not take ownership over the logger payload. If a logger was + * previously assigned, the caller is responsible for releasing any memory + * owned by the previous logger. + */ +void ts_parser_set_logger(TSParser *self, TSLogger logger); + +/** + * Get the parser's current logger. + */ +TSLogger ts_parser_logger(const TSParser *self); + +/** + * Set the file descriptor to which the parser should write debugging graphs + * during parsing. The graphs are formatted in the DOT language. You may want + * to pipe these graphs directly to a `dot(1)` process in order to generate + * SVG output. You can turn off this logging by passing a negative number. + */ +void ts_parser_print_dot_graphs(TSParser *self, int fd); + +/******************/ +/* Section - Tree */ +/******************/ + +/** + * Create a shallow copy of the syntax tree. This is very fast. + * + * You need to copy a syntax tree in order to use it on more than one thread at + * a time, as syntax trees are not thread safe. + */ +TSTree *ts_tree_copy(const TSTree *self); + +/** + * Delete the syntax tree, freeing all of the memory that it used. + */ +void ts_tree_delete(TSTree *self); + +/** + * Get the root node of the syntax tree. + */ +TSNode ts_tree_root_node(const TSTree *self); + +/** + * Get the root node of the syntax tree, but with its position + * shifted forward by the given offset. + */ +TSNode ts_tree_root_node_with_offset( + const TSTree *self, + uint32_t offset_bytes, + TSPoint offset_extent +); + +/** + * Get the language that was used to parse the syntax tree. + */ +const TSLanguage *ts_tree_language(const TSTree *self); + +/** + * Get the array of included ranges that was used to parse the syntax tree. + * + * The returned pointer must be freed by the caller. + */ +TSRange *ts_tree_included_ranges(const TSTree *self, uint32_t *length); + +/** + * Edit the syntax tree to keep it in sync with source code that has been + * edited. + * + * You must describe the edit both in terms of byte offsets and in terms of + * (row, column) coordinates. + */ +void ts_tree_edit(TSTree *self, const TSInputEdit *edit); + +/** + * Compare an old edited syntax tree to a new syntax tree representing the same + * document, returning an array of ranges whose syntactic structure has changed. + * + * For this to work correctly, the old syntax tree must have been edited such + * that its ranges match up to the new tree. Generally, you'll want to call + * this function right after calling one of the [`ts_parser_parse`] functions. + * You need to pass the old tree that was passed to parse, as well as the new + * tree that was returned from that function. + * + * The returned array is allocated using `malloc` and the caller is responsible + * for freeing it using `free`. The length of the array will be written to the + * given `length` pointer. + */ +TSRange *ts_tree_get_changed_ranges( + const TSTree *old_tree, + const TSTree *new_tree, + uint32_t *length +); + +/** + * Write a DOT graph describing the syntax tree to the given file. + */ +void ts_tree_print_dot_graph(const TSTree *self, int file_descriptor); + +/******************/ +/* Section - Node */ +/******************/ + +/** + * Get the node's type as a null-terminated string. + */ +const char *ts_node_type(TSNode self); + +/** + * Get the node's type as a numerical id. + */ +TSSymbol ts_node_symbol(TSNode self); + +/** + * Get the node's language. + */ +const TSLanguage *ts_node_language(TSNode self); + +/** + * Get the node's type as it appears in the grammar ignoring aliases as a + * null-terminated string. + */ +const char *ts_node_grammar_type(TSNode self); + +/** + * Get the node's type as a numerical id as it appears in the grammar ignoring + * aliases. This should be used in [`ts_language_next_state`] instead of + * [`ts_node_symbol`]. + */ +TSSymbol ts_node_grammar_symbol(TSNode self); + +/** + * Get the node's start byte. + */ +uint32_t ts_node_start_byte(TSNode self); + +/** + * Get the node's start position in terms of rows and columns. + */ +TSPoint ts_node_start_point(TSNode self); + +/** + * Get the node's end byte. + */ +uint32_t ts_node_end_byte(TSNode self); + +/** + * Get the node's end position in terms of rows and columns. + */ +TSPoint ts_node_end_point(TSNode self); + +/** + * Get an S-expression representing the node as a string. + * + * This string is allocated with `malloc` and the caller is responsible for + * freeing it using `free`. + */ +char *ts_node_string(TSNode self); + +/** + * Check if the node is null. Functions like [`ts_node_child`] and + * [`ts_node_next_sibling`] will return a null node to indicate that no such node + * was found. + */ +bool ts_node_is_null(TSNode self); + +/** + * Check if the node is *named*. Named nodes correspond to named rules in the + * grammar, whereas *anonymous* nodes correspond to string literals in the + * grammar. + */ +bool ts_node_is_named(TSNode self); + +/** + * Check if the node is *missing*. Missing nodes are inserted by the parser in + * order to recover from certain kinds of syntax errors. + */ +bool ts_node_is_missing(TSNode self); + +/** + * Check if the node is *extra*. Extra nodes represent things like comments, + * which are not required the grammar, but can appear anywhere. + */ +bool ts_node_is_extra(TSNode self); + +/** + * Check if a syntax node has been edited. + */ +bool ts_node_has_changes(TSNode self); + +/** + * Check if the node is a syntax error or contains any syntax errors. + */ +bool ts_node_has_error(TSNode self); + +/** + * Check if the node is a syntax error. +*/ +bool ts_node_is_error(TSNode self); + +/** + * Get this node's parse state. +*/ +TSStateId ts_node_parse_state(TSNode self); + +/** + * Get the parse state after this node. +*/ +TSStateId ts_node_next_parse_state(TSNode self); + +/** + * Get the node's immediate parent. + */ +TSNode ts_node_parent(TSNode self); + +/** + * Get the node's child at the given index, where zero represents the first + * child. + */ +TSNode ts_node_child(TSNode self, uint32_t child_index); + +/** + * Get the field name for node's child at the given index, where zero represents + * the first child. Returns NULL, if no field is found. + */ +const char *ts_node_field_name_for_child(TSNode self, uint32_t child_index); + +/** + * Get the node's number of children. + */ +uint32_t ts_node_child_count(TSNode self); + +/** + * Get the node's *named* child at the given index. + * + * See also [`ts_node_is_named`]. + */ +TSNode ts_node_named_child(TSNode self, uint32_t child_index); + +/** + * Get the node's number of *named* children. + * + * See also [`ts_node_is_named`]. + */ +uint32_t ts_node_named_child_count(TSNode self); + +/** + * Get the node's child with the given field name. + */ +TSNode ts_node_child_by_field_name( + TSNode self, + const char *name, + uint32_t name_length +); + +/** + * Get the node's child with the given numerical field id. + * + * You can convert a field name to an id using the + * [`ts_language_field_id_for_name`] function. + */ +TSNode ts_node_child_by_field_id(TSNode self, TSFieldId field_id); + +/** + * Get the node's next / previous sibling. + */ +TSNode ts_node_next_sibling(TSNode self); +TSNode ts_node_prev_sibling(TSNode self); + +/** + * Get the node's next / previous *named* sibling. + */ +TSNode ts_node_next_named_sibling(TSNode self); +TSNode ts_node_prev_named_sibling(TSNode self); + +/** + * Get the node's first child that extends beyond the given byte offset. + */ +TSNode ts_node_first_child_for_byte(TSNode self, uint32_t byte); + +/** + * Get the node's first named child that extends beyond the given byte offset. + */ +TSNode ts_node_first_named_child_for_byte(TSNode self, uint32_t byte); + +/** + * Get the node's number of descendants, including one for the node itself. + */ +uint32_t ts_node_descendant_count(TSNode self); + +/** + * Get the smallest node within this node that spans the given range of bytes + * or (row, column) positions. + */ +TSNode ts_node_descendant_for_byte_range(TSNode self, uint32_t start, uint32_t end); +TSNode ts_node_descendant_for_point_range(TSNode self, TSPoint start, TSPoint end); + +/** + * Get the smallest named node within this node that spans the given range of + * bytes or (row, column) positions. + */ +TSNode ts_node_named_descendant_for_byte_range(TSNode self, uint32_t start, uint32_t end); +TSNode ts_node_named_descendant_for_point_range(TSNode self, TSPoint start, TSPoint end); + +/** + * Edit the node to keep it in-sync with source code that has been edited. + * + * This function is only rarely needed. When you edit a syntax tree with the + * [`ts_tree_edit`] function, all of the nodes that you retrieve from the tree + * afterward will already reflect the edit. You only need to use [`ts_node_edit`] + * when you have a [`TSNode`] instance that you want to keep and continue to use + * after an edit. + */ +void ts_node_edit(TSNode *self, const TSInputEdit *edit); + +/** + * Check if two nodes are identical. + */ +bool ts_node_eq(TSNode self, TSNode other); + +/************************/ +/* Section - TreeCursor */ +/************************/ + +/** + * Create a new tree cursor starting from the given node. + * + * A tree cursor allows you to walk a syntax tree more efficiently than is + * possible using the [`TSNode`] functions. It is a mutable object that is always + * on a certain syntax node, and can be moved imperatively to different nodes. + */ +TSTreeCursor ts_tree_cursor_new(TSNode node); + +/** + * Delete a tree cursor, freeing all of the memory that it used. + */ +void ts_tree_cursor_delete(TSTreeCursor *self); + +/** + * Re-initialize a tree cursor to start at a different node. + */ +void ts_tree_cursor_reset(TSTreeCursor *self, TSNode node); + +/** + * Re-initialize a tree cursor to the same position as another cursor. + * + * Unlike [`ts_tree_cursor_reset`], this will not lose parent information and + * allows reusing already created cursors. +*/ +void ts_tree_cursor_reset_to(TSTreeCursor *dst, const TSTreeCursor *src); + +/** + * Get the tree cursor's current node. + */ +TSNode ts_tree_cursor_current_node(const TSTreeCursor *self); + +/** + * Get the field name of the tree cursor's current node. + * + * This returns `NULL` if the current node doesn't have a field. + * See also [`ts_node_child_by_field_name`]. + */ +const char *ts_tree_cursor_current_field_name(const TSTreeCursor *self); + +/** + * Get the field id of the tree cursor's current node. + * + * This returns zero if the current node doesn't have a field. + * See also [`ts_node_child_by_field_id`], [`ts_language_field_id_for_name`]. + */ +TSFieldId ts_tree_cursor_current_field_id(const TSTreeCursor *self); + +/** + * Move the cursor to the parent of its current node. + * + * This returns `true` if the cursor successfully moved, and returns `false` + * if there was no parent node (the cursor was already on the root node). + */ +bool ts_tree_cursor_goto_parent(TSTreeCursor *self); + +/** + * Move the cursor to the next sibling of its current node. + * + * This returns `true` if the cursor successfully moved, and returns `false` + * if there was no next sibling node. + */ +bool ts_tree_cursor_goto_next_sibling(TSTreeCursor *self); + +/** + * Move the cursor to the previous sibling of its current node. + * + * This returns `true` if the cursor successfully moved, and returns `false` if + * there was no previous sibling node. + * + * Note, that this function may be slower than + * [`ts_tree_cursor_goto_next_sibling`] due to how node positions are stored. In + * the worst case, this will need to iterate through all the children upto the + * previous sibling node to recalculate its position. + */ +bool ts_tree_cursor_goto_previous_sibling(TSTreeCursor *self); + +/** + * Move the cursor to the first child of its current node. + * + * This returns `true` if the cursor successfully moved, and returns `false` + * if there were no children. + */ +bool ts_tree_cursor_goto_first_child(TSTreeCursor *self); + +/** + * Move the cursor to the last child of its current node. + * + * This returns `true` if the cursor successfully moved, and returns `false` if + * there were no children. + * + * Note that this function may be slower than [`ts_tree_cursor_goto_first_child`] + * because it needs to iterate through all the children to compute the child's + * position. + */ +bool ts_tree_cursor_goto_last_child(TSTreeCursor *self); + +/** + * Move the cursor to the node that is the nth descendant of + * the original node that the cursor was constructed with, where + * zero represents the original node itself. + */ +void ts_tree_cursor_goto_descendant(TSTreeCursor *self, uint32_t goal_descendant_index); + +/** + * Get the index of the cursor's current node out of all of the + * descendants of the original node that the cursor was constructed with. + */ +uint32_t ts_tree_cursor_current_descendant_index(const TSTreeCursor *self); + +/** + * Get the depth of the cursor's current node relative to the original + * node that the cursor was constructed with. + */ +uint32_t ts_tree_cursor_current_depth(const TSTreeCursor *self); + +/** + * Move the cursor to the first child of its current node that extends beyond + * the given byte offset or point. + * + * This returns the index of the child node if one was found, and returns -1 + * if no such child was found. + */ +int64_t ts_tree_cursor_goto_first_child_for_byte(TSTreeCursor *self, uint32_t goal_byte); +int64_t ts_tree_cursor_goto_first_child_for_point(TSTreeCursor *self, TSPoint goal_point); + +TSTreeCursor ts_tree_cursor_copy(const TSTreeCursor *cursor); + +/*******************/ +/* Section - Query */ +/*******************/ + +/** + * Create a new query from a string containing one or more S-expression + * patterns. The query is associated with a particular language, and can + * only be run on syntax nodes parsed with that language. + * + * If all of the given patterns are valid, this returns a [`TSQuery`]. + * If a pattern is invalid, this returns `NULL`, and provides two pieces + * of information about the problem: + * 1. The byte offset of the error is written to the `error_offset` parameter. + * 2. The type of error is written to the `error_type` parameter. + */ +TSQuery *ts_query_new( + const TSLanguage *language, + const char *source, + uint32_t source_len, + uint32_t *error_offset, + TSQueryError *error_type +); + +/** + * Delete a query, freeing all of the memory that it used. + */ +void ts_query_delete(TSQuery *self); + +/** + * Get the number of patterns, captures, or string literals in the query. + */ +uint32_t ts_query_pattern_count(const TSQuery *self); +uint32_t ts_query_capture_count(const TSQuery *self); +uint32_t ts_query_string_count(const TSQuery *self); + +/** + * Get the byte offset where the given pattern starts in the query's source. + * + * This can be useful when combining queries by concatenating their source + * code strings. + */ +uint32_t ts_query_start_byte_for_pattern(const TSQuery *self, uint32_t pattern_index); + +/** + * Get all of the predicates for the given pattern in the query. + * + * The predicates are represented as a single array of steps. There are three + * types of steps in this array, which correspond to the three legal values for + * the `type` field: + * - `TSQueryPredicateStepTypeCapture` - Steps with this type represent names + * of captures. Their `value_id` can be used with the + * [`ts_query_capture_name_for_id`] function to obtain the name of the capture. + * - `TSQueryPredicateStepTypeString` - Steps with this type represent literal + * strings. Their `value_id` can be used with the + * [`ts_query_string_value_for_id`] function to obtain their string value. + * - `TSQueryPredicateStepTypeDone` - Steps with this type are *sentinels* + * that represent the end of an individual predicate. If a pattern has two + * predicates, then there will be two steps with this `type` in the array. + */ +const TSQueryPredicateStep *ts_query_predicates_for_pattern( + const TSQuery *self, + uint32_t pattern_index, + uint32_t *step_count +); + +/* + * Check if the given pattern in the query has a single root node. + */ +bool ts_query_is_pattern_rooted(const TSQuery *self, uint32_t pattern_index); + +/* + * Check if the given pattern in the query is 'non local'. + * + * A non-local pattern has multiple root nodes and can match within a + * repeating sequence of nodes, as specified by the grammar. Non-local + * patterns disable certain optimizations that would otherwise be possible + * when executing a query on a specific range of a syntax tree. + */ +bool ts_query_is_pattern_non_local(const TSQuery *self, uint32_t pattern_index); + +/* + * Check if a given pattern is guaranteed to match once a given step is reached. + * The step is specified by its byte offset in the query's source code. + */ +bool ts_query_is_pattern_guaranteed_at_step(const TSQuery *self, uint32_t byte_offset); + +/** + * Get the name and length of one of the query's captures, or one of the + * query's string literals. Each capture and string is associated with a + * numeric id based on the order that it appeared in the query's source. + */ +const char *ts_query_capture_name_for_id( + const TSQuery *self, + uint32_t index, + uint32_t *length +); + +/** + * Get the quantifier of the query's captures. Each capture is * associated + * with a numeric id based on the order that it appeared in the query's source. + */ +TSQuantifier ts_query_capture_quantifier_for_id( + const TSQuery *self, + uint32_t pattern_index, + uint32_t capture_index +); + +const char *ts_query_string_value_for_id( + const TSQuery *self, + uint32_t index, + uint32_t *length +); + +/** + * Disable a certain capture within a query. + * + * This prevents the capture from being returned in matches, and also avoids + * any resource usage associated with recording the capture. Currently, there + * is no way to undo this. + */ +void ts_query_disable_capture(TSQuery *self, const char *name, uint32_t length); + +/** + * Disable a certain pattern within a query. + * + * This prevents the pattern from matching and removes most of the overhead + * associated with the pattern. Currently, there is no way to undo this. + */ +void ts_query_disable_pattern(TSQuery *self, uint32_t pattern_index); + +/** + * Create a new cursor for executing a given query. + * + * The cursor stores the state that is needed to iteratively search + * for matches. To use the query cursor, first call [`ts_query_cursor_exec`] + * to start running a given query on a given syntax node. Then, there are + * two options for consuming the results of the query: + * 1. Repeatedly call [`ts_query_cursor_next_match`] to iterate over all of the + * *matches* in the order that they were found. Each match contains the + * index of the pattern that matched, and an array of captures. Because + * multiple patterns can match the same set of nodes, one match may contain + * captures that appear *before* some of the captures from a previous match. + * 2. Repeatedly call [`ts_query_cursor_next_capture`] to iterate over all of the + * individual *captures* in the order that they appear. This is useful if + * don't care about which pattern matched, and just want a single ordered + * sequence of captures. + * + * If you don't care about consuming all of the results, you can stop calling + * [`ts_query_cursor_next_match`] or [`ts_query_cursor_next_capture`] at any point. + * You can then start executing another query on another node by calling + * [`ts_query_cursor_exec`] again. + */ +TSQueryCursor *ts_query_cursor_new(void); + +/** + * Delete a query cursor, freeing all of the memory that it used. + */ +void ts_query_cursor_delete(TSQueryCursor *self); + +/** + * Start running a given query on a given node. + */ +void ts_query_cursor_exec(TSQueryCursor *self, const TSQuery *query, TSNode node); + +/** + * Manage the maximum number of in-progress matches allowed by this query + * cursor. + * + * Query cursors have an optional maximum capacity for storing lists of + * in-progress captures. If this capacity is exceeded, then the + * earliest-starting match will silently be dropped to make room for further + * matches. This maximum capacity is optional — by default, query cursors allow + * any number of pending matches, dynamically allocating new space for them as + * needed as the query is executed. + */ +bool ts_query_cursor_did_exceed_match_limit(const TSQueryCursor *self); +uint32_t ts_query_cursor_match_limit(const TSQueryCursor *self); +void ts_query_cursor_set_match_limit(TSQueryCursor *self, uint32_t limit); + +/** + * Set the range of bytes or (row, column) positions in which the query + * will be executed. + */ +void ts_query_cursor_set_byte_range(TSQueryCursor *self, uint32_t start_byte, uint32_t end_byte); +void ts_query_cursor_set_point_range(TSQueryCursor *self, TSPoint start_point, TSPoint end_point); + +/** + * Advance to the next match of the currently running query. + * + * If there is a match, write it to `*match` and return `true`. + * Otherwise, return `false`. + */ +bool ts_query_cursor_next_match(TSQueryCursor *self, TSQueryMatch *match); +void ts_query_cursor_remove_match(TSQueryCursor *self, uint32_t match_id); + +/** + * Advance to the next capture of the currently running query. + * + * If there is a capture, write its match to `*match` and its index within + * the matche's capture list to `*capture_index`. Otherwise, return `false`. + */ +bool ts_query_cursor_next_capture( + TSQueryCursor *self, + TSQueryMatch *match, + uint32_t *capture_index +); + +/** + * Set the maximum start depth for a query cursor. + * + * This prevents cursors from exploring children nodes at a certain depth. + * Note if a pattern includes many children, then they will still be checked. + * + * The zero max start depth value can be used as a special behavior and + * it helps to destructure a subtree by staying on a node and using captures + * for interested parts. Note that the zero max start depth only limit a search + * depth for a pattern's root node but other nodes that are parts of the pattern + * may be searched at any depth what defined by the pattern structure. + * + * Set to `UINT32_MAX` to remove the maximum start depth. + */ +void ts_query_cursor_set_max_start_depth(TSQueryCursor *self, uint32_t max_start_depth); + +/**********************/ +/* Section - Language */ +/**********************/ + +/** + * Get another reference to the given language. + */ +const TSLanguage *ts_language_copy(const TSLanguage *self); + +/** + * Free any dynamically-allocated resources for this language, if + * this is the last reference. + */ +void ts_language_delete(const TSLanguage *self); + +/** + * Get the number of distinct node types in the language. + */ +uint32_t ts_language_symbol_count(const TSLanguage *self); + +/** + * Get the number of valid states in this language. +*/ +uint32_t ts_language_state_count(const TSLanguage *self); + +/** + * Get a node type string for the given numerical id. + */ +const char *ts_language_symbol_name(const TSLanguage *self, TSSymbol symbol); + +/** + * Get the numerical id for the given node type string. + */ +TSSymbol ts_language_symbol_for_name( + const TSLanguage *self, + const char *string, + uint32_t length, + bool is_named +); + +/** + * Get the number of distinct field names in the language. + */ +uint32_t ts_language_field_count(const TSLanguage *self); + +/** + * Get the field name string for the given numerical id. + */ +const char *ts_language_field_name_for_id(const TSLanguage *self, TSFieldId id); + +/** + * Get the numerical id for the given field name string. + */ +TSFieldId ts_language_field_id_for_name(const TSLanguage *self, const char *name, uint32_t name_length); + +/** + * Check whether the given node type id belongs to named nodes, anonymous nodes, + * or a hidden nodes. + * + * See also [`ts_node_is_named`]. Hidden nodes are never returned from the API. + */ +TSSymbolType ts_language_symbol_type(const TSLanguage *self, TSSymbol symbol); + +/** + * Get the ABI version number for this language. This version number is used + * to ensure that languages were generated by a compatible version of + * Tree-sitter. + * + * See also [`ts_parser_set_language`]. + */ +uint32_t ts_language_version(const TSLanguage *self); + +/** + * Get the next parse state. Combine this with lookahead iterators to generate + * completion suggestions or valid symbols in error nodes. Use + * [`ts_node_grammar_symbol`] for valid symbols. +*/ +TSStateId ts_language_next_state(const TSLanguage *self, TSStateId state, TSSymbol symbol); + +/********************************/ +/* Section - Lookahead Iterator */ +/********************************/ + +/** + * Create a new lookahead iterator for the given language and parse state. + * + * This returns `NULL` if state is invalid for the language. + * + * Repeatedly using [`ts_lookahead_iterator_next`] and + * [`ts_lookahead_iterator_current_symbol`] will generate valid symbols in the + * given parse state. Newly created lookahead iterators will contain the `ERROR` + * symbol. + * + * Lookahead iterators can be useful to generate suggestions and improve syntax + * error diagnostics. To get symbols valid in an ERROR node, use the lookahead + * iterator on its first leaf node state. For `MISSING` nodes, a lookahead + * iterator created on the previous non-extra leaf node may be appropriate. +*/ +TSLookaheadIterator *ts_lookahead_iterator_new(const TSLanguage *self, TSStateId state); + +/** + * Delete a lookahead iterator freeing all the memory used. +*/ +void ts_lookahead_iterator_delete(TSLookaheadIterator *self); + +/** + * Reset the lookahead iterator to another state. + * + * This returns `true` if the iterator was reset to the given state and `false` + * otherwise. +*/ +bool ts_lookahead_iterator_reset_state(TSLookaheadIterator *self, TSStateId state); + +/** + * Reset the lookahead iterator. + * + * This returns `true` if the language was set successfully and `false` + * otherwise. +*/ +bool ts_lookahead_iterator_reset(TSLookaheadIterator *self, const TSLanguage *language, TSStateId state); + +/** + * Get the current language of the lookahead iterator. +*/ +const TSLanguage *ts_lookahead_iterator_language(const TSLookaheadIterator *self); + +/** + * Advance the lookahead iterator to the next symbol. + * + * This returns `true` if there is a new symbol and `false` otherwise. +*/ +bool ts_lookahead_iterator_next(TSLookaheadIterator *self); + +/** + * Get the current symbol of the lookahead iterator; +*/ +TSSymbol ts_lookahead_iterator_current_symbol(const TSLookaheadIterator *self); + +/** + * Get the current symbol type of the lookahead iterator as a null terminated + * string. +*/ +const char *ts_lookahead_iterator_current_symbol_name(const TSLookaheadIterator *self); + +/*************************************/ +/* Section - WebAssembly Integration */ +/************************************/ + +typedef struct wasm_engine_t TSWasmEngine; +typedef struct TSWasmStore TSWasmStore; + +typedef enum { + TSWasmErrorKindNone = 0, + TSWasmErrorKindParse, + TSWasmErrorKindCompile, + TSWasmErrorKindInstantiate, + TSWasmErrorKindAllocate, +} TSWasmErrorKind; + +typedef struct { + TSWasmErrorKind kind; + char *message; +} TSWasmError; + +/** + * Create a Wasm store. + */ +TSWasmStore *ts_wasm_store_new( + TSWasmEngine *engine, + TSWasmError *error +); + +/** + * Free the memory associated with the given Wasm store. + */ +void ts_wasm_store_delete(TSWasmStore *); + +/** + * Create a language from a buffer of Wasm. The resulting language behaves + * like any other Tree-sitter language, except that in order to use it with + * a parser, that parser must have a Wasm store. Note that the language + * can be used with any Wasm store, it doesn't need to be the same store that + * was used to originally load it. + */ +const TSLanguage *ts_wasm_store_load_language( + TSWasmStore *, + const char *name, + const char *wasm, + uint32_t wasm_len, + TSWasmError *error +); + +/** + * Get the number of languages instantiated in the given wasm store. + */ +size_t ts_wasm_store_language_count(const TSWasmStore *); + +/** + * Check if the language came from a Wasm module. If so, then in order to use + * this language with a Parser, that parser must have a Wasm store assigned. + */ +bool ts_language_is_wasm(const TSLanguage *); + +/** + * Assign the given Wasm store to the parser. A parser must have a Wasm store + * in order to use Wasm languages. + */ +void ts_parser_set_wasm_store(TSParser *, TSWasmStore *); + +/** + * Remove the parser's current Wasm store and return it. This returns NULL if + * the parser doesn't have a Wasm store. + */ +TSWasmStore *ts_parser_take_wasm_store(TSParser *); + +/**********************************/ +/* Section - Global Configuration */ +/**********************************/ + +/** + * Set the allocation functions used by the library. + * + * By default, Tree-sitter uses the standard libc allocation functions, + * but aborts the process when an allocation fails. This function lets + * you supply alternative allocation functions at runtime. + * + * If you pass `NULL` for any parameter, Tree-sitter will switch back to + * its default implementation of that function. + * + * If you call this function after the library has already been used, then + * you must ensure that either: + * 1. All the existing objects have been freed. + * 2. The new allocator shares its state with the old one, so it is capable + * of freeing memory that was allocated by the old allocator. + */ +void ts_set_allocator( + void *(*new_malloc)(size_t), + void *(*new_calloc)(size_t, size_t), + void *(*new_realloc)(void *, size_t), + void (*new_free)(void *) +); + +#ifdef __cplusplus +} +#endif + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC visibility pop +#endif + +#endif // TREE_SITTER_API_H_ diff --git a/examples/server/utils.hpp b/examples/server/utils.hpp index c17dbcd84..fea29c33c 100644 --- a/examples/server/utils.hpp +++ b/examples/server/utils.hpp @@ -4,6 +4,7 @@ #include "common.h" #include "json.hpp" +#include "python-parser.hpp" #include #include @@ -421,7 +422,7 @@ static std::string rubra_format_function_call_str(const std::vector & func return final_str; } -std::string default_tool_formatter(const std::vector& tools) { +static std::string default_tool_formatter(const std::vector& tools) { std::string toolText = ""; std::vector toolNames; for (const auto& tool : tools) { @@ -556,11 +557,6 @@ static json oaicompat_completion_params_parse( } -static json parse_response_for_function_call(const std::string content) { - -} - - static json format_final_response_oaicompat(const json & request, json result, const std::string & completion_id, bool streaming = false) { bool stopped_word = result.count("stopped_word") != 0; bool stopped_eos = json_value(result, "stopped_eos", false); @@ -568,6 +564,9 @@ static json format_final_response_oaicompat(const json & request, json result, c int num_prompt_tokens = json_value(result, "tokens_evaluated", 0); std::string content = json_value(result, "content", std::string("")); + std::vector parsed_content = parsePythonFunctionCalls(content); + + std::string finish_reason = "length"; if (stopped_word || stopped_eos) { finish_reason = "stop"; @@ -579,7 +578,7 @@ static json format_final_response_oaicompat(const json & request, json result, c {"delta", json::object()}}}) : json::array({json{{"finish_reason", finish_reason}, {"index", 0}, - {"message", json{{"content", content}, + {"message", json{{"content", parsed_content}, {"role", "assistant"}}}}}); std::time_t t = std::time(0); diff --git a/test_llamacpp.ipynb b/test_llamacpp.ipynb index 15781f283..5302ac8b8 100644 --- a/test_llamacpp.ipynb +++ b/test_llamacpp.ipynb @@ -29,14 +29,14 @@ }, { "cell_type": "code", - "execution_count": 161, + "execution_count": 163, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - " The current weather in Boston is 72 degrees Fahrenheit and it's raining.\n" + " <>[orderUmbrella(brand_name=\"Patagonia\")]\n" ] } ], @@ -93,14 +93,15 @@ }, { "cell_type": "code", - "execution_count": 160, + "execution_count": 177, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - " The current stock price of Tesla (TSLA) is $170 and the current stock price of Google (GOOG) is $138.\n" + " <>[get_stock_fundermentals(symbol=\"TSLA\")]\n", + "<>[get_stock_fundermentals(symbol=\"GOOG\")]\n" ] } ], @@ -109,8 +110,8 @@ "functions = [\n", " {\"function\":\n", " {\n", - " \"name\": \"get_stock_price\",\n", - " \"description\": \"Get the current stock price\",\n", + " \"name\": \"get_stock_fundermentals\",\n", + " \"description\": \"Get the stock fundermentals data\",\n", " \"parameters\": {\n", " \"type\": \"object\",\n", " \"properties\": {\n", @@ -147,14 +148,140 @@ " }}\n", "]\n", "\n", - "user_query = \"What's the stock price of Tesla and Google?\"\n", + "user_query = \"What's the stock fundementals of Tesla and google\"\n", "\n", "# \n", - "msgs = [{\"role\": \"system\", \"content\":system_prompt} ,{\"role\": \"user\", \"content\": user_query}, {\"role\": \"function\", \"content\": '<>[get_stock_price(symbol=\"TSLA\")], <>[get_stock_price(symbol=\"GOOG\")]'}, {\"role\": \"observation\", \"content\": \"<>170, 138\"}]\n", - "# msgs = [{\"role\": \"system\", \"content\":system_prompt} ,{\"role\": \"user\", \"content\": user_query},]\n", - "res = get_mistral_rubra_response(user_query, \"gorilla-openfunctions-v2\", functions=functions, msgs=msgs)\n", + "# msgs = [{\"role\": \"system\", \"content\":system_prompt} ,{\"role\": \"user\", \"content\": user_query}, {\"role\": \"function\", \"content\": '<>[get_stock_price(symbol=\"TSLA\")], <>[get_stock_price(symbol=\"GOOG\")]'}, {\"role\": \"observation\", \"content\": \"{'symbol': 'TSLA', 'company_name': 'Tesla, Inc.', 'sector': 'Consumer Cyclical', 'industry': 'Auto Manufacturers', 'market_cap': 611384164352, 'pe_ratio': 49.604652, 'pb_ratio': 9.762013, 'dividend_yield': None, 'eps': 4.3, 'beta': 2.427, '52_week_high': 299.29, '52_week_low': 152.37}}\"}]\n", + "msgs = [{\"role\": \"system\", \"content\":system_prompt} ,{\"role\": \"user\", \"content\": user_query},]\n", + "res = get_mistral_rubra_response(user_query, \"mistral_rubra\", functions=functions, msgs=msgs)\n", "print(res.message.content)" ] + }, + { + "cell_type": "code", + "execution_count": 183, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "[('get_current_weather', [], {'location': 'Boston, MA', 'api_key': 123456789, 'unit': 'fahrenheit'}), ('func', ['cde'], {'x': 1, 'b': '2', 'c': [1, 2, {'a': 1, 'b': 2}]})]\n" + ] + } + ], + "source": [ + "import ast\n", + "\n", + "input_str = \"[get_current_weather(location='Boston, MA', api_key=123456789, unit='fahrenheit'), func('cde', x=1, b='2', c=[1, 2, {'a': 1, 'b': 2}])]\"\n", + "\n", + "# Parse the string into an AST\n", + "parsed_ast = ast.parse(input_str, mode='eval')\n", + "\n", + "# Function to convert an AST node to a Python object\n", + "def ast_node_to_object(node):\n", + " if isinstance(node, ast.Constant):\n", + " return node.value\n", + " elif isinstance(node, ast.List):\n", + " return [ast_node_to_object(n) for n in node.elts]\n", + " elif isinstance(node, ast.Dict):\n", + " return {ast_node_to_object(key): ast_node_to_object(value) for key, value in zip(node.keys, node.values)}\n", + " elif isinstance(node, ast.Tuple):\n", + " return tuple(ast_node_to_object(n) for n in node.elts)\n", + " # Add more cases here as needed\n", + " return None\n", + "\n", + "def find_calls(node):\n", + " calls = []\n", + " if isinstance(node, ast.Call): # If it's a function call\n", + " calls.append(node)\n", + " for child in ast.iter_child_nodes(node):\n", + " calls.extend(find_calls(child))\n", + " return calls\n", + "\n", + "# Extract all function call nodes\n", + "calls = find_calls(parsed_ast.body)\n", + "\n", + "functions = []\n", + "for call in calls:\n", + " if isinstance(call.func, ast.Name): # Ensure it's a named function\n", + " function_name = call.func.id\n", + " args = [ast_node_to_object(arg) for arg in call.args] # Convert all positional arguments\n", + " kwargs = {kw.arg: ast_node_to_object(kw.value) for kw in call.keywords} # Convert all keyword arguments\n", + " functions.append((function_name, args, kwargs))\n", + "\n", + "print(functions)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[('get_current_weather', [], {'location': 'Boston, MA', 'api_key': 123456789, 'unit': 'fahrenheit'}), ('func', ['cde'], {'x': 1, 'b': '2', 'c': ['func_nested(1, 2)', {'a': \"func_deep('value')\"}]})]\n" + ] + } + ], + "source": [ + "import ast\n", + "\n", + "input_str = \"[get_current_weather(location='Boston, MA', api_key=123456789, unit='fahrenheit'), func('cde', x=1, b='2', c=[func_nested(1, 2), {'a': func_deep('value')}])]\"\n", + "\n", + "def ast_node_to_object(node):\n", + " if isinstance(node, ast.Constant):\n", + " return node.value\n", + " elif isinstance(node, ast.List):\n", + " return [ast_node_to_object(n) for n in node.elts]\n", + " elif isinstance(node, ast.Dict):\n", + " return {ast_node_to_object(key): ast_node_to_object(value) for key, value in zip(node.keys, node.values)}\n", + " elif isinstance(node, ast.Tuple):\n", + " return tuple(ast_node_to_object(n) for n in node.elts)\n", + " elif isinstance(node, ast.Call):\n", + " return ast.unparse(node)\n", + " # Handle function calls: convert to a representation with the function name and arguments\n", + " # func_name = ast_node_to_object(node.func) # Get the function name\n", + " # args = [ast_node_to_object(arg) for arg in node.args] # Convert all positional arguments\n", + " # kwargs = {kw.arg: ast_node_to_object(kw.value) for kw in node.keywords} # Convert all keyword arguments\n", + " # return {\"function\": func_name, \"args\": args, \"kwargs\": kwargs}\n", + " elif isinstance(node, ast.Name):\n", + " return node.id # Return the identifier name\n", + " # Add more cases here as needed\n", + " return None\n", + "\n", + "# Parse the string into an AST\n", + "parsed_ast = ast.parse(input_str, mode='eval')\n", + "\n", + "# Function to find only the top-level Call nodes\n", + "def find_top_level_calls(node):\n", + " calls = []\n", + " if isinstance(node, ast.Call): # If it's a function call\n", + " calls.append(node)\n", + " # Do not descend into child nodes to ensure we're only capturing top-level calls\n", + " return calls\n", + " for child in ast.iter_child_nodes(node):\n", + " # Recursively find calls without going into nested calls\n", + " calls.extend(find_top_level_calls(child))\n", + " return calls\n", + "\n", + "# Extract all top-level function call nodes\n", + "top_level_calls = find_top_level_calls(parsed_ast.body)\n", + "\n", + "# Process each call node to get the details you want\n", + "functions = []\n", + "for call in top_level_calls:\n", + " if isinstance(call.func, ast.Name): # Ensure it's a named function\n", + " function_name = call.func.id\n", + " args = [ast_node_to_object(arg) for arg in call.args] # Convert all positional arguments\n", + " kwargs = {kw.arg: ast_node_to_object(kw.value) for kw in call.keywords} # Convert all keyword arguments\n", + " functions.append((function_name, args, kwargs))\n", + "\n", + "print(functions)\n" + ] } ], "metadata": {