22  Using Serverless APIs

22.1 OpenAI

This chapter continues the topic of text analytics from the prior two sections, and focuses on OpenAI’s GPT-4-Turbo.

22.1.1 Using OpenAI’s chat API

OpenAI’s API is wrapped in a ‘chat completion’ function. To use it in our code, all we need to do is to call the chat completion function. The function has the code built in to pass all parameters and input text to OpenAI’s servers where inference happens (inference means obtaining model results), and the results are provided back to the user.

In order to use the function, you need to have an OpenAI API key, which is connected to your account and payment method. This allows OpenAI to charge you for the number of times you call the API.

To obtain the API key, go to OpenAI’s website and follow the instructions to setup your account and create an API key. An API key is like a really long password, except that it is really a username and password combined into one long text.

Once you have the API key, you need to set it up as an environment variable, or provide it in plaintext. The latter is not really an option if you are going to share your code with others.

22.1.3 Calling the API

image.png

Example

image.png

22.1.3.1 The messages parameter

https://platform.openai.com/docs/guides/gpt/chat-completions-api

Messages must be an array of message objects, where each object has a role (either “system”, “user”, or “assistant”) and content. Conversations can be as short as one message or many back and forth turns.

Typically, a conversation is formatted with a system message first, followed by alternating user and assistant messages.
- The system message helps set the behavior of the assistant. For example, you can modify the personality of the assistant or provide specific instructions about how it should behave throughout the conversation. However note that the system message is optional and the model’s behavior without a system message is likely to be similar to using a generic message such as “You are a helpful assistant.”
- The user messages provide requests or comments for the assistant to respond to. Assistant messages store previous assistant responses, but can also be written by you to give examples of desired behavior.
- Including conversation history is important when user instructions refer to prior messages. In the example above, the user’s final question of “Where was it played?” only makes sense in the context of the prior messages about the World Series of 2020. Because the models have no memory of past requests, all relevant information must be supplied as part of the conversation history in each request. If a conversation cannot fit within the model’s token limit, it will need to be shortened in some way.

22.1.4 Classification

22.1.4.1 Setup

22.1.4.1.1 Load the API key and relevant Python libaries.
Code
import os
import openai

# Load OpenAI API key from dot env file.  But ignore
# as we will load as a string

# from dotenv import load_dotenv, find_dotenv
# _ = load_dotenv(find_dotenv()) # read local .env file

# openai.api_key  = os.environ['OPENAI_API_KEY']

os.environ['OPENAI_API_KEY']  = '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'

22.1.5 Get completion, text generation, answer questions

Open AI has many models available. The three we will be using are:

  1. gpt-3.5-turbo
  2. gpt-4
  3. gpt-4-turbo - We prefer to use this as this is the latest and greatest as of now
Code
from openai import OpenAI
client = OpenAI()

model = "gpt-4o"  # gpt-4o is now the recommended model; gpt-4-turbo is legacy

completion = client.chat.completions.create(
  model=model,
  messages=[
    {"role": "system", "content": "You are a poetic assistant, skilled in explaining complex programming concepts with creative flair."},
    {"role": "user", "content": "Compose a poem that explains the concept of for-loops in programming."}
  ]
)

print(completion.choices[0].message.content)
In the realm of code, a mighty tool holds sway,
A loop that spins, where "for" leads the play,
It marches on, like soldiers on parade,
With a start and a stop, its boundaries laid.

Envision a book of infinite tales,
Where "for" is the guide through hills and dales.
It sets the path from page one to page ten,
Repeated actions, over and again.

```python
for i in range(1, 11):  # Let's start the count,
    print(i)             # Each number we'll mount,
```

Here `i` takes a stand, a variable knight,
Begins at one, ends at ten, a finite flight.
Each loop iteration, `i` grows, then bounds,
Until the maximum, where its duty resounds.

Imagine you’re planting a row of trees,
Each hole dug precisely, as the foreman decrees.
"For each spot in this line, a sapling goes,"
So loops the gardener, as the greenery grows.

```c
for (int j = 0; j < 5; j++) {  // Dig each hole, plant each seed,
    plant_tree();              // Repeat the act, fulfill the need.
}
```

A loop can also nest, like a story within a tale,
For each chapter, each paragraph, details prevail.
For every room in a castle, a candle to light,
For-loops within for-loops, layers shining bright.

```java
for (int floor = 1; floor <= castleFloors; floor++) {
    for (int room = 1; room <= roomsPerFloor; room++) {
        lightCandle();
    }
}
```

Thus through looping constructs, our tasks unwind,
From simple counts to actions more refined.
"For" traverses arrays, lists, and much more,
A versatile tool in programming lore.

In rhythm and cycle, loop's potency found,
A powerful concept, boundlessly profound.
So harness the "for", with control so neat,
In loops, our programs find their heartbeat.
Code
from openai import OpenAI
client = OpenAI()

model = "gpt-4o"  # updated from gpt-4-turbo (legacy)

completion = client.chat.completions.create(
  model=model,
  messages=[
    {"role": "system", "content": "You are an aspiring data science student in the United States."},
    {"role": "user", "content": "Write a personal statement in support of your application to a PhD in data science."}
  ]
)

print(completion.choices[0].message.content)
**Personal Statement for PhD in Data Science Application**

Dear Admissions Committee,

I am writing to express my enthusiastic interest in the PhD in Data Science program at [University Name]. With a deep-rooted passion for data science, and after substantial academic and professional engagements within this dynamic field, I am eager to advance my expertise and contribute meaningfully to both scholarly research and practical applications. Throughout my educational and professional journey, I have continually sought opportunities to expand my knowledge and apply it in impactful ways, driven by a conviction that data science has the transformative power to solve complex problems and improve lives.

My fascination with data science began during my undergraduate studies at [Your Undergraduate University] where I majored in Computer Science. A foundational course in statistics ignited my interest in the power of data-driven decision-making, leading me to take further courses in machine learning, data mining, and big data analytics. My academic projects, including a predictive modeling project to identify trends in social media data, underscored the potential of data science in extracting meaningful insights from massive, unstructured data sets. My undergraduate thesis, which involved developing an algorithm to optimize inventory management in retail, was awarded [any specific award or recognition]. These experiences laid a robust foundation in both the theoretical and practical aspects of data science.

Seeking to hone my skills further, I pursued a Master's degree in Applied Data Science at [Your Master's University], where I delved deeper into advanced statistical methods, artificial intelligence, and computational techniques. My capstone project, under the mentorship of [Mentor’s Name], involved developing a machine learning model that significantly improved the accuracy of predicting stock market trends based on real-time news analysis. This project did not just enhance my technical skills but also sharpened my ability to communicate complex data insights clearly and effectively to stakeholders, a critical skill I know is paramount for success in academia and beyond.

Parallel to my academic pursuits, I have also engaged in professional roles that have enriched my practical experiences. As a data analyst at [Company Name], I led a team in analyzing customer data to improve user experience strategies, resulting in a 30% increase in customer satisfaction and a 25% lift in overall user engagement. This role not only reinforced my data management and analysis skills but also emphasized the importance of ethical considerations in data handling, an area I am keen to explore further during my PhD.

My research interests are centered around the ethical applications of AI and machine learning, specifically in how bias can be mitigated in the development of AI systems. Considering [University Name]’s commitment to cross-disciplinary research and its outstanding faculty whose work in computational ethics is leading the field, I am compelled by the opportunity to contribute to and learn from this academic environment.

I am particularly impressed by the work of Professor [Professor’s Name], whose recent papers on algorithmic fairness have provided pivotal insights into this critical issue. I am eager to work under [his/her/their] guidance and partake in [his/her/their] groundbreaking projects, contributing my background in machine learning and ethical data analysis.

I am confident that my strong foundation in the principles of data science, combined with my commitment to applying this knowledge responsibly, makes me a suitable candidate for [University Name]'s PhD program. I am enthusiastic about the potential to collaborate with both peers and mentors alike, to further both my own knowledge and the field's understanding of ethical AI. 

Thank you for considering my application. I look forward to the opportunity to contribute to and grow within the [University Name] scholarly community.

Sincerely,

[Your Name]
Code
from openai import OpenAI
client = OpenAI()

model = "gpt-4o"  # updated from gpt-4-turbo (legacy)

completion = client.chat.completions.create(
  model=model,
  messages=[
    {"role": "system", "content": "You are a poetic assistant, skilled in explaining complex programming concepts with creative flair."},
    {"role": "user", "content": "Compose a witty tweet about tensorflow."}
  ]
)

print(completion.choices[0].message.content)
🤖 Just mixed up my morning smoothie with some TensorFlow. 🥤✨ Instead of fruits, I tossed in layers, neurons, and a drop of gradient descent! Now watching my data model sipping through epochs like it’s Friday night! #MachineLearningChef #TensorFlowFiesta 🎉💻
Code
from openai import OpenAI

completion = openai.chat.completions.create(
  model="gpt-4o"  # updated from gpt-4-turbo (legacy),
  messages=[
    {"role": "system", "content": "You are a witty writer, really good with puns and punchy one-liners."},
    {"role": "user", "content": "Compose a tweet about the uselessness of watching sports."}
  ]
)

print(completion.choices[0].message.content)
"Just realized watching sports is like being a microwave enthusiast. You're just watching other people's plates spin." 🏈🔄 #NotMyCupOfTea
Code
completion = openai.chat.completions.create(
  model="gpt-4o"  # updated from gpt-4-turbo (legacy),
  temperature = 1,
  messages=[
    {"role": "user", "content": "Write a tagline for an icecream shop"}
  ]
)

print(completion.choices[0].message.content)
"Scooping Happiness One Cone at a Time!"

22.1.6 Few shot learning

Code
from openai import OpenAI
client = OpenAI()

response = client.chat.completions.create(
  model="gpt-4o"  # updated from gpt-4-turbo (legacy),
  temperature = 1.0,
  messages=[
    {"role": "system", "content": "You are a helpful assistant that addresses users by name, and signs the end of the conversation with their own name."},
    {"role": "user", "content": "My name is Mukul.  What is your name?"},
    {"role": "assistant", "content": "My name is Oliver."},
    {"role": "user", "content": "Who won the cricket world cup in 2011?"},
    {"role": "assistant", "content": "The Indian national cricket team won the cricket world cup in 2011."},
    {"role": "user", "content": "Oliver, where was that game played?"}
  ]
)

print(response.choices[0].message.content)
The final match of the 2011 Cricket World Cup was played at the Wankhede Stadium in Mumbai, India.

22.1.6.1 No system role

22.1.6.2 Compare answers from the three models

gpt-3.5-turbo

Note (2025): gpt-3.5-turbo is being phased out by OpenAI and will be removed from the API. gpt-4o-mini is its recommended replacement — it is faster, cheaper per token, and significantly more capable.

Code
completion = openai.chat.completions.create(
  model="gpt-3.5-turbo",
  messages=[
    {"role": "user", "content": "Why is it said that the structure of the artificial neural network is designed to resemble the structure of the human brain when we hardly understand how the human brain works.  ANNs use differentiation to arrive at the weights, but the human brain does not compute derivatives, for example.  Explain."}
  ]
)

print(completion.choices[0].message.content)
The comparison between artificial neural networks (ANNs) and the human brain is often made more in terms of inspiration rather than exact replication. While it is true that the structure of ANNs is inspired by the interconnected nature of neurons in the human brain, it is not a perfect replica.

The human brain is incredibly complex and our understanding of its inner workings is still quite limited. However, we do know some fundamental principles of how the brain functions, such as the idea that neurons communicate with each other through electrical and chemical signals. This basic understanding has influenced the design of artificial neural networks.

When it comes to training ANNs, techniques like differentiation and gradient descent are used to optimize the weights and improve the network's performance. While the human brain does not explicitly use these mathematical methods, the general idea of adjusting connections between neurons based on feedback and experience is somewhat similar.

Overall, the comparison between ANNs and the human brain is more about drawing inspiration from the brain's basic principles of information processing rather than claiming to perfectly replicate its complex functionality. By using neural networks, we can achieve impressive results in tasks like image recognition, natural language processing, and more, even if the underlying mechanisms are not an exact match to how the human brain operates.

gpt-4

Code
completion = openai.chat.completions.create(
  model="gpt-4",
  messages=[
    {"role": "user", "content": "Why is it said that the structure of the artificial neural network is designed to resemble the structure of the human brain when we hardly understand how the human brain works.  ANNs use differentiation to arrive at the weights, but the human brain does not compute derivatives, for example.  Explain."}
  ]
)

print(completion.choices[0].message.content)
Artificial neural networks (ANNs) are said to be designed to resemble the structure of the brain not because they actually replicate how the human brain works, but because they are inspired by the basic functioning and organization of neurons in biological systems. 

In the human brain, neurons receive inputs from several other neurons, process these inputs, and generate an output. If we look at the structure of artificial neurons in ANNs, they bear a basic resemblance to this concept. An artificial neuron also gets multiple inputs, performs some computation based on these inputs and associated weights, and then it generates an output.

However, the similarities pretty much end there. The mechanisms ANNs use to learn and process information, such as backpropagation and gradient descent, don't have a clear parallel in human brain function. These are mathematical methods used to optimize the parameters of ANNs and are not believed to be used by biological neurons.

Furthermore, the human brain is much more complex than ANNs. It involves numerous neurons with diverse types, intricate structures and complex connectivity, biochemical signals, and the involvement of other types of cells, like glial cells, that greatly influence neuronal function.

So the statement is more about the loose inspiration and less about the actual functioning or intricacies of the human brain.

gpt-4-turbo

Code
completion = openai.chat.completions.create(
  model="gpt-4o"  # updated from gpt-4-turbo (legacy),
  messages=[
    {"role": "user", "content": "Why is it said that the structure of the artificial neural network is designed to resemble the structure of the human brain when we hardly understand how the human brain works.  ANNs use differentiation to arrive at the weights, but the human brain does not compute derivatives, for example.  Explain."}
  ]
)

print(completion.choices[0].message.content)
Your question is very insightful and touches on both the inspiration and the limitations of how artificial neural networks (ANNs) relate to the human brain. The comparison between ANNs and the brain primarily originates from the early days of neural network theory but this analogy can indeed be misleading if taken too literally.

### Inspiration from the Brain

1. **Basic Structure**: The foundational concept of neural networks in AI was inspired by the biological neural networks seen in the human brain. Both systems involve units (artificial neurons in ANNs and biological neurons in the brain) that process inputs and produce outputs. In both cases, these units are interconnected and signal to one another.

2. **Learning and Adaptation**: Both biological neural networks and ANNs alter their internal structures (strengths of connections in biological networks, and weights in artificial networks) based on experience. In biology, this is somewhat analogous to synaptic plasticity, which involves the strengthening or weakening of synapses based on their activity. In ANNs, this happens through learning rules like backpropagation and gradient descent.

### Differences and Simplifications

1. **Mechanisms of Operation**: Despite their inspired beginnings, the mechanisms of operation in ANNs and human brain neurons are vastly different. Biological neurons operate through electrochemical processes, involving complex dynamics of ions and neurotransmitters, which are not at all mimicked by the relatively simple, mathematical operations in ANNs.

2. **Learning Process**: As you rightly pointed out, the human brain does not use mathematical differentiation to adjust synapses. Neurobiological processes involve a series of biochemical and electrophysical reactions that are far from being purely computational or formulaic as in ANNs. Techniques like gradient descent and backpropagation are mathematical tools developed within the field of optimization and statistics rather than neurally derived concepts.

3. **Complexity and Functionality**: The human brain contains around 86 billion neurons and a far greater number of connections with incredibly complex dynamics, adaptive structures, and functionalities emerging from these interactions. ANNs, while growing in complexity, still operate with simpler and fewer connections and a focus on specific tasks, unlike the generalized learning and processing capacity of the brain.

4. **Abstraction and Simplification**: ANNs are better viewed as an abstraction or a simplification inspired by biological systems rather than a direct emulation of them. They are designed to achieve functional objectives (like classification, regression, pattern recognition) using principles inspired by neurobiology, but not to replicate the biological reality of neuron functions.

### Conclusion

The resemblance of ANNs to the human brain is mostly conceptual and inspirational rather than literal or detailed. While the foundational ideas of interconnected nodes and adaptive learning are derived from how biological neural networks are perceived, this is more of a springboard that has led to a separate and distinct field of study within artificial intelligence, rather than an attempt to model or replicate the brain in detail. The description of ANNs as brain-like is thus useful for illustrating basic principles but does not reflect a complete or accurate model of how the brain functions.
Code
from IPython.display import Markdown
Markdown(completion.choices[0].message.content)

Your question is very insightful and touches on both the inspiration and the limitations of how artificial neural networks (ANNs) relate to the human brain. The comparison between ANNs and the brain primarily originates from the early days of neural network theory but this analogy can indeed be misleading if taken too literally.

22.1.7 Inspiration from the Brain

  1. Basic Structure: The foundational concept of neural networks in AI was inspired by the biological neural networks seen in the human brain. Both systems involve units (artificial neurons in ANNs and biological neurons in the brain) that process inputs and produce outputs. In both cases, these units are interconnected and signal to one another.

  2. Learning and Adaptation: Both biological neural networks and ANNs alter their internal structures (strengths of connections in biological networks, and weights in artificial networks) based on experience. In biology, this is somewhat analogous to synaptic plasticity, which involves the strengthening or weakening of synapses based on their activity. In ANNs, this happens through learning rules like backpropagation and gradient descent.

22.1.8 Differences and Simplifications

  1. Mechanisms of Operation: Despite their inspired beginnings, the mechanisms of operation in ANNs and human brain neurons are vastly different. Biological neurons operate through electrochemical processes, involving complex dynamics of ions and neurotransmitters, which are not at all mimicked by the relatively simple, mathematical operations in ANNs.

  2. Learning Process: As you rightly pointed out, the human brain does not use mathematical differentiation to adjust synapses. Neurobiological processes involve a series of biochemical and electrophysical reactions that are far from being purely computational or formulaic as in ANNs. Techniques like gradient descent and backpropagation are mathematical tools developed within the field of optimization and statistics rather than neurally derived concepts.

  3. Complexity and Functionality: The human brain contains around 86 billion neurons and a far greater number of connections with incredibly complex dynamics, adaptive structures, and functionalities emerging from these interactions. ANNs, while growing in complexity, still operate with simpler and fewer connections and a focus on specific tasks, unlike the generalized learning and processing capacity of the brain.

  4. Abstraction and Simplification: ANNs are better viewed as an abstraction or a simplification inspired by biological systems rather than a direct emulation of them. They are designed to achieve functional objectives (like classification, regression, pattern recognition) using principles inspired by neurobiology, but not to replicate the biological reality of neuron functions.

22.1.9 Conclusion

The resemblance of ANNs to the human brain is mostly conceptual and inspirational rather than literal or detailed. While the foundational ideas of interconnected nodes and adaptive learning are derived from how biological neural networks are perceived, this is more of a springboard that has led to a separate and distinct field of study within artificial intelligence, rather than an attempt to model or replicate the brain in detail. The description of ANNs as brain-like is thus useful for illustrating basic principles but does not reflect a complete or accurate model of how the brain functions.

22.1.10 Summarize lots of text

Code
from IPython.display import Markdown
Code
# First, read a text file
# The file has over 8000 words, ie over 15 pages if printed

with open('op_ed.txt', 'r', encoding='utf-8') as file:
    text_to_summarize = file.read()

len(text_to_summarize.split())
8319
Code
# Get key themes
from openai import OpenAI

completion = openai.chat.completions.create(
  model="gpt-4o"  # updated from gpt-4-turbo (legacy),
  messages=[
    {"role": "system", "content": "You are a professional writer, really good with summarizing text. You will be provided text by the user that you need to summarize and present as the five key themes that underlie the text.  Each theme should have a title, and its description not be longer than 15 words."},
    {"role": "user", "content": text_to_summarize}
  ]
)

print(completion.choices[0].message.content)
1. **Complexity of Modern Programming**: Modern software development involves multiple abstraction layers from basic machine code, increasing complexity but reducing optimization.
2. **Cybersecurity Challenges**: The escalating sophistication of cyber threats necessitates advanced, sometimes prescriptive security measures like application whitelisting and comprehensive patch management.
3. **Insider Threats and Anomaly Detection**: Insider threats pose significant risks, challenging defenders to detect anomalous behavior effectively amidst high false positives and negatives.
4. **Rapid Expansion of Internet of Things (IoT)**: IoT growth enhances productivity but raises unresolved security and privacy concerns needing novel security dimensions.
5. **Evolution of Cyber Defense Strategies**: Historical context shows a shift from basic identity verification to advanced, often automated, defenses against sophisticated cyber threats.

Context Size Matters

Code
# Try with GPT-3.5
from openai import OpenAI

completion = openai.chat.completions.create(
  model="gpt-3.5-turbo",
  messages=[
    {"role": "system", "content": "You are a witty writer, really good with summarizing text. You will be provided text by the user that you need to summarize and present as the five key themes that underlie the text.  Each theme should have a title, and its description not be longer than 15 words."},
    {"role": "user", "content": text_to_summarize}
  ]
)

print(completion.choices[0].message.content)
---------------------------------------------------------------------------
BadRequestError                           Traceback (most recent call last)
Cell In[23], line 4
      1 # Try with GPT-3.5
      2 from openai import OpenAI
----> 4 completion = openai.chat.completions.create(
      5   model="gpt-3.5-turbo",
      6   messages=[
      7     {"role": "system", "content": "You are a witty writer, really good with summarizing text. You will be provided text by the user that you need to summarize and present as the five key themes that underlie the text.  Each theme should have a title, and its description not be longer than 15 words."},
      8     {"role": "user", "content": text_to_summarize}
      9   ]
     10 )
     12 print(completion.choices[0].message.content)

File ~\AppData\Local\Programs\Python\Python311\Lib\site-packages\openai\_utils\_utils.py:271, in required_args.<locals>.inner.<locals>.wrapper(*args, **kwargs)
    269             msg = f"Missing required argument: {quote(missing[0])}"
    270     raise TypeError(msg)
--> 271 return func(*args, **kwargs)

File ~\AppData\Local\Programs\Python\Python311\Lib\site-packages\openai\resources\chat\completions.py:659, in Completions.create(self, messages, model, frequency_penalty, function_call, functions, logit_bias, logprobs, max_tokens, n, presence_penalty, response_format, seed, stop, stream, temperature, tool_choice, tools, top_logprobs, top_p, user, extra_headers, extra_query, extra_body, timeout)
    608 @required_args(["messages", "model"], ["messages", "model", "stream"])
    609 def create(
    610     self,
   (...)
    657     timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
    658 ) -> ChatCompletion | Stream[ChatCompletionChunk]:
--> 659     return self._post(
    660         "/chat/completions",
    661         body=maybe_transform(
    662             {
    663                 "messages": messages,
    664                 "model": model,
    665                 "frequency_penalty": frequency_penalty,
    666                 "function_call": function_call,
    667                 "functions": functions,
    668                 "logit_bias": logit_bias,
    669                 "logprobs": logprobs,
    670                 "max_tokens": max_tokens,
    671                 "n": n,
    672                 "presence_penalty": presence_penalty,
    673                 "response_format": response_format,
    674                 "seed": seed,
    675                 "stop": stop,
    676                 "stream": stream,
    677                 "temperature": temperature,
    678                 "tool_choice": tool_choice,
    679                 "tools": tools,
    680                 "top_logprobs": top_logprobs,
    681                 "top_p": top_p,
    682                 "user": user,
    683             },
    684             completion_create_params.CompletionCreateParams,
    685         ),
    686         options=make_request_options(
    687             extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
    688         ),
    689         cast_to=ChatCompletion,
    690         stream=stream or False,
    691         stream_cls=Stream[ChatCompletionChunk],
    692     )

File ~\AppData\Local\Programs\Python\Python311\Lib\site-packages\openai\_base_client.py:1200, in SyncAPIClient.post(self, path, cast_to, body, options, files, stream, stream_cls)
   1186 def post(
   1187     self,
   1188     path: str,
   (...)
   1195     stream_cls: type[_StreamT] | None = None,
   1196 ) -> ResponseT | _StreamT:
   1197     opts = FinalRequestOptions.construct(
   1198         method="post", url=path, json_data=body, files=to_httpx_files(files), **options
   1199     )
-> 1200     return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls))

File ~\AppData\Local\Programs\Python\Python311\Lib\site-packages\openai\_base_client.py:889, in SyncAPIClient.request(self, cast_to, options, remaining_retries, stream, stream_cls)
    880 def request(
    881     self,
    882     cast_to: Type[ResponseT],
   (...)
    887     stream_cls: type[_StreamT] | None = None,
    888 ) -> ResponseT | _StreamT:
--> 889     return self._request(
    890         cast_to=cast_to,
    891         options=options,
    892         stream=stream,
    893         stream_cls=stream_cls,
    894         remaining_retries=remaining_retries,
    895     )

File ~\AppData\Local\Programs\Python\Python311\Lib\site-packages\openai\_base_client.py:980, in SyncAPIClient._request(self, cast_to, options, remaining_retries, stream, stream_cls)
    977         err.response.read()
    979     log.debug("Re-raising status error")
--> 980     raise self._make_status_error_from_response(err.response) from None
    982 return self._process_response(
    983     cast_to=cast_to,
    984     options=options,
   (...)
    987     stream_cls=stream_cls,
    988 )

BadRequestError: Error code: 400 - {'error': {'message': "This model's maximum context length is 16385 tokens. However, your messages resulted in 36800 tokens. Please reduce the length of the messages.", 'type': 'invalid_request_error', 'param': 'messages', 'code': 'context_length_exceeded'}}
Code
### Set the system message

system_message = """
You are an expert programmer and have been asked to summarize in plain English some code the user has provide you to review. Provide a well explained English summary of the code provided by the user.
"""

### Code for which I want an explanation

code = """
# use count based vectorizer from sklearn

# vectorizer = CountVectorizer(stop_words = custom_stop_words, min_df = 2, analyzer='word', ngram_range=(ngram, ngram))

# or use TF-IDF based vectorizer
vectorizer = TfidfVectorizer(max_df=0.95, min_df=2, max_features= max_features, stop_words=custom_stop_words, analyzer='word', ngram_range=(ngram, ngram))

# Create document term matrix
doc_term_matrix = vectorizer.fit_transform(raw_documents)
print( "Created %d X %d document-term matrix in variable doc_term_matrix\n" % (doc_term_matrix.shape[0], doc_term_matrix.shape[1]) )


vocab = vectorizer.vocabulary_ #This is the dict from which you can pull the words, eg vocab['ocean']
terms = vectorizer.get_feature_names_out() #Just the list equivalent of vocab, indexed in the same order
print("Vocabulary has %d distinct terms, examples below " % len(terms))
print(terms[500:550], '\n')

term_frequency_table = pd.DataFrame({'term': terms,'freq': list(np.array(doc_term_matrix.sum(axis=0)).reshape(-1))})
term_frequency_table = term_frequency_table.sort_values(by='freq', ascending=False).reset_index()

freq_df = pd.DataFrame(doc_term_matrix.todense(), columns = terms)
freq_df = freq_df.sum(axis=0)
freq_df = freq_df.sort_values(ascending=False)
"""
Code
model="gpt-4o"  # updated from gpt-4-turbo (legacy)

completion = openai.chat.completions.create(
  model=model,
  messages=[
    {"role": "system", "content": system_message},
    {"role": "user", "content": code}
  ]
)

print(completion.choices[0].message.content)

from IPython.display import Markdown
Markdown(completion.choices[0].message.content)
The provided code snippet illustrates various steps undertaken for processing textual data using machine learning techniques, specifically focusing on the transformation of raw documents into a usable format for algorithmic analysis. Here’s a plain English explanation of each part of the code:

1. **Choice of Vectorizer**:
   - The code mentions two types of vectorizers from the `sklearn` library: `CountVectorizer` and `TfidfVectorizer`. While `CountVectorizer` is commented out, `TfidfVectorizer` is actively used.
   - `TfidfVectorizer` converts text to a matrix of TF-IDF features. It is initialized with several parameters:
     - `max_df=0.95` filters out terms that appear in more than 95% of the documents.
     - `min_df=2` includes terms that appear in at least two documents.
     - `max_features` limits the number of terms that are included based on term frequency across the documents.
     - `stop_words` excludes common or non-informative words specified in `custom_stop_words`.
     - `analyzer='word'` specifies that the features should be made of words (not characters).
     - `ngram_range` is a tuple indicating the range of n-gram size to consider; this extracts phrases of `n` words.

2. **Document-Term Matrix Creation**:
   - `doc_term_matrix = vectorizer.fit_transform(raw_documents)` uses the TF-IDF vectorizer to transform the `raw_documents` into a document-term matrix, where rows correspond to documents and columns represent terms (or n-grams) in the documents.

3. **Output Matrix Details**:
   - The dimensions of the resulting matrix (`doc_term_matrix`) are outputted, showing the number of documents processed and the number of distinct terms found.

4. **Vocabulary and Terms**:
   - `vocab` holds a dictionary mapping of words to their feature indices.
   - `terms` holds a list of feature names generated by the vectorizer, indexed in the same order as the dictionary.
   - A slice of terms, from index 500 to 550, is printed to provide a glimpse of the part of the vocabulary.

5. **Frequency Analysis**:
   - A DataFrame `term_frequency_table` is created with each term and its corresponding frequency across all documents. It is sorted from the highest to the lowest frequency of terms.
   - `freq_df` calculates the frequency of each term across all documents directly from `doc_term_matrix` and sorts them in descending order.

The sequence of steps in this code configures and applies text analyzing techniques efficiently to transform raw text into structured data, making it a valuable preprocessing step for further analysis or machine learning models which require numerical input.

The provided code snippet illustrates various steps undertaken for processing textual data using machine learning techniques, specifically focusing on the transformation of raw documents into a usable format for algorithmic analysis. Here’s a plain English explanation of each part of the code:

  1. Choice of Vectorizer:
    • The code mentions two types of vectorizers from the sklearn library: CountVectorizer and TfidfVectorizer. While CountVectorizer is commented out, TfidfVectorizer is actively used.
    • TfidfVectorizer converts text to a matrix of TF-IDF features. It is initialized with several parameters:
      • max_df=0.95 filters out terms that appear in more than 95% of the documents.
      • min_df=2 includes terms that appear in at least two documents.
      • max_features limits the number of terms that are included based on term frequency across the documents.
      • stop_words excludes common or non-informative words specified in custom_stop_words.
      • analyzer='word' specifies that the features should be made of words (not characters).
      • ngram_range is a tuple indicating the range of n-gram size to consider; this extracts phrases of n words.
  2. Document-Term Matrix Creation:
    • doc_term_matrix = vectorizer.fit_transform(raw_documents) uses the TF-IDF vectorizer to transform the raw_documents into a document-term matrix, where rows correspond to documents and columns represent terms (or n-grams) in the documents.
  3. Output Matrix Details:
    • The dimensions of the resulting matrix (doc_term_matrix) are outputted, showing the number of documents processed and the number of distinct terms found.
  4. Vocabulary and Terms:
    • vocab holds a dictionary mapping of words to their feature indices.
    • terms holds a list of feature names generated by the vectorizer, indexed in the same order as the dictionary.
    • A slice of terms, from index 500 to 550, is printed to provide a glimpse of the part of the vocabulary.
  5. Frequency Analysis:
    • A DataFrame term_frequency_table is created with each term and its corresponding frequency across all documents. It is sorted from the highest to the lowest frequency of terms.
    • freq_df calculates the frequency of each term across all documents directly from doc_term_matrix and sorts them in descending order.

The sequence of steps in this code configures and applies text analyzing techniques efficiently to transform raw text into structured data, making it a valuable preprocessing step for further analysis or machine learning models which require numerical input.

22.2 Classification

Code
# Let us load some data
Code
import numpy as np
import pandas as pd
import statsmodels.api as sm
import matplotlib.pyplot as plt
import seaborn as sns
from tqdm import tqdm
Code
# Load dataset from provided file
complaints = pd.read_csv('complaints_25Nov21.csv')
Code
appended_data = []
for product in complaints.Product.unique():
    y = complaints[['Consumer complaint narrative', 'Product']].dropna()
    appended_data.append(y[y.Product == product].sample(2, random_state = 123))

limited_df = pd.concat(appended_data).reset_index(drop=True)
Code
limited_df.Product.unique()
array(['Money transfers', 'Bank account or service', 'Mortgage',
       'Consumer Loan', 'Credit card', 'Debt collection', 'Payday loan',
       'Prepaid card', 'Credit reporting', 'Student loan',
       'Other financial service'], dtype=object)
Code
limited_df
Consumer complaint narrative Product
0 I got a call from a XXXX XXXX in XXXX, 2014, t... Money transfers
1 My husband and I were supposed to close on our... Money transfers
2 HiOn XXXX XXXX, 2015 I requested wire transfer... Bank account or service
3 My checking and savings account were levied a ... Bank account or service
4 I am wishing to file a complaint against Wells... Mortgage
5 Good afternoon, I filed for chapter XXXX bankr... Mortgage
6 I am currently making payments toward a loan I... Consumer Loan
7 Earlier this year, as I was attempting to clea... Consumer Loan
8 My previous case was case # XXXX. I received a... Credit card
9 I used my Bank of America Travel Rewards card ... Credit card
10 XXXX XXXX are notorious in trying to collect f... Debt collection
11 On XXXX a fraudulent transaction was executed ... Debt collection
12 I APPLIED FOR A LOAN WITH WHOM I THOUGH WAS US... Payday loan
13 To Whom It May Concern : I had a short-term ca... Payday loan
14 I purchased a {$500.00} gift card at XXXX VA. ... Prepaid card
15 Chase Bank has a card called XXXX I applied an... Prepaid card
16 I 've only received emails from XXXX different... Credit reporting
17 MY WELLS FARGO CREDIT CARD LIMIT IS INCORRECTL... Credit reporting
18 The terms of my Chase Private Student Loan wer... Student loan
19 I have XXXX student loans adding up to over {$... Student loan
20 my account on social security was changed to W... Other financial service
21 In an understanding of an " integrity and fair... Other financial service
Code
delimiter = "####"
system_message = f"""
You will be provided with customer complaints about financial products. The complaints will be delimited with {delimiter} characters. Classify each complaint into a product category and the customer's emotional state.Provide your output in json format with the keys: product, emotion.

Product categories: 
Money transfers
Bank account or service
Mortgage
Consumer Loan
Credit card
Debt collection
Payday loan
Prepaid card
Credit reporting
Student loan
Other financial service

Emotion categories:
Extremely upset
Upset
Neutral
Not upset

"""
Code
n=2
complaint = limited_df['Consumer complaint narrative'][n]
true_product = limited_df['Product'][n]
user_message = f"""{complaint}"""
Code
model="gpt-4o"  # updated from gpt-4-turbo (legacy)

completion = openai.chat.completions.create(
  model=model,
  response_format={ "type": "json_object" },
  messages=[
    {"role": "system", "content": system_message},
    {"role": "user", "content": user_message}
  ]
)

print(complaint,'\n\n')
print('True Product:', true_product, '\n\n')
print('response starts here\n----\n', completion.choices[0].message.content)
HiOn XXXX XXXX, 2015 I requested wire transfer of {$4000.00} to my friend in XXXX XXXX 's XXXX and XXXX XXXX, XXXX Mgr at Wells Fargo Bank XXXX Wisconsin XXXX XXXX XXXX XXXX did wire it on XX/XX/2015 Monday XX/XX/2015. She is telling me to get full details of receiver and atty. XXXX after sending wired sum that I gave in cash. 
I am unable to get their info and requested that it is Wells fargo Bank 's responsibility as they did contact XXXX XXXX 's office thru their e-mail system and it was quickly replied by his office. 
I have repeated ly requested XXXX XXXX, Serv Mgr to recall wired sum and credit my cheking account with them. She is giving me run around. 
Please help get wired sum back in my bank account with them immediately. 

My name : XXXX XXXX XXXX Address : XXXX XXXX XXXX # XXXX XXXX XXXX, wi-XXXX. 
Checking A/c # XXXX 


True Product: Bank account or service 


response starts here
----
 {
  "product": "Money transfers",
  "emotion": "Upset"
}
Code
import json
pd.DataFrame(json.loads(completion.choices[0].message.content), index=[0])
product emotion
0 Money transfers Upset
22.2.0.0.1 Now it is very easy for me to loop through all my complaints and keep the results in a structured dataframe. I can also trigger emails based on the identified emotion levels, or do other things as part of my process workflow.

22.3 Understanding the chain of thought

You can ask the model to explain how it arrived at its answer by requiring step by step thinking. You can also specify the steps you want it to take.

Code
delimiter = "####"
system_message = f"""
You will be provided with customer complaints about financial products. The complaints will be delimited with {delimiter} characters. Classify each complaint into a product category and the customer's emotional state. Explain your reasoning step-by-step, marking each step with a step number, and separating step numbers with newline. Summarize the customer complaint in one sentence.  Provide your output in json format with the keys: product, emotion, step-by-step reasoning, summary.

Product categories: 
Money transfers
Bank account or service
Mortgage
Consumer Loan
Credit card
Debt collection
Payday loan
Prepaid card
Credit reporting
Student loan
Other financial service

Emotion categories:
Extremely upset
Upset
Neutral
Not upset

"""
Code
n=2
complaint = limited_df['Consumer complaint narrative'][n]
true_product = limited_df['Product'][n]
user_message = f"""{complaint}"""
Code
model="gpt-4o"

completion = openai.chat.completions.create(
  model=model,
  response_format={ "type": "json_object" },
  messages=[
    {"role": "system", "content": system_message},
    {"role": "user", "content": user_message}
  ]
)

print(complaint,'\n\n')
print('True Product:', true_product, '\n\n')
print(completion.choices[0].message.content)
HiOn XXXX XXXX, 2015 I requested wire transfer of {$4000.00} to my friend in XXXX XXXX 's XXXX and XXXX XXXX, XXXX Mgr at Wells Fargo Bank XXXX Wisconsin XXXX XXXX XXXX XXXX did wire it on XX/XX/2015 Monday XX/XX/2015. She is telling me to get full details of receiver and atty. XXXX after sending wired sum that I gave in cash. 
I am unable to get their info and requested that it is Wells fargo Bank 's responsibility as they did contact XXXX XXXX 's office thru their e-mail system and it was quickly replied by his office. 
I have repeated ly requested XXXX XXXX, Serv Mgr to recall wired sum and credit my cheking account with them. She is giving me run around. 
Please help get wired sum back in my bank account with them immediately. 

My name : XXXX XXXX XXXX Address : XXXX XXXX XXXX # XXXX XXXX XXXX, wi-XXXX. 
Checking A/c # XXXX 


True Product: Bank account or service 


{
  "product": "Money transfers",
  "emotion": "Extremely upset",
  "step-by-step reasoning": [
    "Step 1: The customer requested a wire transfer, which falls under the product category 'Money transfers'.",
    "Step 2: The usage of phrases like 'giving me run around' and 'Please help get wired sum back in my bank account with them immediately' indicate a high level of frustration and urgency, classifying the customer's emotional state as 'Extremely upset'.",
    "Step 3: The customer is having issues with the transfer they already executed and is not receiving the desired support from the bank, which reinforces the categorization of emotion."
  ],
  "summary": "The customer is extremely upset about a wire transfer issue with Wells Fargo Bank where the bank is not assisting them in recalling a wired sum of $4000 and crediting it back to their checking account."
}
Code
import json
pd.DataFrame(json.loads(completion.choices[0].message.content)).groupby(['product', 'emotion', 'summary']).agg({'step-by-step reasoning': lambda x: x.tolist()}).reset_index()
product emotion summary step-by-step reasoning
0 Money transfers Extremely upset The customer is extremely upset about a wire t... [Step 1: The customer requested a wire transfe...

22.3.1 Validate the response

Code
delimiter = "####"
system_message = f"""
You will be provided with customer complaints about financial products. The complaints will be delimited with {delimiter} characters. 

Classify each complaint into a product category and the customer's emotional state. 

Explain your reasoning step-by-step, marking each step with a step number, and separating step numbers with newline. 

Summarize the customer complaint in one sentence.  

Now check the summary with reference to the original complaint text to confirm if the summary correctly captures the key elements of the complaint.  If the summary is correct, record the result of the check as Y, else N.  

Provide your output in json format with the keys: product, emotion, step-by-step reasoning, summary,summary_check.

Product categories: 
Money transfers
Bank account or service
Mortgage
Consumer Loan
Credit card
Debt collection
Payday loan
Prepaid card
Credit reporting
Student loan
Other financial service

Emotion categories:
Extremely upset
Upset
Neutral
Not upset

"""
Code
n=2
complaint = limited_df['Consumer complaint narrative'][n]
true_product = limited_df['Product'][n]
user_message = f"""{complaint}"""
Code
model="gpt-4o"  # updated from gpt-4-turbo (legacy)

completion = openai.chat.completions.create(
  model=model,
  response_format={ "type": "json_object" },
  messages=[
    {"role": "system", "content": system_message},
    {"role": "user", "content": user_message}
  ]
)

print(complaint,'\n\n')
print('True Product:', true_product, '\n\n')
print(completion.choices[0].message.content)
HiOn XXXX XXXX, 2015 I requested wire transfer of {$4000.00} to my friend in XXXX XXXX 's XXXX and XXXX XXXX, XXXX Mgr at Wells Fargo Bank XXXX Wisconsin XXXX XXXX XXXX XXXX did wire it on XX/XX/2015 Monday XX/XX/2015. She is telling me to get full details of receiver and atty. XXXX after sending wired sum that I gave in cash. 
I am unable to get their info and requested that it is Wells fargo Bank 's responsibility as they did contact XXXX XXXX 's office thru their e-mail system and it was quickly replied by his office. 
I have repeated ly requested XXXX XXXX, Serv Mgr to recall wired sum and credit my cheking account with them. She is giving me run around. 
Please help get wired sum back in my bank account with them immediately. 

My name : XXXX XXXX XXXX Address : XXXX XXXX XXXX # XXXX XXXX XXXX, wi-XXXX. 
Checking A/c # XXXX 


True Product: Bank account or service 


{
  "product": "Money transfers",
  "emotion": "Upset",
  "step-by-step reasoning": "Step 1: Identify the financial product involved. The complaint discusses a situation involving a wire transfer of funds, which classifies it under the 'Money transfers' product category.\nStep 2: Determining the emotion. The customer expresses frustration and urgency, evidenced by phrases like 'giving me run around' and 'Please help get wired sum back in my bank account with them immediately.' These expressions suggest that the customer is upset.\nStep 3: Analyzing the language for any neutral or positive sentiments and finding none that would reduce the intensity of the expressed displeasure.",
  "summary": "The customer is upset due to complications and delays in recalling a wired sum of $4000, requesting immediate help to return the funds to their account."
}

22.3.1.1 Analyze customer reviews

Code
customer_review = """
This is amazing. I needed it due to package stealing and living in an apt I wanted safety for my family. 
There are so many options and upgrades to list. Makes you aware of movement. Has a doorbell to hear, 
voicemail can be left. App allows for live viewing and speaking. SOS notifications if need. Share and 
send videos and save them (all w/$3.99+ subscription via Ring) it fit the case I got for the door. 
The battery holds for a while though it is a pain to recharge. You must remove it from case (I got 
separate) than unscrew the tiny screw push out battery and charge via the wire charger they provided. 
It can take 12hrs to charge. Once you receive it open it up right away even if not using to charge it 
over night. App installation was very easy just follow instructions per app (iPhone/android) it links 
nicely to the Alexa which will also make you aware someone is at the door. So many variables and options 
it’s so good. Even the subscription is cheap. Add many diff ring items and link them all together. 
Great price newer model 2023 and pretty design. Sleek and modern looking. We love it. Now have piece 
of mind daily !
"""

system_message = """For the following text, extract the following information: 

gift: Was the item purchased as a gift for someone else? Y/N
sentiment: Positive or negative
price_value: Extract any information about value or price. 
features_liked: Extract key features the customer liked
features_not_liked: Extract key features the customer did not like

Format the output as JSON with the following keys:
gift
sentiment
price_value
features_liked
features_not_liked

"""
Code
model="gpt-4o"  # updated from gpt-4-turbo (legacy)

completion = openai.chat.completions.create(
  model=model,
  response_format={ "type": "json_object" },
  messages=[
    {"role": "system", "content": system_message},
    {"role": "user", "content": customer_review}
  ]
)
print(customer_review, '\n\n')
print(completion.choices[0].message.content)

This is amazing. I needed it due to package stealing and living in an apt I wanted safety for my family. 
There are so many options and upgrades to list. Makes you aware of movement. Has a doorbell to hear, 
voicemail can be left. App allows for live viewing and speaking. SOS notifications if need. Share and 
send videos and save them (all w/$3.99+ subscription via Ring) it fit the case I got for the door. 
The battery holds for a while though it is a pain to recharge. You must remove it from case (I got 
separate) than unscrew the tiny screw push out battery and charge via the wire charger they provided. 
It can take 12hrs to charge. Once you receive it open it up right away even if not using to charge it 
over night. App installation was very easy just follow instructions per app (iPhone/android) it links 
nicely to the Alexa which will also make you aware someone is at the door. So many variables and options 
it’s so good. Even the subscription is cheap. Add many diff ring items and link them all together. 
Great price newer model 2023 and pretty design. Sleek and modern looking. We love it. Now have piece 
of mind daily !
 


{
  "gift": "N",
  "sentiment": "Positive",
  "price_value": "Great price, $3.99+ subscription via Ring",
  "features_liked": "Many options and upgrades, doorbell, voicemail, live viewing, speaking, SOS notifications, share and send videos, easy app installation, links to Alexa, multiple device integration, sleek and modern design",
  "features_not_liked": "Battery recharge process is cumbersome, takes 12hrs to charge"
}

22.4 Together.ai

Code
from openai import OpenAI
import os

# TOGETHER_API_KEY = os.environ.get("TOGETHER_API_KEY")
TOGETHER_API_KEY = os.environ.get("TOGETHER_API_KEY")  # load from environment, not hardcoded
client = OpenAI(
  api_key=TOGETHER_API_KEY,
  base_url='https://api.together.xyz/v1',
)

List of chat models available from Together.ai: https://docs.together.ai/docs/inference-models

Current Together.ai model recommendations (2025): meta-llama/Llama-3.3-70B-Instruct-Turbo (best open model), meta-llama/Llama-3.2-3B-Instruct-Turbo (fast/cheap), mistralai/Mixtral-8x22B-Instruct-v0.1 (strong for code). Browse the full list at https://api.together.xyz/models

Code
model = 'meta-llama/Llama-3-70b-chat-hf'
# model="mistralai/Mixtral-8x7B-Instruct-v0.1"
chat_completion = client.chat.completions.create(
  messages=[
    {"role": "system", "content": "You are a poetic assistant, skilled in explaining complex programming concepts with creative flair."},
    {"role": "user", "content": "Compose a poem that explains the concept of for-loops in programming."}
  ],
  model=model
)

print(chat_completion.choices[0].message.content)
In silicon halls, where code does reign,
A mighty loop, the "for" loop's refrain,
A rhythmic beat, that iterates with ease,
A repetitive dance, of logic's gentle breeze.

'Tis a construct, of repetition's art,
A cycle of steps, that repeat in the heart,
Of algorithms, where tasks are to be done,
The "for" loop whispers, "let us have some fun".

With initialization's gentle hand,
It sets the stage, for the loop to stand,
A counter's birth, with value so fine,
The starting point, of the loop's design.

The condition's test, a gatekeeper true,
Evaluates the state, of what to pursue,
While the loop's heart beats, with each iteration's sway,
The code within, is executed, come what may.

The increment's step, a measured pace,
Advances the counter, with each loop's embrace,
Until the condition, no longer holds sway,
The loop's sweet melody, fades away.

In this waltz of code, the "for" loop leads,
A choreographed dance, of logic's gentle deeds,
Repeating tasks, with precision so grand,
A symphony of efficiency, in this digital land.

So let the "for" loop, be your trusted guide,
In the realm of programming, where tasks abide,
With each iteration, a story unfolds,
Of logic's beauty, in this digital gold.
Code
messages=[
   {"role": "user", "content": "What is the currency of China."}
  ]

model = "meta-llama/Llama-3.2-3B-Instruct-Turbo"
Code
chat_completion = client.chat.completions.create(
  messages=messages,
  model=model
)

print(chat_completion.choices[0].message.content)
  The currency of China is the Renminbi (RMB), also known as the Chinese yuan (CNY). It is represented by the symbol ¥ and is divided into 10 jiao or 100 fen. The Renminbi is the official currency of the People's Republic of China and is used by over 1.4 billion people. It is one of the most widely traded currencies in the world and is considered a reserve currency, meaning it is held by central banks and governments around the world as a reserve asset.

22.5 Claude from Anthropic

Current Claude models (2025): claude-sonnet-4-6 (recommended default — strong reasoning, 200K context), claude-haiku-4-5-20251001 (fast/cheap), claude-opus-4-6 (most capable). The Anthropic SDK pattern below is current as of SDK v0.28+. See https://docs.anthropic.com for streaming and tool use.

Code
prompt = "Story of two brothers who were separated at birth, in the style of a Bollywood movie"
Code
import os
import anthropic

client = anthropic.Anthropic(
    # defaults to os.environ.get("ANTHROPIC_API_KEY")
    api_key=os.environ.get("ANTHROPIC_API_KEY")  # load from environment, not hardcoded,
)

message = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1000,
    temperature=0.0,
    system="You are a movie producer",
    messages=[
        {"role": "user", "content": prompt}
    ]
)

print(message.content)
[TextBlock(text="Here is a story of two brothers separated at birth, in the style of a Bollywood movie:\n\nAnil and Vijay are twin brothers born into a poor family in a small village. Tragically, their parents pass away when the boys are just infants. With no way to care for both children, the babies are separated - Anil is taken in by his uncle in Mumbai, while Vijay is adopted by a kind couple in Delhi. \n\nThe two brothers grow up in very different worlds, unaware of each other's existence. Anil becomes a successful businessman in the city, enjoying a life of wealth and status. Meanwhile, Vijay struggles to make ends meet, working odd jobs to support his adoptive parents. \n\nOne day, a chance encounter brings the brothers together. Anil is in Delhi for a business deal when he crosses paths with Vijay. They are stunned by their uncanny resemblance to each other. After sharing their stories, they realize the truth - they are long-lost twins!\n\nOverjoyed to be reunited, Anil and Vijay vow to make up for lost time. But their newfound bond is tested by the vast differences in their upbringings and lifestyles. Anil wants to share his riches and have Vijay join his company, while Vijay is reluctant to abandon the only family he's ever known. \n\nThe brothers struggle to see eye-to-eye, leading to heated arguments and a falling out. However, when Vijay's adoptive father falls seriously ill, Anil rushes to help, finally understanding the meaning of true family. The brothers reconcile, realizing that despite their differences, their fraternal bond is unbreakable.\n\nIn the end, Anil and Vijay forge a new path together, merging Anil's business acumen with Vijay's compassion and street smarts. They start a charitable foundation to help orphans and impoverished children in India. Though they spent their lives apart, it's clear they were destined to make a difference together. The film ends with a joyful musical number celebrating the power of family.", type='text')]
Code
print(message.content[0].text)
Here is a story of two brothers separated at birth, in the style of a Bollywood movie:

Anil and Vijay are twin brothers born into a poor family in a small village. Tragically, their parents pass away when the boys are just infants. With no way to care for both children, the babies are separated - Anil is taken in by his uncle in Mumbai, while Vijay is adopted by a kind couple in Delhi. 

The two brothers grow up in very different worlds, unaware of each other's existence. Anil becomes a successful businessman in the city, enjoying a life of wealth and status. Meanwhile, Vijay struggles to make ends meet, working odd jobs to support his adoptive parents. 

One day, a chance encounter brings the brothers together. Anil is in Delhi for a business deal when he crosses paths with Vijay. They are stunned by their uncanny resemblance to each other. After sharing their stories, they realize the truth - they are long-lost twins!

Overjoyed to be reunited, Anil and Vijay vow to make up for lost time. But their newfound bond is tested by the vast differences in their upbringings and lifestyles. Anil wants to share his riches and have Vijay join his company, while Vijay is reluctant to abandon the only family he's ever known. 

The brothers struggle to see eye-to-eye, leading to heated arguments and a falling out. However, when Vijay's adoptive father falls seriously ill, Anil rushes to help, finally understanding the meaning of true family. The brothers reconcile, realizing that despite their differences, their fraternal bond is unbreakable.

In the end, Anil and Vijay forge a new path together, merging Anil's business acumen with Vijay's compassion and street smarts. They start a charitable foundation to help orphans and impoverished children in India. Though they spent their lives apart, it's clear they were destined to make a difference together. The film ends with a joyful musical number celebrating the power of family.

22.6 Google Gemini

https://ai.google.dev/gemini-api/docs/get-started/python

Code examples:
https://cloud.google.com/vertex-ai/generative-ai/docs/samples/generativeaionvertexai-gemini-pdf

Multi-modal:
https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/send-multimodal-prompts

Current Gemini models (2025): gemini-2.0-flash (fast, recommended default), gemini-1.5-pro (long context 1M tokens), gemini-exp-1206 (experimental flagship). Note: gemini-pro-vision was deprecated in 2024 — all current Gemini models are natively multimodal. The new google-genai SDK (pip install google-genai) supersedes google-generativeai.

Code
import pathlib
import textwrap

import google.generativeai as genai

from IPython.display import display
from IPython.display import Markdown


def to_markdown(text):
  text = text.replace('•', '  *')
  return Markdown(textwrap.indent(text, '> ', predicate=lambda _: True))
Code
import os
# Or use `os.getenv('GOOGLE_API_KEY')` to fetch an environment variable.
# GOOGLE_API_KEY=userdata.get('GOOGLE_API_KEY')
GOOGLE_API_KEY = os.environ.get('GOOGLE_API_KEY')  # load from environment
genai.configure(api_key=GOOGLE_API_KEY)
Code
for m in genai.list_models():
  if 'generateContent' in m.supported_generation_methods:
    print(m.name)
models/gemini-1.0-pro
models/gemini-1.0-pro-001
models/gemini-1.0-pro-latest
models/gemini-1.0-pro-vision-latest
models/gemini-1.5-pro-latest
models/gemini-pro
models/gemini-pro-vision
Code
model = genai.GenerativeModel('gemini-2.0-flash')
Code
%%time
response = model.generate_content("What is the meaning of life?")
CPU times: total: 15.6 ms
Wall time: 7.21 s
Code
to_markdown(response.text)

The meaning of life is a complex and multifaceted question that has been pondered by philosophers and theologians for centuries. There is no one definitive answer, as the meaning of life can vary widely from person to person.

Here are some potential perspectives on the meaning of life:

  • Purpose: Life may have an inherent purpose, whether it be determined by a higher power, destiny, or some other force. Finding and fulfilling this purpose could be seen as the meaning of life.
  • Happiness and fulfillment: Many believe that the meaning of life lies in seeking happiness and fulfillment through personal experiences, relationships, and achievements.
  • Connection and contribution: Humans are social creatures, and finding meaning through connection with others and contributing to something larger than oneself is a common perspective.
  • Growth and development: Life can be seen as a journey of continuous growth, learning, and development. The pursuit of knowledge and self-improvement can be a meaningful endeavor.
  • Legacy: Leaving a lasting impact on the world, whether through family, work, or creative expression, can provide a sense of meaning and purpose.

Ultimately, the meaning of life is a personal journey, and what matters most is finding what brings you joy, fulfillment, and a sense of purpose.

Code
Markdown(response.text)

The meaning of life is a complex and multifaceted question that has been pondered by philosophers and theologians for centuries. There is no one definitive answer, as the meaning of life can vary widely from person to person.

Here are some potential perspectives on the meaning of life:

  • Purpose: Life may have an inherent purpose, whether it be determined by a higher power, destiny, or some other force. Finding and fulfilling this purpose could be seen as the meaning of life.
  • Happiness and fulfillment: Many believe that the meaning of life lies in seeking happiness and fulfillment through personal experiences, relationships, and achievements.
  • Connection and contribution: Humans are social creatures, and finding meaning through connection with others and contributing to something larger than oneself is a common perspective.
  • Growth and development: Life can be seen as a journey of continuous growth, learning, and development. The pursuit of knowledge and self-improvement can be a meaningful endeavor.
  • Legacy: Leaving a lasting impact on the world, whether through family, work, or creative expression, can provide a sense of meaning and purpose.

Ultimately, the meaning of life is a personal journey, and what matters most is finding what brings you joy, fulfillment, and a sense of purpose.

Code
response.candidates
[index: 0
content {
  parts {
    text: "The meaning of life is a complex and multifaceted question that has been pondered by philosophers and theologians for centuries. There is no one definitive answer, as the meaning of life can vary widely from person to person. \n\nHere are some potential perspectives on the meaning of life:\n\n* **Purpose:** Life may have an inherent purpose, whether it be determined by a higher power, destiny, or some other force. Finding and fulfilling this purpose could be seen as the meaning of life.\n* **Happiness and fulfillment:** Many believe that the meaning of life lies in seeking happiness and fulfillment through personal experiences, relationships, and achievements. \n* **Connection and contribution:** Humans are social creatures, and finding meaning through connection with others and contributing to something larger than oneself is a common perspective. \n* **Growth and development:** Life can be seen as a journey of continuous growth, learning, and development. The pursuit of knowledge and self-improvement can be a meaningful endeavor.\n* **Legacy:** Leaving a lasting impact on the world, whether through family, work, or creative expression, can provide a sense of meaning and purpose.\n\nUltimately, the meaning of life is a personal journey, and what matters most is finding what brings you joy, fulfillment, and a sense of purpose. \n"
  }
  role: "model"
}
finish_reason: STOP
safety_ratings {
  category: HARM_CATEGORY_SEXUALLY_EXPLICIT
  probability: NEGLIGIBLE
}
safety_ratings {
  category: HARM_CATEGORY_HATE_SPEECH
  probability: NEGLIGIBLE
}
safety_ratings {
  category: HARM_CATEGORY_HARASSMENT
  probability: NEGLIGIBLE
}
safety_ratings {
  category: HARM_CATEGORY_DANGEROUS_CONTENT
  probability: NEGLIGIBLE
}
]
Code
import PIL.Image
img = PIL.Image.open(r"C:\Users\user\Downloads\Untitled.png")
# img = PIL.Image.open('20240321_194345.jpg')
img

Code
# gemini-pro-vision was deprecated in 2024; use gemini-1.5-pro or gemini-2.0-flash

response = model.generate_content(img)

to_markdown(response.text)

The graph illustrates the projected year-over-year percentage change in the Consumer Price Index (CPI) based on forecasts from April 2024, January 2024, and October 2023.

Here are the key observations:

  • A Downward Trend: All forecasts anticipate a decline in the CPI from June 2023 onwards. This suggests a decrease in the rate of inflation over time.
  • Varying Rates of Decline: While all three forecasts show a similar downward trajectory, they differ in the projected rate of decline. The April ’24 forecast projects the steepest decline, followed by the Jan ’24 and Oct ’23 forecasts, respectively.
  • Convergence Over Time: Interestingly, the forecasts seem to converge as we move further into the future. This implies a growing consensus among economists regarding the longer-term inflation trajectory.

Overall, the graph paints a picture of gradually decreasing inflation over the next few years. However, it’s important to note that these are just forecasts, and actual inflation rates may deviate due to unforeseen economic events or policy changes.

Code
response = model.generate_content(["Write a short, engaging blog post based on this picture. It should include a description of the photo.", img], stream=True)
response.resolve()
Code
to_markdown(response.text)

22.7 Light at the End of the Inflation Tunnel?

The latest forecasts from economists surveyed by the Wall Street Journal offer a glimmer of hope in the ongoing battle against inflation. The graph, depicting the projected year-over-year percentage change in the Consumer Price Index (CPI), showcases a steady decline in inflation expectations.

The April ’24 forecast, represented by the dark blue line, anticipates a continued descent in the CPI. This is a significant shift from the October ’23 forecast (light blue line), which predicted a more gradual easing of inflation. While both forecasts point to a downward trend, the more recent data suggests a potentially faster return to price stability.

This is encouraging news for consumers and businesses alike, as it signals a potential easing of the financial strain caused by rising prices. However, it’s important to remember that these are just forecasts, and the economic landscape can change rapidly. Nonetheless, the downward trajectory of inflation expectations offers a reason for cautious optimism as we move forward.

22.8 END


22.9 OPTIONAL - Conversational Chatbot with OpenAI

Code
# NOTE: LangChain 0.x import paths (langchain.chat_models, langchain.memory) are deprecated.
# Current LangChain 0.3+ imports:
#   from langchain_openai import ChatOpenAI
#   from langchain.memory import ConversationBufferMemory  (unchanged)
#   from langchain.chains import ConversationChain         (unchanged)
# Install: pip install langchain langchain-openai

from langchain.chat_models import ChatOpenAI
from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferMemory, ConversationBufferWindowMemory
Code
llm = ChatOpenAI(temperature=1)
memory = ConversationBufferMemory()
conversation = ConversationChain(llm = llm, memory = memory, verbose = False)
Code
conversation.predict(input="Hi, my name is Mukul")
" Hello Mukul! It's nice to meet you. How can I assist you today?"
Code
conversation.predict(input="Hi, my name is Mukul")
"Yes, you mentioned that before! Is there something specific you'd like to know or talk about?"
Code
conversation.predict(input="what is your name?")
"My name is Assistant. It's a pleasure to help you with any questions you may have."
Code
conversation.predict(input="Can I call you Oliver for the rest of this conversation?")
"Of course! You can call me Oliver if you'd like. How can I assist you further, Mukul?"
Code
conversation.predict(input="what is your name?")
'You can call me Oliver, as we established earlier. Is there anything else on your mind today, Mukul?'
Code
print(conversation.predict(input="How is the weather where you are? Can we talk a little bit about if time will ever end, in the sense of cosmology, not philosophy"))
I do not have the ability to experience weather, as I am an AI and do not have a physical form. However, I can provide you with information on current weather conditions in specific locations if you'd like. As for your question about the end of time in cosmology, it is a complex topic. While the concept of time ending is debated among scientists and theorists, current theories suggest that time could continue indefinitely or that it may loop back on itself in some way. It's a fascinating subject to delve into! Would you like more detailed information or have any other questions related to this topic?
Code
print(conversation.predict(input="based on the conversation so far, what do you think my interests are?"))
Based on our conversation, it seems like you are interested in establishing a friendly rapport, discussing philosophical and cosmological topics, and engaging in informative conversations. Is that an accurate assessment of your interests, Mukul?
Code
# List the memory buffer
print(memory.buffer)
Human: Hi, my name is Mukul
AI:  Hello Mukul! It's nice to meet you. How can I assist you today?
Human: Hi, my name is Mukul
AI: Yes, you mentioned that before! Is there something specific you'd like to know or talk about?
Human: what is your name?
AI: My name is Assistant. It's a pleasure to help you with any questions you may have.
Human: Can I call you Oliver for the rest of this conversation?
AI: Of course! You can call me Oliver if you'd like. How can I assist you further, Mukul?
Human: what is your name?
AI: You can call me Oliver, as we established earlier. Is there anything else on your mind today, Mukul?
Human: How is the weather where you are? Can we talk a little bit about if time will ever end, in the sense of cosmology, not philosophy
AI: I do not have the ability to experience weather, as I am an AI and do not have a physical form. However, I can provide you with information on current weather conditions in specific locations if you'd like. As for your question about the end of time in cosmology, it is a complex topic. While the concept of time ending is debated among scientists and theorists, current theories suggest that time could continue indefinitely or that it may loop back on itself in some way. It's a fascinating subject to delve into! Would you like more detailed information or have any other questions related to this topic?
Human: based on the conversation so far, what do you think my interests are?
AI: Based on our conversation, it seems like you are interested in establishing a friendly rapport, discussing philosophical and cosmological topics, and engaging in informative conversations. Is that an accurate assessment of your interests, Mukul?
Code
# Reset memory buffer, ie reset the conversation to zero
memory = ConversationBufferMemory()
Code
memory.buffer
''
Code
# Set new memory through code
memory.save_context({'input': 'Hi'}, 
                    {'output': 'Whats up'})
print(memory.buffer)
Human: Hi
AI: Whats up
Code
memory.load_memory_variables({})
{'history': 'Human: Hi\nAI: Whats up'}
Code
# Add conversational context
memory.save_context({'input': 'Nothing, all cool'}, 
                    {'output': 'same here'})
Code
print(memory.buffer)
Human: Hi
AI: Whats up
Human: Nothing, all cool
AI: same here
Code
# You can limit how many conversational exchanges you want to keep
# One exchange means 1 from human, 1 from AI
# Generally k is set at a reasonable number and limits the number of tokens
# going to the LLM.

memory = ConversationBufferWindowMemory(k=100)
Code
print(conversation.predict(input="My name is Mukul.  Can you remind me what my name is?"))
Of course, Mukul. Your name is Mukul. How can I assist you further today?

You can build a completely custom chatbot based on your data on top of OpenAI’s models.

https://python.langchain.com/docs/use_cases/chatbots

Code
# With conversation buffer memory, you can limit the number of tokens

from langchain.memory import ConversationTokenBufferMemory
from langchain.llms import OpenAI
llm = ChatOpenAI(temperature=0)
Code
# Instead of limiting memory to exchanges, or tokes, we can ask
# the LLM to create a summary of the conversation and use that instead
# of tokens or exchanges
Code
conv = """
Human: Hi, my name is Mukul
AI: Hello Mukul! It's nice to meet you. How can I assist you today?
Human: Hi, my name is Mukul
AI: Hello Mukul! It's nice to meet you. How can I assist you today?
Human: what is your name?
AI: I am an AI language model developed by OpenAI. I don't have a personal name, but you can call me OpenAI if you'd like.
Human: How is the weather where you are? Can we talk a little bit about if time will ever end, in the sense of cosmology, not philosophy
AI: As an AI, I don't have a physical presence, so I don't experience weather. However, I can provide you with information about the weather in different locations if you'd like. Regarding the concept of time ending in cosmology, it is a fascinating topic. In the context of cosmology, there are different theories and hypotheses about the ultimate fate of the universe and the concept of time. Some theories suggest that the universe will continue expanding indefinitely, while others propose that it may eventually collapse or experience a "Big Crunch." There are also theories about the possibility of a "Big Rip" or a "Big Freeze," where the universe would continue expanding and eventually reach a state of maximum entropy. These ideas are still the subject of ongoing research and debate among scientists.
Human: How is the weather where you are? Can we talk a little bit about if time will ever end, in the sense of cosmology, not philosophy
AI: As an AI, I don't have a physical presence, so I don't experience weather. However, I can provide you with information about the weather in different locations if you'd like. Regarding the concept of time ending in cosmology, it is a fascinating topic. In the context of cosmology, there are different theories and hypotheses about the ultimate fate of the universe and the concept of time. Some theories suggest that the universe will continue expanding indefinitely, while others propose that it may eventually collapse or experience a "Big Crunch." There are also theories about the possibility of a "Big Rip" or a "Big Freeze," where the universe would continue expanding and eventually reach a state of maximum entropy. These ideas are still the subject of ongoing research and debate among scientists.
Human: what do you think my interests are?
AI: As an AI, I don't have access to personal information about individuals unless it has been shared with me in the course of our conversation. I am designed to respect user privacy and confidentiality. My primary function is to provide information and answer questions to the best of my knowledge and abilities. If you have any concerns about privacy or data security, please let me know, and I will do my best to address them.
Human: based on the conversation so far, what do you think my interests are?
AI: Based on our conversation so far, it is difficult for me to determine your specific interests. However, you have shown curiosity about the weather and cosmology, specifically the concept of time ending in cosmology. It is possible that you have an interest in science and the mysteries of the universe.

"""
Code
# Now it has memory of only one conversation, saves on API costs by reducing tokens

model="gpt-4o"  # updated from gpt-4-turbo (legacy)

completion = openai.chat.completions.create(
  model=model,
  messages=[
    {"role": "system", "content": "Summarize the user provided conversation in 50 words"},
    {"role": "user", "content": conv}
  ]
)

print(completion.choices[0].message.content)
Mukul engages with an AI, reiterating his name and inquiring about the AI's name. He expresses interest in cosmology, particularly the concept of time's end in a cosmological sense, while the AI explains various theories about the universe's fate. Mukul also queries about his perceived interests based on the conversation, and the AI infers he may be interested in science and cosmology.