Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import tools from a langchain toolkit #2042

Open
victorserbu2709 opened this issue Nov 15, 2024 · 8 comments
Open

Import tools from a langchain toolkit #2042

victorserbu2709 opened this issue Nov 15, 2024 · 8 comments
Assignees
Labels
bug Something isn't working

Comments

@victorserbu2709
Copy link

victorserbu2709 commented Nov 15, 2024

Is your feature request related to a problem? Please describe.
I would like a simple method to import tool or tools from a langchain toolset

Describe the solution you'd like
to be able to use already defined tools from langchain toolset

Describe alternatives you've considered
i tried something similar to https://github.com/letta-ai/letta/blob/main/examples/langchain_tool_usage.py

    github_api_wrapper = GithubAPIWrapper()
    toolkit = GitHubToolkit.from_github_api_wrapper(github_api_wrapper)
    tools = toolkit.get_tools()
    for tool in tools:
        print(tool.name)

    tool = tools[0]
    wikipedia_query_tool = client.load_langchain_tool(
        tool, additional_imports_module_attr_map={"langchain_community.utilities.github":"GitHubAPIWrapper"}
    )

but it doesnt work

Additional context
Add any other context or screenshots about the feature request here.

@sarahwooders
Copy link
Collaborator

Can you share the error you're getting, or describe how the tool doesn't work?

@victorserbu2709
Copy link
Author

sorry for the incomplete report.
this is the error i get

2024-11-15 19:42:03,047 [embedchain] [INFO] Swapped std-lib sqlite3 with pysqlite3 for ChromaDb compatibility. Your original version was 3.34.1.
[WARNING] Skipping parsing unknown class ModelMetaclass (does not inherit from the Pydantic BaseModel and is not a basic Python type)
[WARNING] Skipping parsing unknown class Github (does not inherit from the Pydantic BaseModel and is not a basic Python type)
[WARNING] Skipping parsing unknown class Repository (does not inherit from the Pydantic BaseModel and is not a basic Python type)
Traceback (most recent call last):
  File "/root/stash/git/letta/letta/functions/functions.py", line 28, in derive_openai_json_schema
    json_schema = generate_schema(func, name=name)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/stash/git/letta/letta/functions/schema_generator.py", line 101, in generate_schema
    raise TypeError(f"Parameter '{param.name}' in function '{function.__name__}' lacks a type annotation")
