.gitignore CHANGED
@@ -2,6 +2,5 @@
2
  .env
3
  __pycache__/
4
  /venv/
5
- langchain-asi-main/
6
- langchain-asi/
7
  *.json
 
2
  .env
3
  __pycache__/
4
  /venv/
5
+
 
6
  *.json
langchain-asi/.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ .env
2
+ asi-env
langchain-asi/LICENSE ADDED
File without changes
langchain-asi/README.md ADDED
@@ -0,0 +1,262 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # langchain-asi
2
+ # LangChain ASI1 Integration
3
+
4
+ A lightweight, easy-to-use integration package that connects ASI1's API with the LangChain ecosystem.
5
+
6
+ ## Overview
7
+
8
+ This package provides seamless integration between ASI1's API and LangChain, allowing you to use ASI1's language models with LangChain's frameworks, agents, and tools. The integration is designed to be a drop-in replacement for other LLM providers like OpenAI and Anthropic, taking advantage of ASI1's OpenAI-compatible API.
9
+
10
+ ## Features
11
+
12
+ - **Simple Integration**: Easily swap ASI1 models into your existing LangChain applications
13
+ - **Conversation Support**: Full support for multi-turn conversations with memory
14
+ - **System Instructions**: Control model behavior with system messages
15
+ - **Agent Support**: Create LangChain agents powered by ASI1 models
16
+ - **Tool Integration**: Connect ASI1 models with LangChain tools and utilities
17
+ - **Parameter Control**: Customize temperature, max tokens, and other model parameters
18
+ - **Error Handling**: Robust error handling for API communication
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ # From source
24
+ git clone https://github.com/yourusername/langchain-asi.git
25
+ cd langchain-asi
26
+ pip install -e .
27
+
28
+ # Or when published on PyPI
29
+ pip install langchain-asi
30
+ ```
31
+ ## Quick Start
32
+
33
+ ### Basic Usage
34
+
35
+ ```python
36
+ from langchain_asi import ASI1ChatModel
37
+ from dotenv import load_dotenv
38
+
39
+ # Load API key from .env file (recommended)
40
+ load_dotenv()
41
+
42
+ # Initialize the model
43
+ llm = ASI1ChatModel()
44
+
45
+ # Simple query
46
+ response = llm.invoke("What are the three laws of robotics?")
47
+ print(response.content)
48
+ ```
49
+
50
+ ### Conversation with System Message
51
+
52
+ ```python
53
+ from langchain_asi import ASI1ChatModel
54
+ from langchain.schema import HumanMessage, SystemMessage, AIMessage
55
+
56
+ # Initialize with custom parameters
57
+ llm = ASI1ChatModel(
58
+ model_name="asi1-mini",
59
+ temperature=0.3,
60
+ max_tokens=2000
61
+ )
62
+
63
+ # Create a conversation with a system message
64
+ messages = [
65
+ SystemMessage(content="You are a helpful assistant that always responds in rhymes."),
66
+ HumanMessage(content="Tell me about artificial intelligence.")
67
+ ]
68
+
69
+ response = llm.invoke(messages)
70
+ print(response.content)
71
+
72
+ # Continue the conversation
73
+ messages.append(response)
74
+ messages.append(HumanMessage(content="What are its potential risks?"))
75
+ response = llm.invoke(messages)
76
+ print(response.content)
77
+ ```
78
+ ## Working with LangChain Chains
79
+
80
+ ```python
81
+ from langchain_asi import ASI1ChatModel
82
+ from langchain.chains import LLMChain
83
+ from langchain.prompts import PromptTemplate
84
+
85
+ # Initialize the model
86
+ llm = ASI1ChatModel()
87
+
88
+ # Create a simple prompt template
89
+ template = "Write a short {style} poem about {topic}."
90
+ prompt = PromptTemplate(template=template, input_variables=["style", "topic"])
91
+
92
+ # Create a chain
93
+ chain = LLMChain(llm=llm, prompt=prompt)
94
+
95
+ # Run the chain
96
+ result = chain.run(style="haiku", topic="artificial intelligence")
97
+ print(result)
98
+ ```
99
+
100
+ ## Creating Agents
101
+
102
+ ### Simple Agent with Tools
103
+
104
+ ```python
105
+ from langchain_asi import ASI1ChatModel, create_asi_agent
106
+ from langchain.tools import BaseTool
107
+ from typing import List
108
+
109
+ # Define a calculator tool
110
+ class Calculator(BaseTool):
111
+ name: str = "calculator"
112
+ description: str = "Useful for performing mathematical calculations"
113
+
114
+ def _run(self, query: str) -> str:
115
+ try:
116
+ return str(eval(query))
117
+ except Exception as e:
118
+ return f"Error: {str(e)}"
119
+
120
+ def _arun(self, query: str):
121
+ raise NotImplementedError("This tool does not support async")
122
+
123
+ # Create a list of tools
124
+ tools = [Calculator()]
125
+
126
+ # Create an agent using the utility function
127
+ agent = create_asi_agent(
128
+ tools=tools,
129
+ system_prompt="You are a helpful assistant that's good at math.",
130
+ temperature=0.2
131
+ )
132
+
133
+ # Use the agent
134
+ result = agent.run("If I have 25 apples and give 7 to my friend, then eat 3 myself, how many do I have left?")
135
+ print(result)
136
+ ```
137
+
138
+ ## API Configuration
139
+
140
+ ### Environment Variables
141
+
142
+ The recommended way to set your ASI1 API key is via environment variables:
143
+
144
+ ```bash
145
+ export ASI1_API_KEY=your_api_key_here
146
+ ```
147
+
148
+ Or in your Python code:
149
+
150
+ ```python
151
+ import os
152
+ os.environ["ASI1_API_KEY"] = "your_api_key_here"
153
+ ```
154
+
155
+ ### Using .env Files
156
+
157
+ For development, you can store your API key in a `.env` file:
158
+
159
+ ```
160
+ ASI1_API_KEY=your_api_key_here
161
+ ```
162
+
163
+ Then load it with:
164
+
165
+ ```python
166
+ from dotenv import load_dotenv
167
+ load_dotenv()
168
+ ```
169
+
170
+ ### Direct Parameter
171
+
172
+ You can also pass the API key directly when initializing the model:
173
+
174
+ ```python
175
+ llm = ASI1ChatModel(api_key="your_api_key_here")
176
+ ```
177
+
178
+ ## Advanced Configuration
179
+
180
+ ### Custom API Base URL
181
+
182
+ If you need to use a different API endpoint:
183
+
184
+ ```python
185
+ llm = ASI1ChatModel(
186
+ api_base="https://your-custom-endpoint.com/v1"
187
+ )
188
+ ```
189
+
190
+ ### Model Parameters
191
+
192
+ Configure various model parameters:
193
+
194
+ ```python
195
+ llm = ASI1ChatModel(
196
+ model_name="asi1-mini", # Model name
197
+ temperature=0.7, # Randomness (0-1)
198
+ max_tokens=8000 # Maximum response length
199
+ )
200
+ ```
201
+
202
+ ## Integration with LangGraph
203
+
204
+ For more complex agent workflows, you can integrate ASI1 models with LangGraph:
205
+
206
+ ```python
207
+ from langgraph.prebuilt import create_react_agent
208
+ from langgraph.checkpoint.memory import MemorySaver
209
+ from langchain_asi import ASI1ChatModel
210
+ from langchain_core.tools import tool
211
+
212
+ # Define a tool
213
+ @tool
214
+ def search(query: str):
215
+ """Search for information."""
216
+ if "weather" in query.lower():
217
+ return "It's currently sunny and 22°C."
218
+ return "No specific information found."
219
+
220
+ # Initialize the ASI1 model
221
+ model = ASI1ChatModel(temperature=0)
222
+
223
+ # Initialize memory
224
+ checkpointer = MemorySaver()
225
+
226
+ # Create a LangGraph agent
227
+ app = create_react_agent(model, [search], checkpointer=checkpointer)
228
+
229
+ # Use the agent
230
+ result = app.invoke(
231
+ {"messages": [{"role": "user", "content": "What's the weather today?"}]},
232
+ config={"configurable": {"thread_id": "unique-thread-id"}}
233
+ )
234
+
235
+ # Get the final response
236
+ print(result["messages"][-1].content)
237
+ ```
238
+
239
+ ## Limitations
240
+
241
+ - The current implementation does not support native function calling (available in some other LLMs)
242
+ - Streaming responses are not yet implemented
243
+ - Some advanced LangChain features may require additional configuration
244
+
245
+ ## Troubleshooting
246
+
247
+ ### API Key Issues
248
+
249
+ If you encounter authentication errors, check that your API key is:
250
+ - Correctly set in your environment or passed to the model
251
+ - Valid and active in your ASI1 account
252
+
253
+ ### Agent Parsing Errors
254
+
255
+ When using agents, you may see parsing errors. These can often be resolved by:
256
+ - Setting `handle_parsing_errors=True` when creating the agent
257
+ - Using the `ZERO_SHOT_REACT_DESCRIPTION` agent type which is more forgiving
258
+
259
+ ## Contributing
260
+
261
+ Contributions are welcome! Please feel free to submit a Pull Request.
262
+
langchain-asi/examples/test_agent.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # test_agent.py
2
+ from dotenv import load_dotenv
3
+ load_dotenv()
4
+
5
+ from langchain_asi import ASI1ChatModel
6
+ from langchain.agents import AgentType, initialize_agent
7
+ from langchain.tools import BaseTool
8
+ from typing import List
9
+
10
+ from typing import Optional, Type
11
+ from langchain_asi import ASI1ChatModel
12
+ from langchain.agents import AgentType, initialize_agent
13
+ from langchain.tools import BaseTool
14
+ from typing import List
15
+
16
+ # Update the Calculator class with type annotations
17
+ class Calculator(BaseTool):
18
+ name: str = "calculator" # Add type annotation here
19
+ description: str = "Useful for when you need to calculate mathematical expressions"
20
+
21
+ def _run(self, query: str) -> str:
22
+ try:
23
+ return str(eval(query))
24
+ except Exception as e:
25
+ return f"Error: {str(e)}"
26
+
27
+ def _arun(self, query: str):
28
+ raise NotImplementedError("This tool does not support async")
29
+
30
+ # Do the same for WeatherTool
31
+ class WeatherTool(BaseTool):
32
+ name: str = "weather" # Add type annotation here
33
+ description: str = "Get the weather for a specific location"
34
+
35
+ def _run(self, location: str) -> str:
36
+ # This is a mock implementation
37
+ location = location.lower()
38
+ if "london" in location:
39
+ return "It's rainy and 15°C in London."
40
+ elif "new york" in location or "nyc" in location:
41
+ return "It's sunny and 22°C in New York."
42
+ elif "tokyo" in location:
43
+ return "It's cloudy and 20°C in Tokyo."
44
+ else:
45
+ return f"The weather in {location} is currently unavailable."
46
+
47
+ def _arun(self, location: str):
48
+ raise NotImplementedError("This tool does not support async")
49
+
50
+ # Create a list of tools
51
+ tools: List[BaseTool] = [Calculator(), WeatherTool()]
52
+
53
+ # Initialize the ASI1 model
54
+ llm = ASI1ChatModel(temperature=0)
55
+
56
+ # Use your utility function:
57
+ from langchain_asi.utils import create_asi_agent
58
+
59
+ # Create the agent with a different agent type
60
+ agent = initialize_agent(
61
+ tools,
62
+ llm,
63
+ agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION, # Try this instead
64
+ verbose=True,
65
+ handle_parsing_errors=True,
66
+ max_iterations=5 # Add this to prevent infinite loops
67
+ )
68
+
69
+ # Test the agent with different queries
70
+ test_queries = [
71
+ "What is 25 * 63?",
72
+ "What's the weather like in London?",
73
+ "If it's 22°C in New York, what is that in Fahrenheit?"
74
+ ]
75
+
76
+ for query in test_queries:
77
+ print("\n" + "="*50)
78
+ print(f"Query: {query}")
79
+ print("="*50)
80
+ try:
81
+ response = agent.invoke(query)
82
+ print(f"Response: {response}")
83
+ except Exception as e:
84
+ print(f"Error: {str(e)}")
langchain-asi/examples/test_example1.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # test_examples.py
2
+ from dotenv import load_dotenv
3
+ load_dotenv()
4
+
5
+ from langchain_asi import ASI1ChatModel
6
+ from langchain.schema import HumanMessage, SystemMessage, AIMessage
7
+
8
+ # Initialize the model
9
+ llm = ASI1ChatModel()
10
+
11
+ print("="*50)
12
+ print("Example 1: Basic Chat Completion")
13
+ print("="*50)
14
+ response = llm.invoke("Explain what quantum computing is in one sentence.")
15
+ print(f"Response: {response.content}")
16
+
17
+ print("\n"+"="*50)
18
+ print("Example 2: Using System Messages")
19
+ print("="*50)
20
+ messages = [
21
+ SystemMessage(content="You are a helpful assistant that always responds in rhymes."),
22
+ HumanMessage(content="Tell me about artificial intelligence.")
23
+ ]
24
+ response = llm.invoke(messages)
25
+ print(f"Response: {response.content}")
26
+
27
+ print("\n"+"="*50)
28
+ print("Example 3: Multi-turn Conversation")
29
+ print("="*50)
30
+ messages = [
31
+ SystemMessage(content="You are a helpful assistant."),
32
+ HumanMessage(content="My name is Alex."),
33
+ AIMessage(content="Hello Alex! It's nice to meet you. How can I help you today?"),
34
+ HumanMessage(content="What's my name?")
35
+ ]
36
+ response = llm.invoke(messages)
37
+ print(f"Response: {response.content}")
langchain-asi/examples/test_langgraph.py ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # test_langgraph.py
2
+ from dotenv import load_dotenv
3
+ load_dotenv()
4
+
5
+ import os
6
+ from langgraph.prebuilt import create_react_agent
7
+ from langgraph.checkpoint.memory import MemorySaver
8
+ from langchain_core.tools import tool
9
+ from langchain_asi import ASI1ChatModel
10
+
11
+ # Define a simple search tool
12
+ @tool
13
+ def search(query: str):
14
+ """Call to search for information."""
15
+ # This is a mock implementation
16
+ if "weather" in query.lower():
17
+ return "It's currently sunny and 22°C."
18
+ elif "population" in query.lower():
19
+ return "The population is approximately 8.8 million people."
20
+ elif "capital" in query.lower():
21
+ return "The capital of France is Paris."
22
+ else:
23
+ return "No specific information found for this query."
24
+
25
+ # Define a simple calculator tool
26
+ @tool
27
+ def calculator(expression: str):
28
+ """Calculate a mathematical expression."""
29
+ try:
30
+ return str(eval(expression))
31
+ except Exception as e:
32
+ return f"Error in calculation: {str(e)}"
33
+
34
+ # List of tools
35
+ tools = [search, calculator]
36
+
37
+ # Initialize the ASI1 model
38
+ model = ASI1ChatModel(
39
+ model_name="asi1-mini",
40
+ temperature=0, # Lower temperature for more deterministic responses
41
+ max_tokens=4000
42
+ )
43
+
44
+ # Initialize memory to persist state between graph runs
45
+ checkpointer = MemorySaver()
46
+
47
+ # Create the agent
48
+ print("Creating LangGraph ReAct agent with ASI1...")
49
+ app = create_react_agent(model, tools, checkpointer=checkpointer)
50
+
51
+ # Test queries
52
+ test_queries = [
53
+ "What is the capital of France?",
54
+ "What is 42 * 18?",
55
+ "What's the weather like today?"
56
+ ]
57
+
58
+ # Run the tests
59
+ for i, query in enumerate(test_queries):
60
+ print(f"\n{'='*50}")
61
+ print(f"Test {i+1}: {query}")
62
+ print(f"{'='*50}")
63
+
64
+ try:
65
+ # Create a unique thread ID for each conversation
66
+ thread_id = f"test-thread-{i}"
67
+
68
+ # Invoke the agent
69
+ final_state = app.invoke(
70
+ {"messages": [{"role": "user", "content": query}]},
71
+ config={"configurable": {"thread_id": thread_id}}
72
+ )
73
+
74
+ # Print the final response
75
+ print("\nFinal Response:")
76
+ print(final_state["messages"][-1].content)
77
+
78
+ except Exception as e:
79
+ print(f"Error: {str(e)}")
langchain-asi/examples/test_langgraph_weather.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #In place of anthropic, ASI model can be used
2
+ from dotenv import load_dotenv
3
+ load_dotenv() # Load environment variables from .env file
4
+
5
+ from langgraph.prebuilt import create_react_agent
6
+ from langgraph.checkpoint.memory import MemorySaver
7
+ from langchain_asi import ASI1ChatModel # Your custom ASI1 integration
8
+ from langchain_core.tools import tool
9
+
10
+ # Define the tools for the agent to use
11
+ @tool
12
+ def search(query: str):
13
+ """Call to surf the web."""
14
+ # This is a placeholder implementation
15
+ if "sf" in query.lower() or "san francisco" in query.lower():
16
+ return "It's 60 degrees and foggy."
17
+ return "It's 90 degrees and sunny."
18
+
19
+ # Create the list of tools
20
+ tools = [search]
21
+
22
+ # Initialize the ASI1 model
23
+ model = ASI1ChatModel(model_name="asi1-mini", temperature=0)
24
+
25
+ # Initialize memory to persist state between graph runs
26
+ checkpointer = MemorySaver()
27
+
28
+ # Create the ReAct agent
29
+ app = create_react_agent(model, tools, checkpointer=checkpointer)
30
+
31
+ # Use the agent to answer a weather question
32
+ final_state = app.invoke(
33
+ {"messages": [{"role": "user", "content": "what is the weather in sf"}]},
34
+ config={"configurable": {"thread_id": 42}}
35
+ )
36
+
37
+ # Print the final response
38
+ print(final_state["messages"][-1].content)
langchain-asi/import_test.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ # import_test.py
2
+ try:
3
+ import langchain_asi
4
+ print(f"Successfully imported langchain_asi from {langchain_asi.__file__}")
5
+ from langchain_asi import ASI1ChatModel
6
+ print("Successfully imported ASI1ChatModel")
7
+ except ImportError as e:
8
+ print(f"Import error: {e}")
langchain-asi/langchain_asi.egg-info/PKG-INFO ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.4
2
+ Name: langchain-asi
3
+ Version: 0.1.0
4
+ Summary: LangChain integration for ASI1 API
5
+ Author: Rajashekar Vennavelli
6
+ Author-email: rajashekarvennavelli@gmail.com
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.8
12
+ Classifier: Programming Language :: Python :: 3.9
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Requires-Python: >=3.8
15
+ License-File: LICENSE
16
+ Requires-Dist: langchain>=0.0.267
17
+ Requires-Dist: requests>=2.28.0
18
+ Dynamic: author
19
+ Dynamic: author-email
20
+ Dynamic: classifier
21
+ Dynamic: license-file
22
+ Dynamic: requires-dist
23
+ Dynamic: requires-python
24
+ Dynamic: summary
langchain-asi/langchain_asi.egg-info/SOURCES.txt ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ LICENSE
2
+ README.md
3
+ setup.py
4
+ langchain_asi/__init__.py
5
+ langchain_asi/chat_models.py
6
+ langchain_asi/utils.py
7
+ langchain_asi.egg-info/PKG-INFO
8
+ langchain_asi.egg-info/SOURCES.txt
9
+ langchain_asi.egg-info/dependency_links.txt
10
+ langchain_asi.egg-info/requires.txt
11
+ langchain_asi.egg-info/top_level.txt
12
+ tests/test_agent.py
13
+ tests/test_chat_model.py
14
+ tests/test_integration.py
15
+ tests/test_simple.py
langchain-asi/langchain_asi.egg-info/dependency_links.txt ADDED
@@ -0,0 +1 @@
 
 
1
+
langchain-asi/langchain_asi.egg-info/requires.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ langchain>=0.0.267
2
+ requests>=2.28.0
langchain-asi/langchain_asi.egg-info/top_level.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ langchain_asi
langchain-asi/langchain_asi/__init__.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ from langchain_asi.chat_models import ASI1ChatModel
2
+ from langchain_asi.utils import create_asi_agent
3
+
4
+ __all__ = ["ASI1ChatModel", "create_asi_agent"]
langchain-asi/langchain_asi/chat_models.py ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain.chat_models.base import BaseChatModel
2
+ from langchain.schema import AIMessage, HumanMessage, SystemMessage
3
+ from langchain_core.outputs import ChatGeneration, ChatResult
4
+ import requests
5
+ import os
6
+ from typing import List, Dict, Any, Optional, Union, Tuple
7
+
8
+ class ASI1ChatModel(BaseChatModel):
9
+ """LangChain integration for ASI1 API chat models."""
10
+
11
+ model_name: str = "asi1-mini"
12
+ temperature: float = 0.7
13
+ max_tokens: int = 4000
14
+ api_key: Optional[str] = None
15
+ api_base: str = "https://api.asi1.ai/v1"
16
+
17
+ def __init__(self, **kwargs):
18
+ super().__init__(**kwargs)
19
+ # Get API key from environment or constructor
20
+ self.api_key = kwargs.get("api_key", os.environ.get("ASI1_API_KEY"))
21
+ if not self.api_key:
22
+ raise ValueError("ASI1_API_KEY must be provided as an argument or environment variable")
23
+
24
+ # Override default params if provided
25
+ for param in ["model_name", "temperature", "max_tokens", "api_base"]:
26
+ if param in kwargs:
27
+ setattr(self, param, kwargs[param])
28
+
29
+ def _generate(self, messages: List, stop: Optional[List[str]] = None,
30
+ **kwargs) -> ChatResult:
31
+ """Generate a completion using the ASI1 API."""
32
+
33
+ # Convert LangChain message format to ASI1 format
34
+ asi_messages = []
35
+ for message in messages:
36
+ if isinstance(message, SystemMessage):
37
+ asi_messages.append({"role": "system", "content": message.content})
38
+ elif isinstance(message, HumanMessage):
39
+ asi_messages.append({"role": "user", "content": message.content})
40
+ elif isinstance(message, AIMessage):
41
+ asi_messages.append({"role": "assistant", "content": message.content})
42
+ elif hasattr(message, "content"):
43
+ # If it's a string, treat it as a user message
44
+ asi_messages.append({"role": "user", "content": str(message.content)})
45
+ else:
46
+ # If it's a string, treat it as a user message
47
+ asi_messages.append({"role": "user", "content": str(message)})
48
+
49
+ # Prepare the request payload
50
+ payload = {
51
+ "model": self.model_name,
52
+ "messages": asi_messages,
53
+ "temperature": self.temperature,
54
+ "max_tokens": self.max_tokens
55
+ }
56
+
57
+ # Add stop sequences if provided
58
+ if stop:
59
+ payload["stop"] = stop
60
+
61
+ # Make the API request
62
+ headers = {
63
+ "Content-Type": "application/json",
64
+ "Authorization": f"Bearer {self.api_key}"
65
+ }
66
+
67
+ response = requests.post(
68
+ f"{self.api_base}/chat/completions",
69
+ headers=headers,
70
+ json=payload
71
+ )
72
+
73
+ # Parse the response
74
+ if response.status_code != 200:
75
+ raise Exception(f"API request failed: {response.text}")
76
+
77
+ result = response.json()
78
+ content = result["choices"][0]["message"]["content"]
79
+
80
+ # Create an AIMessage
81
+ message = AIMessage(content=content)
82
+
83
+ # Create a ChatGeneration with the message
84
+ generation = ChatGeneration(message=message)
85
+
86
+ # Create and return a ChatResult
87
+ chat_result = ChatResult(generations=[generation])
88
+
89
+ # Add token usage if available
90
+ if "usage" in result:
91
+ chat_result.llm_output = {
92
+ "token_usage": result["usage"],
93
+ "model_name": self.model_name
94
+ }
95
+
96
+ return chat_result
97
+
98
+ def _llm_type(self) -> str:
99
+ """Return type of LLM."""
100
+ return "asi1"
101
+
102
+ def bind_tools(self, tools):
103
+ """Bind tools to the model.
104
+
105
+ Args:
106
+ tools: List of tools to bind to the model
107
+
108
+ Returns:
109
+ A new instance of the model with the tools bound
110
+ """
111
+ # For models that don't natively support tool binding,
112
+ # we just return the model itself
113
+ return self
langchain-asi/langchain_asi/utils.py ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain.agents import initialize_agent, AgentType
2
+ from langchain.tools.base import BaseTool
3
+ from typing import List, Optional
4
+ from langchain_asi.chat_models import ASI1ChatModel
5
+
6
+ def create_asi_agent(tools: List[BaseTool],
7
+ system_prompt: Optional[str] = None,
8
+ model_name: str = "asi1-mini",
9
+ temperature: float = 0.7,
10
+ max_tokens: int = 4000,
11
+ api_key: Optional[str] = None,
12
+ api_base: Optional[str] = None,
13
+ agent_type: AgentType = AgentType.OPENAI_FUNCTIONS,
14
+ handle_parsing_errors: bool = True):
15
+ """Create a LangChain agent using ASI1."""
16
+
17
+ # Create ASI1 model
18
+ llm_kwargs = {
19
+ "model_name": model_name,
20
+ "temperature": temperature,
21
+ "max_tokens": max_tokens
22
+ }
23
+ if api_key:
24
+ llm_kwargs["api_key"] = api_key
25
+ if api_base:
26
+ llm_kwargs["api_base"] = api_base
27
+
28
+ llm = ASI1ChatModel(**llm_kwargs)
29
+
30
+ # Create and return agent
31
+ if system_prompt:
32
+ agent_kwargs = {"system_message": system_prompt}
33
+ else:
34
+ agent_kwargs = {}
35
+
36
+ return initialize_agent(
37
+ tools=tools,
38
+ llm=llm,
39
+ agent=agent_type,
40
+ agent_kwargs=agent_kwargs,
41
+ verbose=True,
42
+ handle_parsing_errors=handle_parsing_errors
43
+ )
langchain-asi/requirements.txt ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Core dependencies
2
+ langchain>=0.0.267
3
+ requests>=2.28.0
4
+
5
+ # Testing
6
+ pytest>=7.0.0
7
+ python-dotenv>=1.0.0
8
+
9
+ # Development
10
+ black>=23.0.0
11
+ isort>=5.12.0
12
+ mypy>=1.0.0
13
+ build>=0.10.0
14
+ twine>=4.0.0
15
+
16
+ # Example dependencies
17
+ langgraph>=0.0.15
18
+ langgraph-prebuilt>=0.0.5
langchain-asi/setup.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # setup.py
2
+ from setuptools import setup, find_packages
3
+
4
+ setup(
5
+ name="langchain-asi",
6
+ version="0.1.0",
7
+ description="LangChain integration for ASI1 API",
8
+ author="Rajashekar Vennavelli",
9
+ author_email="rajashekarvennavelli@gmail.com",
10
+ packages=find_packages(),
11
+ install_requires=[
12
+ "langchain>=0.0.267",
13
+ "requests>=2.28.0"
14
+ ],
15
+ classifiers=[
16
+ "Development Status :: 3 - Alpha",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.8",
21
+ "Programming Language :: Python :: 3.9",
22
+ "Programming Language :: Python :: 3.10",
23
+ ],
24
+ python_requires=">=3.8",
25
+ )
langchain-asi/tests/conftest.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # tests/conftest.py
2
+ import os
3
+ import pytest
4
+ from dotenv import load_dotenv
5
+
6
+ # tests/conftest.py
7
+ import sys
8
+ import os
9
+ from pathlib import Path
10
+
11
+ # Add the project root directory to sys.path
12
+ project_root = Path(__file__).parent.parent
13
+ sys.path.insert(0, str(project_root))
14
+
15
+ print(f"Added {project_root} to sys.path")
16
+ print(f"sys.path is now: {sys.path}")
langchain-asi/tests/test_agent.py ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # tests/test_agent.py
2
+ import os
3
+ import pytest
4
+ from langchain_asi import ASI1ChatModel
5
+ from langchain_asi.utils import create_asi_agent
6
+ from langchain.tools import BaseTool
7
+
8
+ # Skip tests if no API key is available
9
+ requires_api_key = pytest.mark.skipif(
10
+ not os.environ.get("ASI1_API_KEY"),
11
+ reason="ASI1_API_KEY environment variable not set"
12
+ )
13
+
14
+ class TestAgentIntegration:
15
+
16
+ def setup_method(self):
17
+ """Set up the test fixture."""
18
+ self.model = ASI1ChatModel()
19
+
20
+ # Define a simple calculator tool
21
+ class Calculator(BaseTool):
22
+ name: str = "calculator"
23
+ description: str = "Useful for math calculations"
24
+
25
+ def _run(self, query: str) -> str:
26
+ try:
27
+ return str(eval(query))
28
+ except Exception as e:
29
+ return f"Error: {str(e)}"
30
+
31
+ def _arun(self, query: str):
32
+ raise NotImplementedError("Async not supported")
33
+
34
+ self.tools = [Calculator()]
35
+
36
+ @requires_api_key
37
+ def test_create_agent(self):
38
+ """Test creating an agent with tools."""
39
+ agent = create_asi_agent(
40
+ tools=self.tools,
41
+ system_prompt="You are a helpful assistant."
42
+ )
43
+ assert agent is not None
44
+
45
+ @requires_api_key
46
+ def test_agent_calculation(self):
47
+ """Test that the agent can use tools to solve problems."""
48
+ agent = create_asi_agent(
49
+ tools=self.tools,
50
+ system_prompt="You are a helpful assistant.",
51
+ handle_parsing_errors=True
52
+ )
53
+ response = agent.invoke("What is 25 * 42?")
54
+
55
+ # Check if '1050' is in the output field of the response
56
+ assert "1050" in response['output']
langchain-asi/tests/test_chat_model.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # tests/test_chat_model.py
2
+ import os
3
+ import pytest
4
+ from langchain_asi import ASI1ChatModel
5
+ from langchain.schema import HumanMessage, SystemMessage, AIMessage
6
+
7
+ # Skip tests if no API key is available
8
+ requires_api_key = pytest.mark.skipif(
9
+ not os.environ.get("ASI1_API_KEY"),
10
+ reason="ASI1_API_KEY environment variable not set"
11
+ )
12
+
13
+ class TestASI1ChatModel:
14
+
15
+ def setup_method(self):
16
+ """Set up the test fixture."""
17
+ self.model = ASI1ChatModel()
18
+
19
+ @requires_api_key
20
+ def test_initialization(self):
21
+ """Test model initialization with different parameters."""
22
+ # Default initialization
23
+ model1 = ASI1ChatModel()
24
+ assert model1.model_name == "asi1-mini"
25
+ assert model1.temperature == 0.7
26
+
27
+ # Custom parameters
28
+ model2 = ASI1ChatModel(model_name="custom-model", temperature=0.3)
29
+ assert model2.model_name == "custom-model"
30
+ assert model2.temperature == 0.3
31
+
32
+ @requires_api_key
33
+ def test_invoke_with_string(self):
34
+ """Test model invocation with a string."""
35
+ response = self.model.invoke("Hello, how are you?")
36
+ assert isinstance(response, AIMessage)
37
+ assert len(response.content) > 0
38
+
39
+ @requires_api_key
40
+ def test_invoke_with_messages(self):
41
+ """Test model invocation with a list of messages."""
42
+ messages = [
43
+ SystemMessage(content="You are a helpful assistant."),
44
+ HumanMessage(content="What is the capital of France?")
45
+ ]
46
+ response = self.model.invoke(messages)
47
+ assert isinstance(response, AIMessage)
48
+ assert len(response.content) > 0
49
+ assert "Paris" in response.content
50
+
51
+ @requires_api_key
52
+ def test_bind_tools(self):
53
+ """Test binding tools to the model."""
54
+ from langchain.tools import tool
55
+
56
+ @tool
57
+ def calculator(expression: str) -> str:
58
+ """Calculate a mathematical expression."""
59
+ return str(eval(expression))
60
+
61
+ tools = [calculator]
62
+ model_with_tools = self.model.bind_tools(tools)
63
+ assert model_with_tools is not None
langchain-asi/tests/test_integration.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # tests/test_integration.py
2
+ import os
3
+ import pytest
4
+ from langchain_asi import ASI1ChatModel
5
+ from langchain.chains import LLMChain
6
+ from langchain.prompts import PromptTemplate
7
+
8
+ # Skip tests if no API key is available
9
+ requires_api_key = pytest.mark.skipif(
10
+ not os.environ.get("ASI1_API_KEY"),
11
+ reason="ASI1_API_KEY environment variable not set"
12
+ )
13
+
14
+ class TestLangChainIntegration:
15
+
16
+ def setup_method(self):
17
+ """Set up the test fixture."""
18
+ self.model = ASI1ChatModel()
19
+
20
+ @requires_api_key
21
+ def test_llm_chain(self):
22
+ """Test using the model in a LLMChain."""
23
+ prompt = PromptTemplate(
24
+ input_variables=["topic"],
25
+ template="Write a one-sentence summary about {topic}."
26
+ )
27
+ chain = LLMChain(llm=self.model, prompt=prompt)
28
+ result = chain.run("quantum computing")
29
+ assert len(result) > 0
30
+ assert isinstance(result, str)
langchain-asi/tests/test_simple.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ # tests/test_simple.py
2
+ def test_import():
3
+ """Test that langchain_asi can be imported."""
4
+ import langchain_asi
5
+ assert hasattr(langchain_asi, "ASI1ChatModel")