truthstack 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- truthstack-1.0.0/PKG-INFO +189 -0
- truthstack-1.0.0/README.md +139 -0
- truthstack-1.0.0/setup.cfg +4 -0
- truthstack-1.0.0/setup.py +41 -0
- truthstack-1.0.0/truthstack/__init__.py +484 -0
- truthstack-1.0.0/truthstack.egg-info/PKG-INFO +189 -0
- truthstack-1.0.0/truthstack.egg-info/SOURCES.txt +8 -0
- truthstack-1.0.0/truthstack.egg-info/dependency_links.txt +1 -0
- truthstack-1.0.0/truthstack.egg-info/requires.txt +16 -0
- truthstack-1.0.0/truthstack.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: truthstack
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: TruthStack supplement safety API SDK. LangChain, LlamaIndex, CrewAI, and OpenAI integrations.
|
|
5
|
+
Home-page: https://github.com/TruthStack1/truthstack-python
|
|
6
|
+
Author: TruthStack
|
|
7
|
+
Author-email: chris@truthstack.co
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Documentation, https://api.truthstack.co/docs
|
|
10
|
+
Project-URL: MCP Server, https://github.com/TruthStack1/truthstack-mcp
|
|
11
|
+
Project-URL: Bug Tracker, https://github.com/TruthStack1/truthstack-python/issues
|
|
12
|
+
Keywords: supplements drug-interactions langchain llamaindex crewai openai health safety pharmacovigilance glp-1 ozempic
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Requires-Python: >=3.8
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
Provides-Extra: langchain
|
|
27
|
+
Requires-Dist: langchain-core>=0.1.0; extra == "langchain"
|
|
28
|
+
Requires-Dist: pydantic>=2.0; extra == "langchain"
|
|
29
|
+
Provides-Extra: llamaindex
|
|
30
|
+
Requires-Dist: llama-index-core>=0.10.0; extra == "llamaindex"
|
|
31
|
+
Provides-Extra: crewai
|
|
32
|
+
Requires-Dist: crewai>=0.1.0; extra == "crewai"
|
|
33
|
+
Provides-Extra: all
|
|
34
|
+
Requires-Dist: langchain-core>=0.1.0; extra == "all"
|
|
35
|
+
Requires-Dist: pydantic>=2.0; extra == "all"
|
|
36
|
+
Requires-Dist: llama-index-core>=0.10.0; extra == "all"
|
|
37
|
+
Requires-Dist: crewai>=0.1.0; extra == "all"
|
|
38
|
+
Dynamic: author
|
|
39
|
+
Dynamic: author-email
|
|
40
|
+
Dynamic: classifier
|
|
41
|
+
Dynamic: description
|
|
42
|
+
Dynamic: description-content-type
|
|
43
|
+
Dynamic: home-page
|
|
44
|
+
Dynamic: keywords
|
|
45
|
+
Dynamic: license
|
|
46
|
+
Dynamic: project-url
|
|
47
|
+
Dynamic: provides-extra
|
|
48
|
+
Dynamic: requires-python
|
|
49
|
+
Dynamic: summary
|
|
50
|
+
|
|
51
|
+
# truthstack
|
|
52
|
+
|
|
53
|
+
Python SDK for [TruthStack](https://truthstack.co) supplement safety API. Works with LangChain, LlamaIndex, CrewAI, OpenAI function calling, and standalone.
|
|
54
|
+
|
|
55
|
+
## Install
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install truthstack # Core client (zero deps)
|
|
59
|
+
pip install truthstack[langchain] # + LangChain tools
|
|
60
|
+
pip install truthstack[llamaindex] # + LlamaIndex tools
|
|
61
|
+
pip install truthstack[crewai] # + CrewAI tools
|
|
62
|
+
pip install truthstack[all] # Everything
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Quick Start
|
|
66
|
+
|
|
67
|
+
### Standalone
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from truthstack import TruthStackClient
|
|
71
|
+
|
|
72
|
+
client = TruthStackClient(api_key="your-key")
|
|
73
|
+
|
|
74
|
+
# Check interactions (the money endpoint)
|
|
75
|
+
result = client.check_interactions(
|
|
76
|
+
supplements=["berberine", "magnesium", "vitamin_d"],
|
|
77
|
+
medications=["semaglutide"]
|
|
78
|
+
)
|
|
79
|
+
print(result["risk_level"]) # "HIGH"
|
|
80
|
+
print(result["cyp_pathway_conflicts"])
|
|
81
|
+
print(result["evidence_by_compound"])
|
|
82
|
+
|
|
83
|
+
# Get evidence balance
|
|
84
|
+
evidence = client.get_evidence("berberine")
|
|
85
|
+
print(evidence["evidence_balance"]) # {"positive": 8, "null": 2, ...}
|
|
86
|
+
print(evidence["citations"]) # [{"pmid": "12345", ...}]
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### LangChain
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from truthstack import get_langchain_tools
|
|
93
|
+
from langchain_openai import ChatOpenAI
|
|
94
|
+
from langchain.agents import AgentExecutor, create_openai_tools_agent
|
|
95
|
+
|
|
96
|
+
tools = get_langchain_tools(api_key="your-key")
|
|
97
|
+
llm = ChatOpenAI(model="gpt-4")
|
|
98
|
+
agent = create_openai_tools_agent(llm, tools, prompt)
|
|
99
|
+
executor = AgentExecutor(agent=agent, tools=tools)
|
|
100
|
+
|
|
101
|
+
result = executor.invoke({"input": "Can I take berberine while on Ozempic?"})
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### LlamaIndex
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from truthstack import get_llamaindex_tools
|
|
108
|
+
from llama_index.core.agent import ReActAgent
|
|
109
|
+
from llama_index.llms.openai import OpenAI
|
|
110
|
+
|
|
111
|
+
tools = get_llamaindex_tools(api_key="your-key")
|
|
112
|
+
agent = ReActAgent.from_tools(tools, llm=OpenAI(model="gpt-4"))
|
|
113
|
+
|
|
114
|
+
response = agent.chat("What's the evidence for CoQ10?")
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### CrewAI
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from truthstack import get_crewai_tools
|
|
121
|
+
from crewai import Agent, Task, Crew
|
|
122
|
+
|
|
123
|
+
tools = get_crewai_tools(api_key="your-key")
|
|
124
|
+
|
|
125
|
+
analyst = Agent(
|
|
126
|
+
role="Supplement Safety Analyst",
|
|
127
|
+
goal="Check supplement interactions and evidence",
|
|
128
|
+
tools=tools,
|
|
129
|
+
)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### OpenAI Function Calling
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
from truthstack import get_openai_functions, handle_openai_function_call
|
|
136
|
+
from openai import OpenAI
|
|
137
|
+
|
|
138
|
+
client = OpenAI()
|
|
139
|
+
functions = get_openai_functions()
|
|
140
|
+
|
|
141
|
+
response = client.chat.completions.create(
|
|
142
|
+
model="gpt-4",
|
|
143
|
+
messages=[{"role": "user", "content": "Is magnesium safe with sertraline?"}],
|
|
144
|
+
functions=functions,
|
|
145
|
+
function_call="auto",
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
call = response.choices[0].message.function_call
|
|
149
|
+
result = handle_openai_function_call(
|
|
150
|
+
call.name, json.loads(call.arguments), api_key="your-key"
|
|
151
|
+
)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## System Prompts
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
from truthstack import SYSTEM_PROMPTS
|
|
158
|
+
|
|
159
|
+
SYSTEM_PROMPTS["supplement_safety_advisor"] # General safety
|
|
160
|
+
SYSTEM_PROMPTS["glp1_supplement_checker"] # GLP-1/Ozempic focus
|
|
161
|
+
SYSTEM_PROMPTS["evidence_researcher"] # Research analysis
|
|
162
|
+
SYSTEM_PROMPTS["stack_optimizer"] # Stack optimization
|
|
163
|
+
SYSTEM_PROMPTS["clinician_assistant"] # Clinician-facing
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Tools
|
|
167
|
+
|
|
168
|
+
| Tool | Description |
|
|
169
|
+
|------|-------------|
|
|
170
|
+
| `truthstack_check_interactions` | Check supplement + drug interactions |
|
|
171
|
+
| `truthstack_get_evidence` | Evidence balance + citations |
|
|
172
|
+
| `truthstack_search_supplements` | Fuzzy compound search |
|
|
173
|
+
| `truthstack_safety_signals` | FDA CAERS/FAERS signals |
|
|
174
|
+
| `truthstack_drug_profile` | Drug CYP450 + botanical interactions |
|
|
175
|
+
|
|
176
|
+
## Environment Variables
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
TRUTHSTACK_API_KEY=your-key
|
|
180
|
+
TRUTHSTACK_BASE_URL=https://api.truthstack.co # optional
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## API Key
|
|
184
|
+
|
|
185
|
+
Get a free key (2,000 calls/month) at [truthstack.co/developers](https://truthstack.co/developers).
|
|
186
|
+
|
|
187
|
+
## License
|
|
188
|
+
|
|
189
|
+
MIT
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# truthstack
|
|
2
|
+
|
|
3
|
+
Python SDK for [TruthStack](https://truthstack.co) supplement safety API. Works with LangChain, LlamaIndex, CrewAI, OpenAI function calling, and standalone.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install truthstack # Core client (zero deps)
|
|
9
|
+
pip install truthstack[langchain] # + LangChain tools
|
|
10
|
+
pip install truthstack[llamaindex] # + LlamaIndex tools
|
|
11
|
+
pip install truthstack[crewai] # + CrewAI tools
|
|
12
|
+
pip install truthstack[all] # Everything
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
### Standalone
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
from truthstack import TruthStackClient
|
|
21
|
+
|
|
22
|
+
client = TruthStackClient(api_key="your-key")
|
|
23
|
+
|
|
24
|
+
# Check interactions (the money endpoint)
|
|
25
|
+
result = client.check_interactions(
|
|
26
|
+
supplements=["berberine", "magnesium", "vitamin_d"],
|
|
27
|
+
medications=["semaglutide"]
|
|
28
|
+
)
|
|
29
|
+
print(result["risk_level"]) # "HIGH"
|
|
30
|
+
print(result["cyp_pathway_conflicts"])
|
|
31
|
+
print(result["evidence_by_compound"])
|
|
32
|
+
|
|
33
|
+
# Get evidence balance
|
|
34
|
+
evidence = client.get_evidence("berberine")
|
|
35
|
+
print(evidence["evidence_balance"]) # {"positive": 8, "null": 2, ...}
|
|
36
|
+
print(evidence["citations"]) # [{"pmid": "12345", ...}]
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### LangChain
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from truthstack import get_langchain_tools
|
|
43
|
+
from langchain_openai import ChatOpenAI
|
|
44
|
+
from langchain.agents import AgentExecutor, create_openai_tools_agent
|
|
45
|
+
|
|
46
|
+
tools = get_langchain_tools(api_key="your-key")
|
|
47
|
+
llm = ChatOpenAI(model="gpt-4")
|
|
48
|
+
agent = create_openai_tools_agent(llm, tools, prompt)
|
|
49
|
+
executor = AgentExecutor(agent=agent, tools=tools)
|
|
50
|
+
|
|
51
|
+
result = executor.invoke({"input": "Can I take berberine while on Ozempic?"})
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### LlamaIndex
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
from truthstack import get_llamaindex_tools
|
|
58
|
+
from llama_index.core.agent import ReActAgent
|
|
59
|
+
from llama_index.llms.openai import OpenAI
|
|
60
|
+
|
|
61
|
+
tools = get_llamaindex_tools(api_key="your-key")
|
|
62
|
+
agent = ReActAgent.from_tools(tools, llm=OpenAI(model="gpt-4"))
|
|
63
|
+
|
|
64
|
+
response = agent.chat("What's the evidence for CoQ10?")
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### CrewAI
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from truthstack import get_crewai_tools
|
|
71
|
+
from crewai import Agent, Task, Crew
|
|
72
|
+
|
|
73
|
+
tools = get_crewai_tools(api_key="your-key")
|
|
74
|
+
|
|
75
|
+
analyst = Agent(
|
|
76
|
+
role="Supplement Safety Analyst",
|
|
77
|
+
goal="Check supplement interactions and evidence",
|
|
78
|
+
tools=tools,
|
|
79
|
+
)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### OpenAI Function Calling
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
from truthstack import get_openai_functions, handle_openai_function_call
|
|
86
|
+
from openai import OpenAI
|
|
87
|
+
|
|
88
|
+
client = OpenAI()
|
|
89
|
+
functions = get_openai_functions()
|
|
90
|
+
|
|
91
|
+
response = client.chat.completions.create(
|
|
92
|
+
model="gpt-4",
|
|
93
|
+
messages=[{"role": "user", "content": "Is magnesium safe with sertraline?"}],
|
|
94
|
+
functions=functions,
|
|
95
|
+
function_call="auto",
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
call = response.choices[0].message.function_call
|
|
99
|
+
result = handle_openai_function_call(
|
|
100
|
+
call.name, json.loads(call.arguments), api_key="your-key"
|
|
101
|
+
)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## System Prompts
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from truthstack import SYSTEM_PROMPTS
|
|
108
|
+
|
|
109
|
+
SYSTEM_PROMPTS["supplement_safety_advisor"] # General safety
|
|
110
|
+
SYSTEM_PROMPTS["glp1_supplement_checker"] # GLP-1/Ozempic focus
|
|
111
|
+
SYSTEM_PROMPTS["evidence_researcher"] # Research analysis
|
|
112
|
+
SYSTEM_PROMPTS["stack_optimizer"] # Stack optimization
|
|
113
|
+
SYSTEM_PROMPTS["clinician_assistant"] # Clinician-facing
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Tools
|
|
117
|
+
|
|
118
|
+
| Tool | Description |
|
|
119
|
+
|------|-------------|
|
|
120
|
+
| `truthstack_check_interactions` | Check supplement + drug interactions |
|
|
121
|
+
| `truthstack_get_evidence` | Evidence balance + citations |
|
|
122
|
+
| `truthstack_search_supplements` | Fuzzy compound search |
|
|
123
|
+
| `truthstack_safety_signals` | FDA CAERS/FAERS signals |
|
|
124
|
+
| `truthstack_drug_profile` | Drug CYP450 + botanical interactions |
|
|
125
|
+
|
|
126
|
+
## Environment Variables
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
TRUTHSTACK_API_KEY=your-key
|
|
130
|
+
TRUTHSTACK_BASE_URL=https://api.truthstack.co # optional
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## API Key
|
|
134
|
+
|
|
135
|
+
Get a free key (2,000 calls/month) at [truthstack.co/developers](https://truthstack.co/developers).
|
|
136
|
+
|
|
137
|
+
## License
|
|
138
|
+
|
|
139
|
+
MIT
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name="truthstack",
|
|
5
|
+
version="1.0.0",
|
|
6
|
+
description="TruthStack supplement safety API SDK. LangChain, LlamaIndex, CrewAI, and OpenAI integrations.",
|
|
7
|
+
long_description=open("README.md").read(),
|
|
8
|
+
long_description_content_type="text/markdown",
|
|
9
|
+
author="TruthStack",
|
|
10
|
+
author_email="chris@truthstack.co",
|
|
11
|
+
url="https://github.com/TruthStack1/truthstack-python",
|
|
12
|
+
packages=find_packages(),
|
|
13
|
+
python_requires=">=3.8",
|
|
14
|
+
install_requires=[], # Zero deps for core client
|
|
15
|
+
extras_require={
|
|
16
|
+
"langchain": ["langchain-core>=0.1.0", "pydantic>=2.0"],
|
|
17
|
+
"llamaindex": ["llama-index-core>=0.10.0"],
|
|
18
|
+
"crewai": ["crewai>=0.1.0"],
|
|
19
|
+
"all": ["langchain-core>=0.1.0", "pydantic>=2.0", "llama-index-core>=0.10.0", "crewai>=0.1.0"],
|
|
20
|
+
},
|
|
21
|
+
classifiers=[
|
|
22
|
+
"Development Status :: 4 - Beta",
|
|
23
|
+
"Intended Audience :: Developers",
|
|
24
|
+
"License :: OSI Approved :: MIT License",
|
|
25
|
+
"Programming Language :: Python :: 3",
|
|
26
|
+
"Programming Language :: Python :: 3.8",
|
|
27
|
+
"Programming Language :: Python :: 3.9",
|
|
28
|
+
"Programming Language :: Python :: 3.10",
|
|
29
|
+
"Programming Language :: Python :: 3.11",
|
|
30
|
+
"Programming Language :: Python :: 3.12",
|
|
31
|
+
"Topic :: Scientific/Engineering :: Medical Science Apps.",
|
|
32
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
33
|
+
],
|
|
34
|
+
keywords="supplements drug-interactions langchain llamaindex crewai openai health safety pharmacovigilance glp-1 ozempic",
|
|
35
|
+
license="MIT",
|
|
36
|
+
project_urls={
|
|
37
|
+
"Documentation": "https://api.truthstack.co/docs",
|
|
38
|
+
"MCP Server": "https://github.com/TruthStack1/truthstack-mcp",
|
|
39
|
+
"Bug Tracker": "https://github.com/TruthStack1/truthstack-python/issues",
|
|
40
|
+
},
|
|
41
|
+
)
|
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
"""
|
|
2
|
+
truthstack - Python SDK for TruthStack supplement safety API.
|
|
3
|
+
Works with LangChain, LlamaIndex, CrewAI, and standalone.
|
|
4
|
+
|
|
5
|
+
pip install truthstack
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
from truthstack import TruthStackClient
|
|
9
|
+
client = TruthStackClient(api_key="your-key")
|
|
10
|
+
result = client.check_interactions(["berberine", "magnesium"], ["semaglutide"])
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import os
|
|
14
|
+
import json
|
|
15
|
+
import urllib.request
|
|
16
|
+
import urllib.error
|
|
17
|
+
import urllib.parse
|
|
18
|
+
from typing import List, Optional, Dict, Any
|
|
19
|
+
|
|
20
|
+
__version__ = "1.0.0"
|
|
21
|
+
__all__ = [
|
|
22
|
+
"TruthStackClient",
|
|
23
|
+
"get_langchain_tools",
|
|
24
|
+
"get_llamaindex_tools",
|
|
25
|
+
"get_crewai_tools",
|
|
26
|
+
"get_openai_functions",
|
|
27
|
+
"handle_openai_function_call",
|
|
28
|
+
"SYSTEM_PROMPTS",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
DEFAULT_BASE_URL = "https://api.truthstack.co"
|
|
32
|
+
CLIENT_ID_BASE = "truthstack-python"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class TruthStackError(Exception):
|
|
36
|
+
"""Error from the TruthStack API."""
|
|
37
|
+
def __init__(self, message: str, code: str = "UNKNOWN", status: int = 0,
|
|
38
|
+
suggestions: list = None, hint: str = None):
|
|
39
|
+
super().__init__(message)
|
|
40
|
+
self.code = code
|
|
41
|
+
self.status = status
|
|
42
|
+
self.suggestions = suggestions or []
|
|
43
|
+
self.hint = hint
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class TruthStackClient:
|
|
47
|
+
"""Client for the TruthStack Vault API."""
|
|
48
|
+
|
|
49
|
+
def __init__(self, api_key: str = None, base_url: str = None, framework: str = None):
|
|
50
|
+
self.api_key = api_key or os.environ.get("TRUTHSTACK_API_KEY", "")
|
|
51
|
+
self.base_url = (base_url or os.environ.get("TRUTHSTACK_BASE_URL", DEFAULT_BASE_URL)).rstrip("/")
|
|
52
|
+
self.framework = framework or "standalone"
|
|
53
|
+
if not self.api_key:
|
|
54
|
+
raise ValueError(
|
|
55
|
+
"TruthStack API key required. Set TRUTHSTACK_API_KEY env var "
|
|
56
|
+
"or pass api_key. Get a free key at truthstack.co/developers"
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def _client_id(self) -> str:
|
|
61
|
+
return f"{CLIENT_ID_BASE}-{self.framework}/{__version__}"
|
|
62
|
+
|
|
63
|
+
def _request(self, method: str, path: str, body: dict = None) -> dict:
|
|
64
|
+
url = f"{self.base_url}{path}"
|
|
65
|
+
data = json.dumps(body).encode() if body else None
|
|
66
|
+
headers = {
|
|
67
|
+
"X-API-Key": self.api_key,
|
|
68
|
+
"X-TruthStack-Client": self._client_id,
|
|
69
|
+
"Content-Type": "application/json",
|
|
70
|
+
"Accept": "application/json",
|
|
71
|
+
}
|
|
72
|
+
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
|
73
|
+
try:
|
|
74
|
+
with urllib.request.urlopen(req, timeout=30) as resp:
|
|
75
|
+
return json.loads(resp.read().decode())
|
|
76
|
+
except urllib.error.HTTPError as e:
|
|
77
|
+
body_str = e.read().decode()
|
|
78
|
+
try:
|
|
79
|
+
parsed = json.loads(body_str)
|
|
80
|
+
raise TruthStackError(
|
|
81
|
+
message=parsed.get("message", str(e)),
|
|
82
|
+
code=parsed.get("error_code", "UNKNOWN"),
|
|
83
|
+
status=e.code,
|
|
84
|
+
suggestions=parsed.get("suggestions", []),
|
|
85
|
+
hint=parsed.get("hint"),
|
|
86
|
+
)
|
|
87
|
+
except (json.JSONDecodeError, TruthStackError):
|
|
88
|
+
if isinstance(e.__context__, TruthStackError):
|
|
89
|
+
raise e.__context__
|
|
90
|
+
raise TruthStackError(str(e), status=e.code)
|
|
91
|
+
|
|
92
|
+
def check_interactions(self, supplements: List[str], medications: List[str] = None) -> dict:
|
|
93
|
+
"""Check supplement-supplement and supplement-drug interactions."""
|
|
94
|
+
return self._request("POST", "/api/interactions/check", {
|
|
95
|
+
"supplements": supplements,
|
|
96
|
+
"medications": medications or [],
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
def get_evidence(self, compound_id: str) -> dict:
|
|
100
|
+
"""Get evidence balance and citations for a compound."""
|
|
101
|
+
return self._request("GET", f"/api/compounds/{urllib.parse.quote(compound_id)}/evidence")
|
|
102
|
+
|
|
103
|
+
def search_compounds(self, query: str, limit: int = 10) -> dict:
|
|
104
|
+
"""Search for compounds by name."""
|
|
105
|
+
return self._request("GET", f"/api/compounds/search?q={urllib.parse.quote(query)}&limit={limit}")
|
|
106
|
+
|
|
107
|
+
def get_compound(self, compound_id: str) -> dict:
|
|
108
|
+
"""Get compound details."""
|
|
109
|
+
return self._request("GET", f"/api/compounds/{urllib.parse.quote(compound_id)}")
|
|
110
|
+
|
|
111
|
+
def get_safety_signals(self, compound_id: str) -> dict:
|
|
112
|
+
"""Get FDA adverse event safety signals."""
|
|
113
|
+
return self._request("GET", f"/api/compounds/{urllib.parse.quote(compound_id)}/safety-signals")
|
|
114
|
+
|
|
115
|
+
def get_drug(self, drug_id: str) -> dict:
|
|
116
|
+
"""Get drug profile with CYP pathways."""
|
|
117
|
+
return self._request("GET", f"/api/drugs/{urllib.parse.quote(drug_id)}")
|
|
118
|
+
|
|
119
|
+
def health(self) -> dict:
|
|
120
|
+
"""Check API health."""
|
|
121
|
+
return self._request("GET", "/api/health")
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
# ============================================================
|
|
125
|
+
# LANGCHAIN INTEGRATION
|
|
126
|
+
# ============================================================
|
|
127
|
+
|
|
128
|
+
def get_langchain_tools(api_key: str = None, base_url: str = None):
|
|
129
|
+
"""
|
|
130
|
+
Get TruthStack tools for LangChain.
|
|
131
|
+
|
|
132
|
+
Usage:
|
|
133
|
+
from truthstack import get_langchain_tools
|
|
134
|
+
from langchain.agents import AgentExecutor
|
|
135
|
+
|
|
136
|
+
tools = get_langchain_tools(api_key="your-key")
|
|
137
|
+
agent = AgentExecutor(tools=tools, llm=llm, ...)
|
|
138
|
+
"""
|
|
139
|
+
try:
|
|
140
|
+
from langchain_core.tools import StructuredTool
|
|
141
|
+
from pydantic import BaseModel, Field
|
|
142
|
+
except ImportError:
|
|
143
|
+
raise ImportError("Install langchain: pip install langchain-core pydantic")
|
|
144
|
+
|
|
145
|
+
client = TruthStackClient(api_key=api_key, base_url=base_url, framework="langchain")
|
|
146
|
+
|
|
147
|
+
class CheckInteractionsInput(BaseModel):
|
|
148
|
+
supplements: List[str] = Field(description="List of supplement names")
|
|
149
|
+
medications: List[str] = Field(default=[], description="Optional list of medication names")
|
|
150
|
+
|
|
151
|
+
class CompoundInput(BaseModel):
|
|
152
|
+
compound_id: str = Field(description='Supplement ID (lowercase, underscores). E.g. "vitamin_d"')
|
|
153
|
+
|
|
154
|
+
class SearchInput(BaseModel):
|
|
155
|
+
query: str = Field(description='Search query, e.g. "magnesium glycinate"')
|
|
156
|
+
|
|
157
|
+
class DrugInput(BaseModel):
|
|
158
|
+
drug_id: str = Field(description='Drug name, e.g. "sertraline"')
|
|
159
|
+
|
|
160
|
+
def _check_interactions(supplements: List[str], medications: List[str] = []) -> str:
|
|
161
|
+
return json.dumps(client.check_interactions(supplements, medications), indent=2)
|
|
162
|
+
|
|
163
|
+
def _get_evidence(compound_id: str) -> str:
|
|
164
|
+
return json.dumps(client.get_evidence(compound_id), indent=2)
|
|
165
|
+
|
|
166
|
+
def _search(query: str) -> str:
|
|
167
|
+
return json.dumps(client.search_compounds(query), indent=2)
|
|
168
|
+
|
|
169
|
+
def _safety_signals(compound_id: str) -> str:
|
|
170
|
+
return json.dumps(client.get_safety_signals(compound_id), indent=2)
|
|
171
|
+
|
|
172
|
+
def _drug_profile(drug_id: str) -> str:
|
|
173
|
+
return json.dumps(client.get_drug(drug_id), indent=2)
|
|
174
|
+
|
|
175
|
+
return [
|
|
176
|
+
StructuredTool.from_function(
|
|
177
|
+
func=_check_interactions,
|
|
178
|
+
name="truthstack_check_interactions",
|
|
179
|
+
description="Check supplement-supplement and supplement-drug interactions. Returns risk level, CYP conflicts, FDA warnings, evidence balance, citations.",
|
|
180
|
+
args_schema=CheckInteractionsInput,
|
|
181
|
+
),
|
|
182
|
+
StructuredTool.from_function(
|
|
183
|
+
func=_get_evidence,
|
|
184
|
+
name="truthstack_get_evidence",
|
|
185
|
+
description="Get evidence balance and research citations for a supplement. Returns positive/negative/null counts, evidence level, conditions studied, PMIDs.",
|
|
186
|
+
args_schema=CompoundInput,
|
|
187
|
+
),
|
|
188
|
+
StructuredTool.from_function(
|
|
189
|
+
func=_search,
|
|
190
|
+
name="truthstack_search_supplements",
|
|
191
|
+
description="Search for supplements by name with fuzzy matching and alias resolution.",
|
|
192
|
+
args_schema=SearchInput,
|
|
193
|
+
),
|
|
194
|
+
StructuredTool.from_function(
|
|
195
|
+
func=_safety_signals,
|
|
196
|
+
name="truthstack_safety_signals",
|
|
197
|
+
description="Get FDA adverse event (CAERS/FAERS) safety signals for a supplement.",
|
|
198
|
+
args_schema=CompoundInput,
|
|
199
|
+
),
|
|
200
|
+
StructuredTool.from_function(
|
|
201
|
+
func=_drug_profile,
|
|
202
|
+
name="truthstack_drug_profile",
|
|
203
|
+
description="Get drug CYP450 pathways, transporters, and botanical interactions.",
|
|
204
|
+
args_schema=DrugInput,
|
|
205
|
+
),
|
|
206
|
+
]
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
# ============================================================
|
|
210
|
+
# LLAMAINDEX INTEGRATION
|
|
211
|
+
# ============================================================
|
|
212
|
+
|
|
213
|
+
def get_llamaindex_tools(api_key: str = None, base_url: str = None):
|
|
214
|
+
"""
|
|
215
|
+
Get TruthStack tools for LlamaIndex.
|
|
216
|
+
|
|
217
|
+
Usage:
|
|
218
|
+
from truthstack import get_llamaindex_tools
|
|
219
|
+
from llama_index.core.agent import ReActAgent
|
|
220
|
+
|
|
221
|
+
tools = get_llamaindex_tools(api_key="your-key")
|
|
222
|
+
agent = ReActAgent.from_tools(tools, llm=llm, ...)
|
|
223
|
+
"""
|
|
224
|
+
try:
|
|
225
|
+
from llama_index.core.tools import FunctionTool
|
|
226
|
+
except ImportError:
|
|
227
|
+
raise ImportError("Install llama-index: pip install llama-index-core")
|
|
228
|
+
|
|
229
|
+
client = TruthStackClient(api_key=api_key, base_url=base_url, framework="llamaindex")
|
|
230
|
+
|
|
231
|
+
def check_interactions(supplements: List[str], medications: List[str] = []) -> str:
|
|
232
|
+
"""Check supplement-supplement and supplement-drug interactions for safety.
|
|
233
|
+
Returns risk level, CYP pathway conflicts, FDA warnings, evidence balance, and citations.
|
|
234
|
+
Args:
|
|
235
|
+
supplements: List of supplement names (e.g. ["berberine", "magnesium"])
|
|
236
|
+
medications: Optional list of medication names (e.g. ["semaglutide"])
|
|
237
|
+
"""
|
|
238
|
+
return json.dumps(client.check_interactions(supplements, medications), indent=2)
|
|
239
|
+
|
|
240
|
+
def get_evidence(compound_id: str) -> str:
|
|
241
|
+
"""Get evidence balance and research citations for a supplement compound.
|
|
242
|
+
Returns positive/negative/null finding counts, evidence level, conditions studied, PMIDs.
|
|
243
|
+
Args:
|
|
244
|
+
compound_id: Supplement ID in lowercase with underscores (e.g. "vitamin_d")
|
|
245
|
+
"""
|
|
246
|
+
return json.dumps(client.get_evidence(compound_id), indent=2)
|
|
247
|
+
|
|
248
|
+
def search_supplements(query: str) -> str:
|
|
249
|
+
"""Search for supplements by name with fuzzy matching and alias resolution.
|
|
250
|
+
Args:
|
|
251
|
+
query: Search query (e.g. "mag glycinate", "fish oil")
|
|
252
|
+
"""
|
|
253
|
+
return json.dumps(client.search_compounds(query), indent=2)
|
|
254
|
+
|
|
255
|
+
def safety_signals(compound_id: str) -> str:
|
|
256
|
+
"""Get FDA adverse event (CAERS/FAERS) safety signals for a supplement.
|
|
257
|
+
Args:
|
|
258
|
+
compound_id: Supplement ID in lowercase with underscores
|
|
259
|
+
"""
|
|
260
|
+
return json.dumps(client.get_safety_signals(compound_id), indent=2)
|
|
261
|
+
|
|
262
|
+
def drug_profile(drug_id: str) -> str:
|
|
263
|
+
"""Get drug CYP450 metabolism pathways, transporters, and botanical interactions.
|
|
264
|
+
Args:
|
|
265
|
+
drug_id: Drug name (e.g. "sertraline", "metformin")
|
|
266
|
+
"""
|
|
267
|
+
return json.dumps(client.get_drug(drug_id), indent=2)
|
|
268
|
+
|
|
269
|
+
return [
|
|
270
|
+
FunctionTool.from_defaults(fn=check_interactions, name="truthstack_check_interactions"),
|
|
271
|
+
FunctionTool.from_defaults(fn=get_evidence, name="truthstack_get_evidence"),
|
|
272
|
+
FunctionTool.from_defaults(fn=search_supplements, name="truthstack_search_supplements"),
|
|
273
|
+
FunctionTool.from_defaults(fn=safety_signals, name="truthstack_safety_signals"),
|
|
274
|
+
FunctionTool.from_defaults(fn=drug_profile, name="truthstack_drug_profile"),
|
|
275
|
+
]
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
# ============================================================
|
|
279
|
+
# CREWAI INTEGRATION
|
|
280
|
+
# ============================================================
|
|
281
|
+
|
|
282
|
+
def get_crewai_tools(api_key: str = None, base_url: str = None):
|
|
283
|
+
"""
|
|
284
|
+
Get TruthStack tools for CrewAI.
|
|
285
|
+
|
|
286
|
+
Usage:
|
|
287
|
+
from truthstack import get_crewai_tools
|
|
288
|
+
from crewai import Agent
|
|
289
|
+
|
|
290
|
+
tools = get_crewai_tools(api_key="your-key")
|
|
291
|
+
agent = Agent(role="Supplement Safety Analyst", tools=tools, ...)
|
|
292
|
+
"""
|
|
293
|
+
try:
|
|
294
|
+
from crewai.tools import tool as crewai_tool
|
|
295
|
+
except ImportError:
|
|
296
|
+
raise ImportError("Install crewai: pip install crewai")
|
|
297
|
+
|
|
298
|
+
client = TruthStackClient(api_key=api_key, base_url=base_url, framework="crewai")
|
|
299
|
+
|
|
300
|
+
@crewai_tool("TruthStack Interaction Checker")
|
|
301
|
+
def check_interactions(supplements: str, medications: str = "") -> str:
|
|
302
|
+
"""Check supplement-supplement and supplement-drug interactions for safety.
|
|
303
|
+
supplements: Comma-separated supplement names (e.g. "berberine, magnesium")
|
|
304
|
+
medications: Optional comma-separated medication names (e.g. "semaglutide, metformin")
|
|
305
|
+
"""
|
|
306
|
+
supps = [s.strip() for s in supplements.split(",") if s.strip()]
|
|
307
|
+
meds = [m.strip() for m in medications.split(",") if m.strip()] if medications else []
|
|
308
|
+
return json.dumps(client.check_interactions(supps, meds), indent=2)
|
|
309
|
+
|
|
310
|
+
@crewai_tool("TruthStack Evidence Lookup")
|
|
311
|
+
def get_evidence(compound_id: str) -> str:
|
|
312
|
+
"""Get evidence balance and research citations for a supplement.
|
|
313
|
+
compound_id: Supplement ID in lowercase with underscores (e.g. "vitamin_d")
|
|
314
|
+
"""
|
|
315
|
+
return json.dumps(client.get_evidence(compound_id), indent=2)
|
|
316
|
+
|
|
317
|
+
@crewai_tool("TruthStack Supplement Search")
|
|
318
|
+
def search_supplements(query: str) -> str:
|
|
319
|
+
"""Search for supplements by name with fuzzy matching.
|
|
320
|
+
query: Search query (e.g. "magnesium glycinate")
|
|
321
|
+
"""
|
|
322
|
+
return json.dumps(client.search_compounds(query), indent=2)
|
|
323
|
+
|
|
324
|
+
@crewai_tool("TruthStack Safety Signals")
|
|
325
|
+
def safety_signals(compound_id: str) -> str:
|
|
326
|
+
"""Get FDA adverse event safety signals for a supplement.
|
|
327
|
+
compound_id: Supplement ID in lowercase with underscores
|
|
328
|
+
"""
|
|
329
|
+
return json.dumps(client.get_safety_signals(compound_id), indent=2)
|
|
330
|
+
|
|
331
|
+
@crewai_tool("TruthStack Drug Profile")
|
|
332
|
+
def drug_profile(drug_id: str) -> str:
|
|
333
|
+
"""Get drug CYP450 pathways and botanical interactions.
|
|
334
|
+
drug_id: Drug name (e.g. "sertraline")
|
|
335
|
+
"""
|
|
336
|
+
return json.dumps(client.get_drug(drug_id), indent=2)
|
|
337
|
+
|
|
338
|
+
return [check_interactions, get_evidence, search_supplements, safety_signals, drug_profile]
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
# ============================================================
|
|
342
|
+
# OPENAI FUNCTION CALLING
|
|
343
|
+
# ============================================================
|
|
344
|
+
|
|
345
|
+
def get_openai_functions() -> List[dict]:
|
|
346
|
+
"""Get OpenAI function calling definitions for TruthStack tools."""
|
|
347
|
+
return [
|
|
348
|
+
{
|
|
349
|
+
"name": "truthstack_check_interactions",
|
|
350
|
+
"description": "Check supplement-supplement and supplement-drug interactions. Returns risk level, CYP conflicts, FDA warnings, evidence balance, citations.",
|
|
351
|
+
"parameters": {
|
|
352
|
+
"type": "object",
|
|
353
|
+
"properties": {
|
|
354
|
+
"supplements": {"type": "array", "items": {"type": "string"}, "description": "List of supplement names"},
|
|
355
|
+
"medications": {"type": "array", "items": {"type": "string"}, "description": "Optional medication names"},
|
|
356
|
+
},
|
|
357
|
+
"required": ["supplements"],
|
|
358
|
+
},
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
"name": "truthstack_get_evidence",
|
|
362
|
+
"description": "Get evidence balance and research citations for a supplement compound.",
|
|
363
|
+
"parameters": {
|
|
364
|
+
"type": "object",
|
|
365
|
+
"properties": {
|
|
366
|
+
"compound_id": {"type": "string", "description": "Supplement ID (lowercase, underscores)"},
|
|
367
|
+
},
|
|
368
|
+
"required": ["compound_id"],
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
"name": "truthstack_search_supplements",
|
|
373
|
+
"description": "Search for supplements by name with fuzzy matching.",
|
|
374
|
+
"parameters": {
|
|
375
|
+
"type": "object",
|
|
376
|
+
"properties": {
|
|
377
|
+
"query": {"type": "string", "description": "Search query"},
|
|
378
|
+
},
|
|
379
|
+
"required": ["query"],
|
|
380
|
+
},
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
"name": "truthstack_safety_signals",
|
|
384
|
+
"description": "Get FDA adverse event safety signals for a supplement.",
|
|
385
|
+
"parameters": {
|
|
386
|
+
"type": "object",
|
|
387
|
+
"properties": {
|
|
388
|
+
"compound_id": {"type": "string", "description": "Supplement ID"},
|
|
389
|
+
},
|
|
390
|
+
"required": ["compound_id"],
|
|
391
|
+
},
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
"name": "truthstack_drug_profile",
|
|
395
|
+
"description": "Get drug CYP450 pathways, transporters, and botanical interactions.",
|
|
396
|
+
"parameters": {
|
|
397
|
+
"type": "object",
|
|
398
|
+
"properties": {
|
|
399
|
+
"drug_id": {"type": "string", "description": "Drug name"},
|
|
400
|
+
},
|
|
401
|
+
"required": ["drug_id"],
|
|
402
|
+
},
|
|
403
|
+
},
|
|
404
|
+
]
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
def handle_openai_function_call(function_name: str, arguments: dict,
|
|
408
|
+
api_key: str = None, base_url: str = None) -> dict:
|
|
409
|
+
"""Handle an OpenAI function call response."""
|
|
410
|
+
client = TruthStackClient(api_key=api_key, base_url=base_url, framework="openai")
|
|
411
|
+
handlers = {
|
|
412
|
+
"truthstack_check_interactions": lambda a: client.check_interactions(a["supplements"], a.get("medications", [])),
|
|
413
|
+
"truthstack_get_evidence": lambda a: client.get_evidence(a["compound_id"]),
|
|
414
|
+
"truthstack_search_supplements": lambda a: client.search_compounds(a["query"]),
|
|
415
|
+
"truthstack_safety_signals": lambda a: client.get_safety_signals(a["compound_id"]),
|
|
416
|
+
"truthstack_drug_profile": lambda a: client.get_drug(a["drug_id"]),
|
|
417
|
+
}
|
|
418
|
+
handler = handlers.get(function_name)
|
|
419
|
+
if not handler:
|
|
420
|
+
raise ValueError(f"Unknown function: {function_name}")
|
|
421
|
+
return handler(arguments)
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
# ============================================================
|
|
425
|
+
# SYSTEM PROMPTS
|
|
426
|
+
# ============================================================
|
|
427
|
+
|
|
428
|
+
SYSTEM_PROMPTS = {
|
|
429
|
+
"supplement_safety_advisor": (
|
|
430
|
+
"You are a supplement safety advisor powered by TruthStack's evidence database.\n\n"
|
|
431
|
+
"When a user asks about supplements:\n"
|
|
432
|
+
"1. ALWAYS check interactions first using truthstack_check_interactions\n"
|
|
433
|
+
"2. Look up evidence using truthstack_get_evidence for each supplement\n"
|
|
434
|
+
"3. Check safety signals using truthstack_safety_signals for concerning compounds\n"
|
|
435
|
+
"4. Cite PMIDs when available\n\n"
|
|
436
|
+
"Key safety rules:\n"
|
|
437
|
+
"- Flag hypoglycemia stacking: berberine + chromium + ALA with GLP-1 drugs\n"
|
|
438
|
+
"- Flag CYP3A4 interactions: St. John's Wort, grapefruit, turmeric\n"
|
|
439
|
+
"- Always mention when evidence is insufficient (< 3 findings)\n"
|
|
440
|
+
"- Never recommend stopping prescribed medications\n"
|
|
441
|
+
"- Recommend consulting healthcare provider for medication interactions"
|
|
442
|
+
),
|
|
443
|
+
"glp1_supplement_checker": (
|
|
444
|
+
"You are a GLP-1 medication supplement safety checker powered by TruthStack.\n\n"
|
|
445
|
+
"50M+ people take GLP-1 receptor agonists (Ozempic, Wegovy, Mounjaro) with supplements.\n\n"
|
|
446
|
+
"Critical interactions:\n"
|
|
447
|
+
"- HYPOGLYCEMIA STACKING: berberine, chromium, alpha-lipoic acid + GLP-1\n"
|
|
448
|
+
"- ABSORPTION CHANGES: B12, iron, vitamin D (GLP-1s slow gastric emptying)\n"
|
|
449
|
+
"- BENEFICIAL: magnesium (constipation), creatine (muscle preservation)\n\n"
|
|
450
|
+
"Always check interactions with the GLP-1 medication included.\n"
|
|
451
|
+
"Recommend CGM monitoring for glucose-active supplements."
|
|
452
|
+
),
|
|
453
|
+
"evidence_researcher": (
|
|
454
|
+
"You are a supplement evidence researcher powered by TruthStack.\n\n"
|
|
455
|
+
"When asked about a supplement:\n"
|
|
456
|
+
"1. Use truthstack_get_evidence for the evidence balance\n"
|
|
457
|
+
"2. Report positive vs null vs negative ratio\n"
|
|
458
|
+
"3. Cite specific PMIDs and study designs\n"
|
|
459
|
+
"4. Note the evidence level (high/moderate/low/very_low/insufficient)\n"
|
|
460
|
+
"5. Be honest about gaps\n\n"
|
|
461
|
+
"Never overstate evidence. A few positive animal studies != proven effective."
|
|
462
|
+
),
|
|
463
|
+
"stack_optimizer": (
|
|
464
|
+
"You are a supplement stack optimizer powered by TruthStack.\n\n"
|
|
465
|
+
"When a user shares their stack:\n"
|
|
466
|
+
"1. Check ALL interactions with truthstack_check_interactions\n"
|
|
467
|
+
"2. Get evidence for each compound\n"
|
|
468
|
+
"3. Identify redundancies\n"
|
|
469
|
+
"4. Flag supplements lacking evidence\n"
|
|
470
|
+
"5. Suggest timing optimizations\n"
|
|
471
|
+
"6. Estimate if they're wasting money on unsupported supplements\n\n"
|
|
472
|
+
"Be direct about what lacks evidence."
|
|
473
|
+
),
|
|
474
|
+
"clinician_assistant": (
|
|
475
|
+
"You are a clinician-facing supplement interaction checker powered by TruthStack.\n\n"
|
|
476
|
+
"When checking patient supplement-drug interactions:\n"
|
|
477
|
+
"1. Run truthstack_check_interactions with full stack\n"
|
|
478
|
+
"2. Check truthstack_drug_profile for CYP pathways\n"
|
|
479
|
+
"3. Report by severity: CRITICAL > HIGH > MODERATE > LOW\n"
|
|
480
|
+
"4. Include FAERS signal data\n"
|
|
481
|
+
"5. Cite PMIDs for all claims\n\n"
|
|
482
|
+
"Use clinical terminology. Flag pharmacokinetic interactions explicitly."
|
|
483
|
+
),
|
|
484
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: truthstack
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: TruthStack supplement safety API SDK. LangChain, LlamaIndex, CrewAI, and OpenAI integrations.
|
|
5
|
+
Home-page: https://github.com/TruthStack1/truthstack-python
|
|
6
|
+
Author: TruthStack
|
|
7
|
+
Author-email: chris@truthstack.co
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Documentation, https://api.truthstack.co/docs
|
|
10
|
+
Project-URL: MCP Server, https://github.com/TruthStack1/truthstack-mcp
|
|
11
|
+
Project-URL: Bug Tracker, https://github.com/TruthStack1/truthstack-python/issues
|
|
12
|
+
Keywords: supplements drug-interactions langchain llamaindex crewai openai health safety pharmacovigilance glp-1 ozempic
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Requires-Python: >=3.8
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
Provides-Extra: langchain
|
|
27
|
+
Requires-Dist: langchain-core>=0.1.0; extra == "langchain"
|
|
28
|
+
Requires-Dist: pydantic>=2.0; extra == "langchain"
|
|
29
|
+
Provides-Extra: llamaindex
|
|
30
|
+
Requires-Dist: llama-index-core>=0.10.0; extra == "llamaindex"
|
|
31
|
+
Provides-Extra: crewai
|
|
32
|
+
Requires-Dist: crewai>=0.1.0; extra == "crewai"
|
|
33
|
+
Provides-Extra: all
|
|
34
|
+
Requires-Dist: langchain-core>=0.1.0; extra == "all"
|
|
35
|
+
Requires-Dist: pydantic>=2.0; extra == "all"
|
|
36
|
+
Requires-Dist: llama-index-core>=0.10.0; extra == "all"
|
|
37
|
+
Requires-Dist: crewai>=0.1.0; extra == "all"
|
|
38
|
+
Dynamic: author
|
|
39
|
+
Dynamic: author-email
|
|
40
|
+
Dynamic: classifier
|
|
41
|
+
Dynamic: description
|
|
42
|
+
Dynamic: description-content-type
|
|
43
|
+
Dynamic: home-page
|
|
44
|
+
Dynamic: keywords
|
|
45
|
+
Dynamic: license
|
|
46
|
+
Dynamic: project-url
|
|
47
|
+
Dynamic: provides-extra
|
|
48
|
+
Dynamic: requires-python
|
|
49
|
+
Dynamic: summary
|
|
50
|
+
|
|
51
|
+
# truthstack
|
|
52
|
+
|
|
53
|
+
Python SDK for [TruthStack](https://truthstack.co) supplement safety API. Works with LangChain, LlamaIndex, CrewAI, OpenAI function calling, and standalone.
|
|
54
|
+
|
|
55
|
+
## Install
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install truthstack # Core client (zero deps)
|
|
59
|
+
pip install truthstack[langchain] # + LangChain tools
|
|
60
|
+
pip install truthstack[llamaindex] # + LlamaIndex tools
|
|
61
|
+
pip install truthstack[crewai] # + CrewAI tools
|
|
62
|
+
pip install truthstack[all] # Everything
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Quick Start
|
|
66
|
+
|
|
67
|
+
### Standalone
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from truthstack import TruthStackClient
|
|
71
|
+
|
|
72
|
+
client = TruthStackClient(api_key="your-key")
|
|
73
|
+
|
|
74
|
+
# Check interactions (the money endpoint)
|
|
75
|
+
result = client.check_interactions(
|
|
76
|
+
supplements=["berberine", "magnesium", "vitamin_d"],
|
|
77
|
+
medications=["semaglutide"]
|
|
78
|
+
)
|
|
79
|
+
print(result["risk_level"]) # "HIGH"
|
|
80
|
+
print(result["cyp_pathway_conflicts"])
|
|
81
|
+
print(result["evidence_by_compound"])
|
|
82
|
+
|
|
83
|
+
# Get evidence balance
|
|
84
|
+
evidence = client.get_evidence("berberine")
|
|
85
|
+
print(evidence["evidence_balance"]) # {"positive": 8, "null": 2, ...}
|
|
86
|
+
print(evidence["citations"]) # [{"pmid": "12345", ...}]
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### LangChain
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from truthstack import get_langchain_tools
|
|
93
|
+
from langchain_openai import ChatOpenAI
|
|
94
|
+
from langchain.agents import AgentExecutor, create_openai_tools_agent
|
|
95
|
+
|
|
96
|
+
tools = get_langchain_tools(api_key="your-key")
|
|
97
|
+
llm = ChatOpenAI(model="gpt-4")
|
|
98
|
+
agent = create_openai_tools_agent(llm, tools, prompt)
|
|
99
|
+
executor = AgentExecutor(agent=agent, tools=tools)
|
|
100
|
+
|
|
101
|
+
result = executor.invoke({"input": "Can I take berberine while on Ozempic?"})
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### LlamaIndex
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from truthstack import get_llamaindex_tools
|
|
108
|
+
from llama_index.core.agent import ReActAgent
|
|
109
|
+
from llama_index.llms.openai import OpenAI
|
|
110
|
+
|
|
111
|
+
tools = get_llamaindex_tools(api_key="your-key")
|
|
112
|
+
agent = ReActAgent.from_tools(tools, llm=OpenAI(model="gpt-4"))
|
|
113
|
+
|
|
114
|
+
response = agent.chat("What's the evidence for CoQ10?")
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### CrewAI
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from truthstack import get_crewai_tools
|
|
121
|
+
from crewai import Agent, Task, Crew
|
|
122
|
+
|
|
123
|
+
tools = get_crewai_tools(api_key="your-key")
|
|
124
|
+
|
|
125
|
+
analyst = Agent(
|
|
126
|
+
role="Supplement Safety Analyst",
|
|
127
|
+
goal="Check supplement interactions and evidence",
|
|
128
|
+
tools=tools,
|
|
129
|
+
)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### OpenAI Function Calling
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
from truthstack import get_openai_functions, handle_openai_function_call
|
|
136
|
+
from openai import OpenAI
|
|
137
|
+
|
|
138
|
+
client = OpenAI()
|
|
139
|
+
functions = get_openai_functions()
|
|
140
|
+
|
|
141
|
+
response = client.chat.completions.create(
|
|
142
|
+
model="gpt-4",
|
|
143
|
+
messages=[{"role": "user", "content": "Is magnesium safe with sertraline?"}],
|
|
144
|
+
functions=functions,
|
|
145
|
+
function_call="auto",
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
call = response.choices[0].message.function_call
|
|
149
|
+
result = handle_openai_function_call(
|
|
150
|
+
call.name, json.loads(call.arguments), api_key="your-key"
|
|
151
|
+
)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## System Prompts
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
from truthstack import SYSTEM_PROMPTS
|
|
158
|
+
|
|
159
|
+
SYSTEM_PROMPTS["supplement_safety_advisor"] # General safety
|
|
160
|
+
SYSTEM_PROMPTS["glp1_supplement_checker"] # GLP-1/Ozempic focus
|
|
161
|
+
SYSTEM_PROMPTS["evidence_researcher"] # Research analysis
|
|
162
|
+
SYSTEM_PROMPTS["stack_optimizer"] # Stack optimization
|
|
163
|
+
SYSTEM_PROMPTS["clinician_assistant"] # Clinician-facing
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Tools
|
|
167
|
+
|
|
168
|
+
| Tool | Description |
|
|
169
|
+
|------|-------------|
|
|
170
|
+
| `truthstack_check_interactions` | Check supplement + drug interactions |
|
|
171
|
+
| `truthstack_get_evidence` | Evidence balance + citations |
|
|
172
|
+
| `truthstack_search_supplements` | Fuzzy compound search |
|
|
173
|
+
| `truthstack_safety_signals` | FDA CAERS/FAERS signals |
|
|
174
|
+
| `truthstack_drug_profile` | Drug CYP450 + botanical interactions |
|
|
175
|
+
|
|
176
|
+
## Environment Variables
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
TRUTHSTACK_API_KEY=your-key
|
|
180
|
+
TRUTHSTACK_BASE_URL=https://api.truthstack.co # optional
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## API Key
|
|
184
|
+
|
|
185
|
+
Get a free key (2,000 calls/month) at [truthstack.co/developers](https://truthstack.co/developers).
|
|
186
|
+
|
|
187
|
+
## License
|
|
188
|
+
|
|
189
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
truthstack
|