TypeError: Parameter 'kwargs' in function 'git_hub_action' lacks a type annotation

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/root/stash/git/letta/examples/langchain_github_tool_usage.py", line 99, in <module>
    main()
  File "/root/stash/git/letta/examples/langchain_github_tool_usage.py", line 54, in main
    github_query_tool = client.load_langchain_tool(
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/stash/git/letta/letta/client/client.py", line 2291, in load_langchain_tool
    return self.server.tool_manager.create_or_update_tool(pydantic_tool=Tool(**tool_create.model_dump()), actor=self.user)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/stash/git/letta/letta/utils.py", line 542, in wrapper
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/root/stash/git/letta/letta/services/tool_manager.py", line 52, in create_or_update_tool
    self.update_tool_by_id(tool.id, ToolUpdate(**update_data), actor)
  File "/root/stash/git/letta/letta/utils.py", line 542, in wrapper
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/root/stash/git/letta/letta/services/tool_manager.py", line 122, in update_tool_by_id
    new_schema = derive_openai_json_schema(source_code=pydantic_tool.source_code)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/stash/git/letta/letta/functions/functions.py", line 31, in derive_openai_json_schema
    raise RuntimeError(f"Failed to execute source code: {e}")
RuntimeError: Failed to execute source code: Parameter 'kwargs' in function 'git_hub_action' lacks a type annotation

@sarahwooders sarahwooders added the bug Something isn't working label Nov 15, 2024
@sarahwooders sarahwooders self-assigned this Nov 15, 2024
@mattzh72
Copy link
Collaborator

Hey! So LangChain tools are not very well-maintained by LangChain themselves - would you be able to use a Composio tool instead?

@victorserbu2709
Copy link
Author

Hey! I cannot use Composio tool because I have a self-hosted github. I thought that I would be able to reuse github langchain tools by extending GitHubAPIWrapper to be able to connect to selfhosted github. I will try to find workarounds,
Thank you.

@mattzh72
Copy link
Collaborator

mattzh72 commented Nov 18, 2024

@victorserbu2709 we are coming out with a tools sandbox feature soon (sometime next week), I can write up a demo covering your use case.

@mattzh72
Copy link
Collaborator

We just merged in the tools sandbox feature, but have not publicized this widely yet (still working on docs). Can you please share details about this tool you're trying to add? I will try to recreate it on my side for you and explain the process. Will also help with debugging our code.

@victorserbu2709
Copy link
Author

Hello.
this is a simple example that shows how could I use a langchain tool with a self hosted github instance. I created a new GithubApiWrapper class mainly to be able to specify github base url

class GithubAPIWrapperFpsa(GitHubAPIWrapper):
    """Wrapper for GitHub API."""

    github: Any  #: :meta private:
    github_repo_instance: Any  #: :meta private:
    github_repository: Optional[str] = None
    github_app_id: Optional[str] = None
    github_app_private_key: Optional[str] = None
    github_base_url: Optional[str] = None
    active_branch: Optional[str] = None
    github_base_branch: Optional[str] = None
    github_token_pat: Optional[str] = None

    class Config:
        extra = "forbid"

    @root_validator(pre=True)
    def validate_environment(cls, values: Dict) -> Dict:
        """Validate that api key and python package exists in environment."""
        github_token_pat = get_from_dict_or_env(
            values, "github_token", "GITHUB_TOKEN_PAT"
        )
        github_repository = get_from_dict_or_env(
            values, "github_repository", "GITHUB_REPOSITORY"
        )

        github_base_url = get_from_dict_or_env(
            values, "github_base_url", "GITHUB_BASE_URL"
        )
        # using an access token
        auth = Auth.Token(github_token_pat)
        g = Github(base_url=github_base_url, auth=auth)

        repo = g.get_repo(github_repository)

        github_base_branch = get_from_dict_or_env(
            values,
            "github_base_branch",
            "GITHUB_BASE_BRANCH",
            default=repo.default_branch,
        )

        active_branch = get_from_dict_or_env(
            values,
            "active_branch",
            "ACTIVE_BRANCH",
            default=repo.default_branch,
        )

        values["github"] = g
        values["github_repo_instance"] = repo
        values["github_repository"] = github_repository
        values["active_branch"] = active_branch
        values["github_base_branch"] = github_base_branch

        return values

def test():
    github_api_wrapper = GithubAPIWrapperFpsa()
    toolkit = GitHubToolkit.from_github_api_wrapper(github_api_wrapper)
    
    tools = [tool for tool in toolkit.get_tools() if tool.name == "Get Issue"]
    print(tools[0].args)
    result = tools[0].run({"issue_number":3})
    print(result)
{'issue_number': {'title': 'Issue Number', 'description': 'Issue number as an integer, e.g. `42`', 'default': 0, 'type': 'integer'}}
{"number": 3, "title": "Testing agent", "body": "Just testing agent", "comments": "[{'body': 'Comment2', 'user': 'victors'}, {'body': 'Comment3', 'user': 'victors'}]", "opened_by": "victors"}

To run this i have to export following env variables

export GITHUB_BASE_URL="https://github.local/api/v3"
export GITHUB_REPOSITORY="Org/repo"
export GITHUB_TOKEN_PAT="github_pat_XYZ"

it would be nice that example showw how can this tool could be used within letta agent
Thanks

@mattzh72
Copy link
Collaborator

mattzh72 commented Nov 27, 2024

Okay, I understand better - a couple notes here:

  • Letta expects the tools to be single Python functions (for now). That means if you have to wrap this whole thing into one function that we then provide to the agent.
  • You need to have a detailed docstring, and everything needs to be strongly typed so we can populate the correct json schema to provide to the AI provider

I think if you do these two things, you could get this tool to work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants